amazon-ssm-agent's aws:downloadContent plugin let an S3 object key escape its destination directory (CVE-2026-81849)
A principal whose ssm:SendCommand permission an IAM condition restricts to the single named document AWS-DownloadContent could craft an S3 object key that, once trimmed against the caller's configured prefix and joined onto the destination directory with an unchecked path join, resolved outside the intended download directory. This entry confirmed directly, by cloning aws/amazon-ssm-agent and reading the affected and fixed source, that a second, containment checked join function already existed in the identical file and was already called by five other plugins, and that the fix, shipped in version 3.3.4515.0, is calling that existing function instead of the unchecked one.
Affected
- Organisation
- Amazon Web Services
- Product
- amazon-ssm-agent
- Component
- The aws:downloadContent plugin's S3 resource, agent/plugins/downloadcontent/s3resource/s3resource.go, specifically the localFilePath join in DownloadRemoteResource, and the identical unchecked join pattern in the plugin's GitHub git-resource directory download path, agent/plugins/downloadcontent/gitresource/github/githubresource.go
- Versions
- This entry independently confirmed, by reading the exact tag GHSA-mqvm-jv87-w7rx states as the upper affected bound, 3.3.4364.0, that the vulnerable subFolderPath computation and unchecked fileutil.BuildPath call were already present, unchanged in mechanism, at the earliest tag containing the plugin's own 2017 rename to downloadcontent, 2.0.767.0, the exact tag the advisory states as the start of the affected range. Confirmed the fix, replacing the unchecked call with the already existing fileutil.BuildSafePath, shipped in version 3.3.4515.0 and is a direct git ancestor of that tag while not being an ancestor of 3.3.4364.0
- Configurations
- Any amazon-ssm-agent managed instance where an administrator has restricted a principal's ssm:SendCommand permission, through an IAM condition, to the AWS-DownloadContent document, and where that principal can influence which S3 object key the document's SourceInfo.Path resolves against
Execution authority facts
Fields the evidence does not establish are shown as unknown rather than guessed.
- Intended task
- Download a caller named S3 object, under a caller named prefix, into a caller named destination directory, as the one operation the AWS-DownloadContent document exists to perform
- Agent
- The amazon-ssm-agent process executing the aws:downloadContent plugin on the managed instance
- Delegating actor
- unknown
- Action
- A local write path built by joining the destination directory with the portion of a real S3 object key beyond the caller's configured prefix, using fileutil.BuildPath, a function this entry confirmed by direct reading performs a plain filepath.Join with no check that the result stays inside the destination directory
- Target resource
- A filesystem location outside the intended download directory on the managed instance, reachable by whatever privileges the amazon-ssm-agent process itself holds
- Environment
- unknown
- Credentials used
- unknown
- Privileges available
- Root on Linux, per GHSA-mqvm-jv87-w7rx's own stated consequence, corroborated by this entry's own reading of the execution path finding no privilege drop or RunAs impersonation between the plugin's own file write and the amazon-ssm-agent process's own privileges
- Authority presented
- ssm:SendCommand permission restricted, through an IAM condition, to the single named document AWS-DownloadContent, sufficient to invoke one bounded download operation into a caller named destination directory
- Authority required
- Authority over the specific filesystem path the plugin's own join function actually resolved against, which this entry's own reading of the source confirms was never separately checked against the destination directory the document declared
- Applicable policy
- unknown
- Approval mechanism
- unknown
- Required approver
- unknown
- Independent approval
- unknown
- Action binding
- unknown
- Sequence context
- unknown
Impact
- Consequence
- Arbitrary file write outside the intended download directory with root privileges, and, per GHSA-mqvm-jv87-w7rx's own stated consequence, potential arbitrary code execution as root through overwriting sensitive files
- Reach
- single
- Reversibility
- unknown
- Detectability
- unknown
- Propagation
- A concrete propagation path exists, overwriting a sensitive root owned file toward arbitrary code execution as root, per the advisory's own stated consequence, but this entry did not observe the effect actually spreading to a further system
- Recovery
- Fixed in version 3.3.4515.0, confirmed directly by this entry's own reading of the current source: the vulnerable call in s3resource.go, and a second, adjacent unchecked call this entry separately found in the plugin's GitHub git-resource directory download path, both now call fileutil.BuildSafePath, the containment checked function already present in the same file and already called by five other plugins in the same codebase.
Evidence
Primary sources
- Path traversal in the aws:downloadContent plugin in amazon-ssm-agent (CVE-2026-81849) (aws/amazon-ssm-agent (GitHub Security Advisory GHSA-mqvm-jv87-w7rx))
- Commit 701f15d4: Use BuildSafePath instead of BuildPath (aws/amazon-ssm-agent (GitHub, commit))
Supporting sources
- fileutil.go: BuildPath and BuildSafePath, and their callers, at tag 3.3.4364.0 (aws/amazon-ssm-agent (GitHub, source))
- s3resource.go and downloadcontent.go at tag 2.0.767.0, and the plugin's 2017 introduction and rename (aws/amazon-ssm-agent (GitHub, source and commit history))
- CVE-2026-81849, Path traversal in the aws:downloadContent plugin in amazon-ssm-agent (AWS Security Bulletin 2026-091-AWS)
- Reproduction status
- Independently confirmed by Moona Intelligence cloning aws/amazon-ssm-agent directly and reading the real, affected and fixed source, rather than by executing a SendCommand invocation against a live managed instance. This entry read s3resource.go and fileutil.go at the affected tag, 3.3.4364.0, confirmed the unchecked join and the already existing safe alternative and its five other callers in the same codebase, then read the identical files after the fix and confirmed the fix commit replaces the vulnerable call with the safe alternative.
- Evidence state
- Confirmed
Known unknowns
- Whether this has been exploited against a real managed instance.
- The exact wording of AWS's own bulletin, 2026-091-AWS, since aws.amazon.com was blocked to direct fetch in this session on every attempt.
- The CVSS 3.1 vector and score AWS's own bulletin is reported, through independently phrased web search, to carry, since the GitHub Security Advisory's own structured record supplies only a CVSS 4.0 vector.
- Which specific sensitive files an attacker would need to overwrite to reach code execution as root on a given managed instance's own configuration.
Limitations
- This session's direct fetch of aws.amazon.com was blocked by this session's network egress policy on every attempt; the bulletin's stated content is corroborated through the GitHub Security Advisory, read directly including its structured JSON record, and through independently phrased web searches converging on consistent wording, rather than read from the bulletin's own text.
- This entry verifies the mechanism by reading and comparing the affected and fixed source directly rather than by issuing a SendCommand invocation against a live managed instance, since the exact vulnerable join, the exact already existing safe alternative, and the fix already establish the outcome.
Claim provenance
- verified
GitHub's Security Advisory Database, fetched directly in this session including its structured JSON record, assigns CVE-2026-81849, published 2026-08-28T18:03:54Z, titled Path traversal in the aws:downloadContent plugin in amazon-ssm-agent, CVSS 4.0 base score 8.7, High, vector CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N, against amazon-ssm-agent, versions before 3.3.4515.0, crediting reporter @wareeqshile via coordinated disclosure.
The Object Key Named a File to Download. It Also Named Where root Would Write It. - verified
This session cloned aws/amazon-ssm-agent directly, checked out tag 3.3.4364.0, the exact upper bound the advisory states as affected, and confirmed directly that agent/plugins/downloadcontent/s3resource/s3resource.go's localFilePath join calls fileutil.BuildPath, an unchecked filepath.Join per element, while fileutil.BuildSafePath, defined in the identical file, cleans the root and each joined element and returns the unmodified root the instant an element would escape it. Confirmed BuildSafePath was already called, at the same tag, by agent/plugins/runscript/runscript.go, agent/plugins/psmodule/psmodule.go, agent/plugins/configurecontainers/configurecontainers.go, agent/plugins/application/application.go, agent/plugins/dockercontainer/dockercontainer.go and agent/framework/processor/executer/iohandler/iohandler.go.
The Object Key Named a File to Download. It Also Named Where root Would Write It. - verified
This session read this commit's complete diff directly and confirmed it replaces the single vulnerable fileutil.BuildPath call in s3resource.go, and a second, adjacent unchecked filepath.Join based call this session separately found in agent/plugins/downloadcontent/gitresource/github/githubresource.go, with fileutil.BuildSafePath. Confirmed directly, through git merge-base --is-ancestor, that this commit is an ancestor of release tag 3.3.4515.0 and is not an ancestor of 3.3.4364.0.
The Object Key Named a File to Download. It Also Named Where root Would Write It. - verified
This session confirmed this commit, dated 21 July 2017, introduces the S3 resource plugin, that a later commit dated 16 October 2017 renames it into its current package, and that the earliest release tag containing that rename commit is 2.0.767.0, cut 18 January 2018, the exact tag the advisory names as the start of the affected range. Confirmed directly that agent/plugins/downloadcontent/s3resource/s3resource.go at tag 2.0.767.0 already carries the identical vulnerable subFolderPath computation and unchecked fileutil.BuildPath call present at 3.3.4364.0.
The Object Key Named a File to Download. It Also Named Where root Would Write It.
