aws-s3-read-data-contains-secret-yields-read-secret
A principal that can read a bucket's data (CanReadData) and the bucket contains secrets (ContainsSecret) can read those secrets via s3:GetObject.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?bucket) ==
ObjectStorage
?bucket.provider_type == 'AWS::S3::Bucket'
emit
| source type | Identity |
|---|---|
| target type | Secret |
| source | ?principal |
| target | ?secret |
| permissions | s3:GetObject |
| conditions | iam_permission resource_policy |
| state logic | inherit_weakest(CanReadData, ContainsSecret): if either contributor is CONDITIONAL or BLOCKED, inherit that state. ACTIVE only when both CanReadData and ContainsSecret are ACTIVE. The edge carries the same key_permission gate as the CanReadData input if the bucket uses SSE-KMS. |
Narrative
{principal.name} can read {bucket.name} (s3:GetObject) and the bucket contains secrets ({secret.name}); reading the bucket yields the secret material.
Raw rule rules/derived/aws/s3.yaml
id: aws-s3-read-data-contains-secret-yields-read-secret
emits: CanReadSecret
description: A principal that can read a bucket's data (CanReadData) and the bucket contains secrets (ContainsSecret)
can read those secrets via s3:GetObject.
match:
- - principal: null
- CanReadData
- bucket: null
- - bucket: null
- ContainsSecret
- secret: null
where:
- node_type(?bucket) == ObjectStorage
- ?bucket.provider_type == 'AWS::S3::Bucket'
emit:
source_type: Identity
target_type: Secret
source: ?principal
target: ?secret
permissions:
- s3:GetObject
conditions:
- iam_permission
- resource_policy
state_logic: 'inherit_weakest(CanReadData, ContainsSecret): if either contributor is CONDITIONAL or
BLOCKED, inherit that state. ACTIVE only when both CanReadData and ContainsSecret are ACTIVE. The
edge carries the same key_permission gate as the CanReadData input if the bucket uses SSE-KMS.'
confidence: min(contributing_confidences) * 0.95
derived_from:
- ?principal CanReadData ?bucket (s3:GetObject)
- ?bucket ContainsSecret ?secret (heuristic or Macie findings)
false_positive_note: "Only emit when ContainsSecret is explicitly evidenced (heuristic patterns or Macie\
\ findings), not inferred. The CanReadData input may be CONDITIONAL (key_permission) if the bucket\
\ is SSE-KMS encrypted \u2014 inherit that gate; the secret read is then CONDITIONAL(key_permission)\
\ until decrypt-gates-secret-read upgrades it. This bridge rule feeds credential-chains:read-secret-yields-identity."
narrative: '{principal.name} can read {bucket.name} (s3:GetObject) and the bucket contains secrets ({secret.name});
reading the bucket yields the secret material.'