aws-codepipeline-artifact-s3-supply-chain

Write access to the pipeline's artifact store S3 bucket/prefix lets an attacker inject a malicious artifact that the next pipeline stage processes as the stage's action role - supply-chain code injection into the pipeline.

derived aws emits CanModifyCode

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanWrite {'artifact_bucket': None}

where

node_type(?artifact_bucket) == ObjectStorage ?artifact_bucket is the pipeline's artifactStore bucket (confirmed by GetPipeline[].pipeline.artifactStore.location) ?principal has EFFECTIVE s3:PutObject on the artifact prefix

optional

Present → upgrade the emitted state; absent → downgrade (not a hard requirement).

{'artifact_bucket': None} CanTrigger {'pipeline': None}

emit

source typeIdentity
target typeCompute
source?principal
target?pipeline
permissionss3:PutObject
conditionsrun_path
state logicACTIVE if matched(optional[0]) — the artifact store has an EventBridge ObjectCreated trigger that starts the pipeline automatically on artifact write. Otherwise CONDITIONAL(run_path): the attacker writes the malicious artifact but the pipeline must be separately triggered (manually or via another event). Do NOT emit ACTIVE when the pipeline Source stage uses S3 with change detection DISABLED (artifact polling only) and the attacker cannot also StartPipelineExecution.

Narrative

{principal.name} can write to the artifact store {artifact_bucket.name} (s3:PutObject) used by pipeline {pipeline.name}. The next stage that reads those artifacts processes the attacker's content as the stage's action role{if optional[0]: '; the S3 ObjectCreated trigger starts the pipeline automatically, making this ACTIVE'}.

Raw rule rules/derived/aws/codepipeline.yaml

id: aws-codepipeline-artifact-s3-supply-chain
emits: CanModifyCode
description: "Write access to the pipeline's artifact store S3 bucket/prefix lets an attacker inject a\
  \ malicious artifact that the next pipeline stage processes as the stage's action role \u2014 supply-chain\
  \ code injection into the pipeline."
match:
- - principal: null
  - CanWrite
  - artifact_bucket: null
where:
- node_type(?artifact_bucket) == ObjectStorage
- ?artifact_bucket is the pipeline's artifactStore bucket (confirmed by GetPipeline[].pipeline.artifactStore.location)
- ?principal has EFFECTIVE s3:PutObject on the artifact prefix
optional:
- - artifact_bucket: null
  - CanTrigger
  - pipeline: null
emit:
  source_type: Identity
  target_type: Compute
  source: ?principal
  target: ?pipeline
  permissions:
  - s3:PutObject
  conditions:
  - run_path
  state_logic: "ACTIVE if matched(optional[0]) \u2014 the artifact store has an EventBridge ObjectCreated\
    \ trigger that starts the pipeline automatically on artifact write. Otherwise CONDITIONAL(run_path):\
    \ the attacker writes the malicious artifact but the pipeline must be separately triggered (manually\
    \ or via another event). Do NOT emit ACTIVE when the pipeline Source stage uses S3 with change detection\
    \ DISABLED (artifact polling only) and the attacker cannot also StartPipelineExecution."
  confidence: min(contributing_confidences) * 0.9
  derived_from:
  - ?principal CanWrite ?artifact_bucket
  - ?artifact_bucket is the artifactStore for ?pipeline
  false_positive_note: Only target pipelines whose artifactStore bucket matches ?artifact_bucket AND where
    the written prefix is the input artifact for a stage the pipeline actually runs (not an output-only
    artifact). The artifact write does NOT immediately run the pipeline unless an S3 source trigger is
    configured. Confirm the trigger exists before emitting ACTIVE. An artifact store protected by a CMK
    also requires the attacker to have kms:GenerateDataKey AND kms:Encrypt (for writing encrypted objects
    to S3); if the bucket is CMK-encrypted, gate on CanDecrypt only as a check, but the actual write permission
    depends on CanDecrypt + CanWrite both succeeding (CanDecrypt gates reading; CanGenerateDataKey gates
    writing). Ensure the principal has both kms:GenerateDataKey and kms:Encrypt on the CMK.
  narrative: '{principal.name} can write to the artifact store {artifact_bucket.name} (s3:PutObject) used
    by pipeline {pipeline.name}. The next stage that reads those artifacts processes the attacker''s content
    as the stage''s action role{if optional[0]: ''; the S3 ObjectCreated trigger starts the pipeline automatically,
    making this ACTIVE''}.'
move · open · esc close