aws-s3-modify-code-artifact
s3:PutObject on a bucket that is a verified code-artifact deployment source (Lambda, CodePipeline, CloudFormation) for a compute workload equals modifying that workload's code.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanWriteData {'bucket': None}
{'bucket': None} ContainsResourceReference {'compute': None}
where
node_type(?bucket) ==
ObjectStorage
node_class(?compute) in [Compute, AnalyticsService] OR node_type(?compute) in [ServerlessFunction, BuildWorker, BatchJob, ApplicationPlatform]
the ContainsResourceReference edge is typed as 'CodeSourceFor' or 'DeploymentSourceFor' (explicit evidence from config)
emit
| source type | Identity |
|---|---|
| target type | * |
| source | ?principal |
| target | ?compute |
| permissions | s3:PutObject |
| conditions | iam_permission resource_policy |
| state logic | ACTIVE when the CanWriteData(principal, bucket) edge is ACTIVE AND the ?bucket -> ?compute ContainsResourceReference edge is confirmed (code-source detected from Lambda GetFunctionConfiguration, CodePipeline config, or CloudFormation template). Inherits weakest state from the contributing CanWriteData edge. BLOCKED when CanWriteData is BLOCKED. |
Narrative
{principal.name} can write to {bucket.name} (s3:PutObject), which is the verified code-artifact deployment source for {compute.name} - overwriting the artifact injects attacker code that runs as {compute.name}'s execution identity.
Raw rule rules/derived/aws/s3.yaml
id: aws-s3-modify-code-artifact
emits: CanModifyCode
description: s3:PutObject on a bucket that is a verified code-artifact deployment source (Lambda, CodePipeline,
CloudFormation) for a compute workload equals modifying that workload's code.
match:
- - principal: null
- CanWriteData
- bucket: null
- - bucket: null
- ContainsResourceReference
- compute: null
where:
- node_type(?bucket) == ObjectStorage
- node_class(?compute) in [Compute, AnalyticsService] OR node_type(?compute) in [ServerlessFunction,
BuildWorker, BatchJob, ApplicationPlatform]
- the ContainsResourceReference edge is typed as 'CodeSourceFor' or 'DeploymentSourceFor' (explicit evidence
from config)
emit:
source_type: Identity
target_type: '*'
source: ?principal
target: ?compute
permissions:
- s3:PutObject
conditions:
- iam_permission
- resource_policy
state_logic: ACTIVE when the CanWriteData(principal, bucket) edge is ACTIVE AND the ?bucket -> ?compute
ContainsResourceReference edge is confirmed (code-source detected from Lambda GetFunctionConfiguration,
CodePipeline config, or CloudFormation template). Inherits weakest state from the contributing CanWriteData
edge. BLOCKED when CanWriteData is BLOCKED.
confidence: min(contributing_confidences) * 0.85
derived_from:
- ?principal CanWriteData ?bucket (s3:PutObject)
- ?bucket ContainsResourceReference ?compute (code-artifact source via explicit normalization)
- "can-execute-as:execute-as-via-code-modify (roll-up \u2014 cited not re-derived)"
false_positive_note: "This rule ONLY matches when ContainsResourceReference is present with code-source\
\ evidence. S3 event notifications (CanTrigger) are NOT sufficient \u2014 they indicate that a Lambda\
\ subscribes to bucket events but do NOT prove the bucket is the deployment source for the Lambda's\
\ code. Lambda event-triggered execution and Lambda code deployment are distinct patterns; do not\
\ conflate them. Versioned buckets: if the compute uses a pinned s3ObjectVersion, a new PutObject\
\ creates an unreferenced version (not injected); in that case downgrade to CONDITIONAL(trigger_exists)."
narrative: "{principal.name} can write to {bucket.name} (s3:PutObject), which is the verified code-artifact\
\ deployment source for {compute.name} \u2014 overwriting the artifact injects attacker code that\
\ runs as {compute.name}'s execution identity."