aws-cb-can-modify-code-source-write
Writing to the project's source repository/bucket on the tracked branch injects code into future builds when the buildspec is stored in-source.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
?source is the source repository or bucket (CodeCommit repo / S3 bucket / GitHub/Bitbucket/GitLab repo) tracked by project ?project
project.source.buildspec is empty OR project.source.buildspec == 'buildspec.yml' (stored in source) — NOT an inline or override buildspec
?source is the branch/ref the project's webhook or primary source monitors
optional
Present → upgrade the emitted state; absent → downgrade (not a hard requirement).
{'webhook': None}
CanTrigger {'project': None}
emit
| source type | Identity |
|---|---|
| target type | BuildWorker |
| source | ?principal |
| target | <CodeBuild Project (BuildWorker) that tracks ?source> |
| conditions | service_state trigger_exists |
| state logic | ACTIVE when the principal can write to the tracked branch AND an existing webhook fires on push (matched(optional[0]) or webhook_exists(?project)); CONDITIONAL(trigger_exists) when the push would not automatically trigger a build (manual build only, no webhook); CONDITIONAL(branch_protection) when branch-protection or required-review gates the write (in which case the upstream CanWrite is already CONDITIONAL and this edge inherits it). |
Narrative
{principal.name} can write to {source.name} (the source tracked by {project.name}); since the project reads its buildspec from source, a push to the monitored branch injects attacker-controlled commands into the next build, which runs as {role.name}.
Raw rule rules/derived/aws/codebuild.yaml
id: aws-cb-can-modify-code-source-write
emits: CanModifyCode
description: Writing to the project's source repository/bucket on the tracked branch injects code into
future builds when the buildspec is stored in-source.
match:
- - principal: null
- CanWrite
- source: null
where:
- ?source is the source repository or bucket (CodeCommit repo / S3 bucket / GitHub/Bitbucket/GitLab repo)
tracked by project ?project
- "project.source.buildspec is empty OR project.source.buildspec == 'buildspec.yml' (stored in source)\
\ \u2014 NOT an inline or override buildspec"
- ?source is the branch/ref the project's webhook or primary source monitors
optional:
- - webhook: null
- CanTrigger
- project: null
emit:
source_type: Identity
target_type: BuildWorker
source: ?principal
target: <CodeBuild Project (BuildWorker) that tracks ?source>
permissions: []
conditions:
- service_state
- trigger_exists
state_logic: ACTIVE when the principal can write to the tracked branch AND an existing webhook fires
on push (matched(optional[0]) or webhook_exists(?project)); CONDITIONAL(trigger_exists) when the push
would not automatically trigger a build (manual build only, no webhook); CONDITIONAL(branch_protection)
when branch-protection or required-review gates the write (in which case the upstream CanWrite is
already CONDITIONAL and this edge inherits it).
derived_from:
- ?principal CanWrite ?source
- project.source binding (BatchGetProjects)
- webhook config
false_positive_note: "ONLY emit when the project reads its buildspec FROM source (default behavior when\
\ no inline buildspec is set). If the project has an explicit inline buildspec (source.buildspec contains\
\ YAML content, not a filename) or a buildspecOverride is always supplied at start time, the source\
\ write does NOT control the buildspec \u2014 downgrade to POTENTIAL or do not emit. Branch protection\
\ (required reviews, status checks) on the tracked branch makes the contributing CanWrite CONDITIONAL;\
\ inherit that state. This edge models the supply-chain path: repo write + webhook = codeless RCE\
\ as the service role."
narrative: '{principal.name} can write to {source.name} (the source tracked by {project.name}); since
the project reads its buildspec from source, a push to the monitored branch injects attacker-controlled
commands into the next build, which runs as {role.name}.'