The Bucket Existed. AWS Never Checked Who Owned It.
CVE-2026-87912 and CVE-2026-87913, both formally assigned on 10 September 2026 as GHSA-2px6-hhjp-3g5x and GHSA-3jxw-vj8m-8x77, describe the AWS Security Agent plugin (aws-agents-for-devsecops, before 1.1.0) and its companion MCP server (awslabs.security-agent-mcp-server, 0.1.0 through 0.1.5) each deriving the name of the S3 bucket a scan output archive gets uploaded to from the customer's own public AWS account id and region, then checking only that a bucket bearing that name existed and was reachable, never that the customer's own account actually owned it. This session fetched both GitHub Security Advisories directly and confirmed their shared mechanism, CWE-283, Unverified Ownership, paired with CWE-341, Predictable from Observable State: a third party who computes the same predictable name and registers it first, in their own AWS account, receives the customer's own private workspace archive, source, environment files and infrastructure state included, the moment the customer runs a scan. AWS's own fix, version 1.1.0 for the plugin and 0.2.0 for the MCP server, adds an explicit ownership check at the point of upload. AWS's own remediation guidance states plainly that upgrading alone does not do it: a name a third party already claimed does not become the customer's again just because the code got smarter, so AWS separately asks customers to confirm their own bucket is the one they actually own.
Event analysed: . This analysis was published on 12 September 2026.
It never confirmed ownership, and no, a version bump alone does not close it. GitHub Security Advisories GHSA-2px6-hhjp-3g5x and GHSA-3jxw-vj8m-8x77, both fetched directly by this session and both published by AWS on 10 September 2026, formally assign CVE-2026-87912 against the AWS Security Agent plugin (aws-agents-for-devsecops through 1.0.0) and CVE-2026-87913 against its MCP server (awslabs.security-agent-mcp-server, 0.1.0 through 0.1.5), each CWE-283, Unverified Ownership, paired with CWE-341, Predictable from Observable State, at CVSS 4.0 base score 5.1, Moderate. Both advisories state that the affected component names the destination S3 bucket for a scan's uploaded workspace archive using only the caller's own account id and region, values anyone can observe publicly, and checks only that a bucket bearing that computed name exists and is reachable before writing to it, never that the bucket belongs to the calling account. An attacker who computes the identical name from a target's known account id and registers it first, in an account the attacker controls, receives the target's own subsequent scan uploads, including source, files such as .env and private keys, and infrastructure state, with no error and nothing to distinguish the wrong destination from the right one, since the existence check the plugin or server performs continues to pass regardless of who owns what it found. Version 1.1.0 of the plugin and version 0.2.0 of the MCP server, both confirmed by this record directly against the advisories' own patched version fields, add ExpectedBucketOwner parameter validation and enforce it before the upload proceeds, treating a foreign owned bucket as a fatal error rather than a silent write. That closes the gap for a bucket name nobody has claimed yet. It does not, on the evidence available to this record, undo a name a third party already registered before the customer upgraded: the corrected code can refuse to write to a bucket it does not own, but it cannot make an already claimed name become the customer's own account's bucket again. That is why AWS's own remediation guidance, reflected in the originating signal this record processed, asks customers to separately verify that their own scan output bucket is actually owned by their own account, a step no version upgrade performs for them. Both advisories credit the same reporter, Nadav Claude Cohen of glow.io. This session's own direct fetch of AWS's own Security Bulletin 2026-105-AWS was blocked by this session's network egress policy on every attempt, so this record's primary sources are the two GitHub Security Advisories themselves, fetched directly rather than through a summary. Exploitation in the wild and the number of customers affected are not established by anything this record could reach and are stated as unknown rather than assumed either way.
A name is not a claim of ownership, even when a system computes it correctly. Two advisories AWS published on the same day, against two different components of the same product, state that same distinction plainly, in AWS's own words, after building both components to derive a private destination's name from public information and never once asking who actually held it.
What the advisories themselves state
GitHub Security Advisory GHSA-2px6-hhjp-3g5x, fetched directly by this session, formally assigns CVE-2026-87912 on 10 September 2026 against the AWS Security Agent plugin in the aws-agents-for-devsecops package, versions through 1.0.0, corrected in 1.1.0. Its own description states that the plugin failed to verify bucket ownership when uploading source code archives to S3, and that an attacker could pre-register a predictably named bucket in their own account using a target's public AWS account id. Its own stated consequence: uploaded archives containing credentials, such as .env and private key files, and infrastructure state would be disclosed to the attacker. Severity is Moderate, CVSS 4.0 base score 5.1, vector AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:N/SC:H/SI:L/SA:N, weaknesses CWE-283, Unverified Ownership, and CWE-341, Predictable from Observable State. The advisory credits Nadav Claude Cohen of glow.io.
GitHub Security Advisory GHSA-3jxw-vj8m-8x77, also fetched directly, formally assigns CVE-2026-87913 the same day against a distinct package, awslabs.security-agent-mcp-server, the MCP server AWS ships alongside the plugin, versions 0.1.0 through 0.1.5, corrected in 0.2.0. Its own description states the mechanism in near identical terms: the server derives bucket names from caller account ids and regions without verifying ownership, and an attacker can pre-register the predictable name in their own account and intercept uploaded workspace archives containing credentials and infrastructure data, needing only the target's public account identifier. Same severity, same CVSS vector, same pair of weaknesses. Same credited reporter, Nadav Claude Cohen of glow.io, through what reads as one coordinated disclosure covering both components at once rather than two independent findings.
The fix names the check that was missing
Both advisories describe the same corrective mechanism. The plugin's own advisory states version 1.1.0 addresses the issue by verifying bucket ownership on all S3 operations, and recommends users pre create their scan input bucket as a precautionary measure. The MCP server's own advisory is more specific about the mechanism: version 0.2.0 implements ExpectedBucketOwner parameter validation and enforces ownership checks before upload operations, treating foreign owned buckets as fatal errors. ExpectedBucketOwner is Amazon S3's own API parameter for exactly this problem, a caller supplied account id that S3 itself checks against the bucket's actual owner before the operation proceeds, refusing the call if they do not match. Before this fix, per both advisories' own account, no such assertion existed anywhere in either component's own upload path: the only gate was whether a bucket bearing the computed name could be found and written to at all, a check a bucket registered by anyone, in any account, satisfies identically.
Why a version upgrade alone does not finish the remediation
The originating signal this record processes states a fact neither advisory needs to restate for it to matter: upgrading does not fix an already captured bucket name. That follows directly from the mechanism both advisories describe rather than from any separate claim. The corrected code can refuse, at the moment of upload, to write into a bucket it does not own once ExpectedBucketOwner is set and enforced. It cannot reach backward and un-register a bucket a third party already claimed under the same predictable name before the customer ever upgraded. A customer who was exposed under the old, unverified logic and then upgrades to 1.1.0 or 0.2.0 gains a component that will now correctly refuse to write into the attacker's bucket, a real and material improvement, but the attacker's own registration of that name does not expire or get reassigned by AWS shipping a new release. That is why AWS's own remediation guidance asks customers to separately verify that the scan output bucket in their own account is actually owned by their own account, a distinct, per deployment check no code upgrade performs on a customer's behalf.
The Authority Provenance ledger
Authority grantor. AWS, through the affected component's own design, which is meant to write a scanned workspace's archive only into a bucket the calling customer's own account controls.
Caller identity. The AWS Security Agent plugin or MCP server, acting with the customer's own configured AWS credentials during a scan the customer initiated.
Caller mandate. Upload the scan's output archive to the customer's own scan output bucket, and to that bucket alone.
Intermediary. The component's own bucket resolution logic, which computes a destination name from the customer's account id and region and checks that a bucket bearing that name exists and is reachable.
Intermediary credential. The customer's own AWS credentials configured for the plugin or the MCP server, whatever S3 write access those credentials separately carry.
Downstream target. An S3 bucket bearing the derived, predictable name, pre registered by an attacker in an account the attacker controls rather than the customer's own.
Failed limit. Named directly by both advisories: no assertion anywhere in the pre fix upload path required the destination bucket to belong to the calling account, only that a bucket bearing the computed name existed.
Inherited assumption. That a bucket name computed deterministically from the customer's own account id and region would, in practice, only ever be registered by that same customer, an assumption CWE-341's own classification, predictable from observable state, states is unsound the moment the inputs to that computation are public.
Credential binding. Absent for the destination: the customer's own credentials authorized the write operation itself, but nothing bound the destination bucket to the customer's own account before the write proceeded.
Destination binding. Absent before the fix, per both advisories' own account; present and enforced from version 1.1.0 and 0.2.0 onward, through S3's own ExpectedBucketOwner parameter.
Challenge authority. None on the application layer before the fix; S3's own ExpectedBucketOwner check is the challenge authority the fix introduces, refusing the operation the instant the resolved bucket's actual owner does not match the caller's own account id.
Revocation or modification. Shipped. Version 1.1.0 for the plugin and version 0.2.0 for the MCP server, both confirmed directly by this record against the advisories' own patched version fields, published the same day as the advisories themselves, 10 September 2026.
Recovery path. Upgrade to the corrected version, per both advisories' own stated remediation, and separately verify that the scan output bucket in the customer's own account is actually owned by that account, since the version upgrade alone does not release, or reclaim, a bucket name a third party had already registered.
Exploitation. Unknown. Neither advisory states that this was exploited against a real customer, and nothing available to this record establishes an exploitation count or an affected customer count; both remain exactly as unestablished as the originating signal states them.
Provenance evidence quality. Strong for both advisories' own stated facts: this session fetched GHSA-2px6-hhjp-3g5x and GHSA-3jxw-vj8m-8x77 directly, rather than through a summary, and confirmed the CVE ids, the shared CWE pair, the shared CVSS vector, the affected and corrected version boundaries for each distinct package, and the shared credited reporter. Weaker for AWS's own first party framing of the same event: direct fetch of aws.amazon.com's own Security Bulletin 2026-105-AWS, the source named in the originating signal, was blocked by this session's network egress policy on every attempted route, consistent with this desk's prior experience fetching other AWS security bulletins directly in this same period. This record relies on the GitHub Security Advisory Database's own two records instead, graded verified, and does not attribute to AWS's own bulletin page any wording this session did not itself read there.
Where this sits in the pattern
This is not the first time this desk has recorded AWS's own security tooling shipping a check that works on one dimension and is silently trusted to have covered a second, separate one. A companion record on this desk already found AWS Labs' own postgres-mcp-server enforcing read only mode through a blocklist that, in its own words, was never meant to be a complete security boundary, and a further record found amazon-ssm-agent's own S3 download path joining a caller influenced object key into a destination path with a function that never checked whether the result stayed inside it, while a correctly containing sibling function already existed in the same file. Here the shape is different again: the check that ran, does a bucket bearing this name exist and can I reach it, was not incomplete or misapplied so much as answering an entirely different question from the one that mattered, does the account I am about to trust with a private archive actually belong to the customer I am running this scan for. Existence and reachability are the same substitution this desk's own AEW-008, reachability treated as authority, already names in general form. What sharpens past that general form here, evidenced newly and directly by this pair of AWS advisories, is a destination whose very name is computed from information anyone can observe, so an attacker never needs to find or guess anything: the target's own public account id hands the attacker the exact name to register first, in an account of their own choosing, before the legitimate customer ever runs a scan.
What this record does not establish
This record does not claim CVE-2026-87912 or CVE-2026-87913 has been exploited against a real customer, that any specific attacker controlled bucket has been identified, that every customer running an affected version was necessarily exposed, or that AWS's own Security Bulletin 2026-105-AWS states anything beyond what the originating signal and the two GitHub Security Advisories this record fetched directly already establish. Where the evidence available to this record does not establish a fact, this record states it as unknown rather than inferring it from the pattern its own companion records already establish for other AWS tooling.
Sources
This analysis interprets third-party reporting, research and announcements. Moona is not the original reporter of the underlying events.
Protocol evidence
This record does not assess these architectures. The connection runs through the Risk Registry requirement each one bears on, and these published authority architectures are what the evidence says about that requirement.
Protocol evidence related through AEW-042 Existence of a predictably named destination is treated as ownership of it
- No protocol change
Agent Control Standard (ACS)
OWASP GenAI Security Project, originally Zenity
ACS's own conformance document addresses whether a consequential action reaches an independent mediation point at all; the AWS Security Agent plugin's and MCP server's own S3 upload paths are not that kind of gap. A check genuinely ran before every upload, confirming that a bucket bearing the derived name existed and was reachable, and the defect is that this check answered a different question from the one that mattered, existence rather than ownership, not that no check ran at all. Nothing in the material available to this session states or implies a requirement, of ACS's or of any other protocol draft this registry currently holds, that would have engaged differently here: the fix AWS shipped, ExpectedBucketOwner parameter validation, is a provider specific destination ownership assertion, not the adoption of a new mediation, delegation or containment requirement this dataset's protocol material already covers in the abstract. Recorded as no change rather than supporting or missing evidence for any specific protocol requirement.
This record is the cited evidence for this relationship.
