cicd-trigger-runner-executes-as

Trigger/start a runner whose current definition already runs attacker-influenced code, executing as the runner's identity.

derived any cloud emits CanExecuteAs

match

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

{'principal': None} CanTrigger {'runner': None} {'runner': None} ExecutesAs {'identity': None}

where

node_type(?runner) in [BuildWorker, ContainerTask, ContainerService, ServerlessFunction, VirtualMachine, KubernetesWorkload]

optional

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

{'principal': None} CanStart {'runner': None}

emit

source typeIdentity
target typeIdentity
source?principal
target?identity
conditionsattacker_influenced_definition
state logicCONDITIONAL(attacker_influenced_definition) by default — triggering runs the CURRENT definition, which yields the identity to the attacker only if that definition already executes attacker-controllable code (a mutable/unpinned dependency the attacker can poison, a build of an untrusted PR/fork with pwn-request semantics, an attacker-authored branch the trigger targets, or an already-tampered spec). ACTIVE only when such attacker influence over the current definition is established (then it is effectively the modify path). A trigger over a fully pinned, trusted, reviewed definition => stays CONDITIONAL and is NOT an ACTIVE execute-as. Inherit weakest with CanTrigger / ExecutesAs.

Narrative

{principal.name} can trigger {runner.name}, which executes as {identity.name}; if the runner's current definition already runs attacker-influenceable code (poisoned dependency, untrusted PR build, tampered spec), the run executes as {identity.name}.

Raw rule rules/derived/cicd-chains.yaml

id: cicd-trigger-runner-executes-as
emits: CanExecuteAs
description: Trigger/start a runner whose current definition already runs attacker-influenced code, executing
  as the runner's identity.
applies_to:
- '*'
match:
- - principal: null
  - CanTrigger
  - runner: null
- - runner: null
  - ExecutesAs
  - identity: null
where:
- node_type(?runner) in [BuildWorker, ContainerTask, ContainerService, ServerlessFunction, VirtualMachine,
  KubernetesWorkload]
optional:
- - principal: null
  - CanStart
  - runner: null
emit:
  source_type: Identity
  target_type: Identity
  source: ?principal
  target: ?identity
  permissions: []
  conditions:
  - attacker_influenced_definition
  state_logic: "CONDITIONAL(attacker_influenced_definition) by default \u2014 triggering runs the CURRENT\
    \ definition, which yields the identity to the attacker only if that definition already executes attacker-controllable\
    \ code (a mutable/unpinned dependency the attacker can poison, a build of an untrusted PR/fork with\
    \ pwn-request semantics, an attacker-authored branch the trigger targets, or an already-tampered spec).\
    \ ACTIVE only when such attacker influence over the current definition is established (then it is\
    \ effectively the modify path). A trigger over a fully pinned, trusted, reviewed definition => stays\
    \ CONDITIONAL and is NOT an ACTIVE execute-as. Inherit weakest with CanTrigger / ExecutesAs."
  confidence: min(contributing_confidences) * 0.7
  derived_from:
  - ?principal CanTrigger ?runner
  - ?runner ExecutesAs ?identity
  false_positive_note: "Strictly weaker than rule 1 (0.7 prior): a trigger is not code control. Do NOT\
    \ emit ACTIVE merely because the principal can start a build \u2014 the current definition must already\
    \ run attacker-influenceable code. The classic ACTIVE cases are pwn-request-style PR builds (untrusted\
    \ fork code runs with the trusted identity) and unpinned-dependency supply-chain (the attacker poisons\
    \ a dependency the build resolves). If the runner builds only trusted, pinned, reviewed source with\
    \ no untrusted input, keep CONDITIONAL. Dedupes with rule 1 on (CanExecuteAs, ?principal, ?identity):\
    \ when the principal can BOTH modify and trigger, rule 1's ACTIVE dominates \u2014 do not double-count."
  narrative: '{principal.name} can trigger {runner.name}, which executes as {identity.name}; if the runner''s
    current definition already runs attacker-influenceable code (poisoned dependency, untrusted PR build,
    tampered spec), the run executes as {identity.name}.'
move · open · esc close