fix(ssh): prevent OS command injection via ssh key and username (CTO-5387) - #113
Open
yash-atwal wants to merge 1 commit into
Open
yash-atwal wants to merge 1 commit into
yash-atwal wants to merge 1 commit into
Conversation
…5387)
The SSH access module built remote shell commands by string-formatting
requester-controlled values — the submitted SSH public key and the derived
username — directly into fabric connection.sudo() calls (e.g.
`echo "{}" | sudo tee -a /home/{}/.ssh/authorized_keys`). With only an
empty-string check on the key, a requester could embed shell metacharacters
($(...), backticks, ;) that execute as root on the target host once the
request is approved. Second-order OS command injection, CWE-78, CVSS 9.0
(GHSA-grpj-9ghj-xhv8).
Fix (defence in depth):
- Sink: shlex.quote every interpolated value (ssh key, username, derived
paths, sed expression) in add_user, add_key_existing_user and
replace_user_key. This is the complete fix — quoted payloads can no longer
break out of their shell token.
- Source: validate the SSH public key against a strict OpenSSH grammar in
SSHAccess.verify_identity, and validate the username against a Linux
login-name allow-list in sshHelper/replace_user_key, so malformed input is
rejected before any connection is opened.
- sed metacharacters are now escaped for correctness (shell safety comes from
shlex.quote on the whole expression).
Adds ssh/test_ssh_injection.py covering the validators, verify_identity, the
dispatcher reject paths, and sink-level quoting (payload cannot fire even if
validation is bypassed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Central YAML (base), Organization UI (inherited), Workspace UI (inherited) Review profile: ASSERTIVE Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a second-order OS command injection (CWE-78, CVSS 9.0) in the SSH access module — CTO-5387 / GHSA-grpj-9ghj-xhv8.
ssh/helpers.pybuilt remote shell commands by string-formatting requester-controlled values — the submitted SSH public key and the derived username — directly intofabricconnection.sudo()calls, e.g.:The only check was an empty-string test on the key. A requester (a normal, low-privilege authenticated action) could embed
$(...), backticks or;in thessh_pub_key/ username fields; on approval the payload executed as root/sudo on every host the automation identity manages.Fix — defence in depth
1. Sink hardening (the complete fix) —
shlex.quote()every interpolated value (ssh key, username, derived/home/<user>/…paths, and thesedexpression) inadd_user,add_key_existing_user, andreplace_user_key. Quoted payloads can no longer break out of their shell token.2. Source validation (defence in depth)
SSHAccess.verify_identity()now rejects anything that isn't a single, well-formed OpenSSH public key line (strict<type> <base64> [comment]grammar; no newlines).sshHelper()/replace_user_key()reject usernames that aren't valid Linux login names — before any connection is opened.sedregex metacharacters are escaped for correctness (shell safety comes fromshlex.quoteon the whole expression).Tests
Adds
ssh/test_ssh_injection.py(31 cases): validators,verify_identity, dispatcher reject-paths, and sink-level quoting — asserting the$(...)payload cannot fire even if validation is bypassed.Verified locally two ways: (a) full test suite green; (b) a standalone harness that executes the generated commands through a real shell confirms no marker file is created by any attack path, while a benign key still works.
Risk / compatibility