aws-s3-read-data-get-object
s3:GetObject on a bucket grants full data-plane read of stored objects (SSE-S3/no-encryption path - AWS-managed decryption, no caller kms:Decrypt needed).
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'
?principal has EFFECTIVE s3:GetObject on ?bucket ARN (identity-based policy + bucket policy jointly permit; Block Public Access evaluated)
?bucket.encryption NOT in ['aws:kms', 'aws:kms:dsse'] OR ?bucket.properties.KMSMasterKeyID is null (service-managed key)
emit
| source type | Identity |
|---|---|
| target type | ObjectStorage |
| source | ?principal |
| target | ?bucket |
| permissions | s3:GetObject |
| conditions | iam_permission resource_policy scp_or_org_policy |
| state logic | ACTIVE when s3:GetObject is confirmed EFFECTIVE (identity-based policy + bucket policy jointly permit; no SCP or permission-boundary deny). Bucket policy with aws:PrincipalOrgID / aws:SourceVpc conditions: honor those conditions — only ACTIVE for principals that satisfy them. BLOCKED when an SCP or explicit bucket-policy Deny overrides the grant. |
Narrative
{principal.name} has s3:GetObject on {bucket.name} and can read any object in the bucket (AWS-managed or no encryption - decryption is transparent).
Raw rule rules/derived/aws/s3.yaml
id: aws-s3-read-data-get-object
emits: CanReadData
description: "s3:GetObject on a bucket grants full data-plane read of stored objects (SSE-S3/no-encryption\
\ path \u2014 AWS-managed decryption, no caller kms:Decrypt needed)."
match:
- - principal: null
- HasPermission
- bucket: null
where:
- node_type(?bucket) == ObjectStorage
- ?bucket.provider_type == 'AWS::S3::Bucket'
- ?principal has EFFECTIVE s3:GetObject on ?bucket ARN (identity-based policy + bucket policy jointly
permit; Block Public Access evaluated)
- ?bucket.encryption NOT in ['aws:kms', 'aws:kms:dsse'] OR ?bucket.properties.KMSMasterKeyID is null (service-managed
key)
emit:
source_type: Identity
target_type: ObjectStorage
source: ?principal
target: ?bucket
permissions:
- s3:GetObject
conditions:
- iam_permission
- resource_policy
- scp_or_org_policy
state_logic: "ACTIVE when s3:GetObject is confirmed EFFECTIVE (identity-based policy + bucket policy\
\ jointly permit; no SCP or permission-boundary deny). Bucket policy with aws:PrincipalOrgID / aws:SourceVpc\
\ conditions: honor those conditions \u2014 only ACTIVE for principals that satisfy them. BLOCKED\
\ when an SCP or explicit bucket-policy Deny overrides the grant."
confidence: min(contributing_confidences) * 0.95
derived_from:
- ?principal HasPermission ?bucket (s3:GetObject effective permission)
- "aws-s3-read-data-contains-secret-yields-read-secret (bridge rule \u2014 converts CanReadData + ContainsSecret\
\ to CanReadSecret)"
- "credential-chains:read-secret-yields-identity (cited not re-derived \u2014 CanReadSecret + CredentialsFor\
\ -> CanImpersonate)"
false_positive_note: "For SSE-KMS encrypted buckets, s3:GetObject alone is insufficient \u2014 the caller\
\ cannot decrypt the ciphertext without kms:Decrypt on the wrapping CMK; use rule aws-s3-read-data-sse-kms\
\ (CONDITIONAL key_permission) instead. Bucket policy conditions (aws:PrincipalOrgID, aws:SourceVpc,\
\ aws:SourceAccount) restrict who the grant actually covers \u2014 honor them. Block Public Access\
\ RestrictPublicBuckets=true overrides even an explicit bucket-policy allow for anonymous/unauthenticated\
\ principals; do not emit for anonymous callers when BPA is active. s3:GetObject scoped to a specific\
\ object prefix (Resource: arn:aws:s3:::bucket/prefix/*) limits the read to that prefix \u2014 scope\
\ the edge to that prefix, not the whole bucket."
narrative: "{principal.name} has s3:GetObject on {bucket.name} and can read any object in the bucket\
\ (AWS-managed or no encryption \u2014 decryption is transparent)."