aws-cc-cross-account-push-code-inject

A cross-account GitPush grant in the repository resource policy lets an external principal inject code into pipelines in the repository-owning account.

derived aws emits CanModifyCode

match

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

{'ext_principal': None} HasPermission {'repo': None}

where

node_type(?repo) == ArtifactRepository ?repo.provider_type == 'AWS::CodeCommit::Repository' ?ext_principal.account != ?repo.account # cross-account effective permission includes codecommit:GitPush on ?repo ARN for ?ext_principal (from resource policy + caller IAM policy, dual-policy eval) exists a BuildWorker ?runner in ?repo.account whose source is ?repo AND tracked branch intersects the push scope

emit

source typeIdentity
target typeBuildWorker
source?ext_principal
target?runner
permissionscodecommit:GitPush
conditionsiam_permission resource_policy
state logicCONDITIONAL(iam_permission, resource_policy) by default: cross-account access requires BOTH the resource policy grant (in the repo-owning account) AND an IAM policy grant in the caller's own account. Confirm both sides before upgrading to ACTIVE. BLOCKED when either side is denied (SCP in the repo account denying cross-account push, or no matching IAM grant in the caller account).

Narrative

{ext_principal.name} (account {ext_principal.account}) has codecommit:GitPush on {repo.name} via its resource policy; pushing to the branch {runner.name} tracks injects attacker code into {runner.name}'s build, running as {runner.name}'s service role in account {repo.account}.

Raw rule rules/derived/aws/codecommit.yaml

id: aws-cc-cross-account-push-code-inject
emits: CanModifyCode
description: A cross-account GitPush grant in the repository resource policy lets an external principal
  inject code into pipelines in the repository-owning account.
match:
- - ext_principal: null
  - HasPermission
  - repo: null
where:
- node_type(?repo) == ArtifactRepository
- ?repo.provider_type == 'AWS::CodeCommit::Repository'
- '?ext_principal.account != ?repo.account  # cross-account'
- effective permission includes codecommit:GitPush on ?repo ARN for ?ext_principal (from resource policy
  + caller IAM policy, dual-policy eval)
- exists a BuildWorker ?runner in ?repo.account whose source is ?repo AND tracked branch intersects the
  push scope
emit:
  source_type: Identity
  target_type: BuildWorker
  source: ?ext_principal
  target: ?runner
  permissions:
  - codecommit:GitPush
  conditions:
  - iam_permission
  - resource_policy
  state_logic: 'CONDITIONAL(iam_permission, resource_policy) by default: cross-account access requires
    BOTH the resource policy grant (in the repo-owning account) AND an IAM policy grant in the caller''s
    own account. Confirm both sides before upgrading to ACTIVE. BLOCKED when either side is denied (SCP
    in the repo account denying cross-account push, or no matching IAM grant in the caller account).'
  confidence: 0.88
  derived_from:
  - codecommit:GitPush effective via resource policy (cross-account)
  - ?runner source binding to ?repo branch
  false_positive_note: "Cross-account CodeCommit access uses standard dual-policy evaluation: the resource\
    \ policy in the repository-owning account + an IAM policy in the calling principal's account must\
    \ both allow the action. Confirm the IAM side before emitting ACTIVE. Honor codecommit:References\
    \ conditions on either policy side. This rule emits CanModifyCode (not CrossAccountTrust) because\
    \ it is the CanModifyCode FACT \u2014 the CrossAccountTrust explicit edge is separately emitted by\
    \ the explicit normalization rules (aws-codecommit.yaml, rule cross-account-policy). cicd-chains then\
    \ collapses the resulting CanModifyCode + ExecutesAs into CanExecuteAs, and can-control produces CanEnterAccount\
    \ for the owning account."
  narrative: '{ext_principal.name} (account {ext_principal.account}) has codecommit:GitPush on {repo.name}
    via its resource policy; pushing to the branch {runner.name} tracks injects attacker code into {runner.name}''s
    build, running as {runner.name}''s service role in account {repo.account}.'
move · open · esc close