Pipeline-level parameter declaration captured from a top-level
parameters: block. Used by rules that need to reason about whether
caller-supplied parameter values are constrained (values: allowlist)
or free-form (no allowlist on a string parameter — shell-injection risk).
Marks a Step task that runs with addSpnToEnvironment: true, exposing
the federated SPN (idToken / servicePrincipalKey / servicePrincipalId /
tenantId) to the inline script body via environment variables.
Marks a Step that calls actions/cache (or actions/cache/save /
actions/cache/restore). The cell value is the raw key: input from
the step’s with: block. Consumed by pr_specific_cache_key_in_default_branch_consumer
to detect PR-derived cache keys (head_ref, head.ref, actor) that a
default-branch run can later restore — classic cache poisoning.
Step-level metadata: the value passed to actions/checkout’s with.ref
input (verbatim, including any ${{ … }} expressions). Stamped only on
actions/checkout steps that supply a ref:. Consumed by
manual_dispatch_input_to_url_or_command.
Marks a Secret node whose value is interpolated into a CLI flag argument (e.g. -var "key=$(SECRET)").
CLI flag values appear in pipeline log output even when ADO secret masking is active,
because the command string is logged before masking runs and Terraform itself logs -var values.
Graph-level metadata: comma-joined list of workflow_dispatch.inputs.*
names declared by the workflow. Empty / absent if the workflow has no
workflow_dispatch trigger. Consumed by
manual_dispatch_input_to_url_or_command to taint-track input flow into
command lines, URLs, and actions/checkout refs.
Records the GitLab artifacts.reports.dotenv: file path for a Step.
When set, the file’s KEY=value lines are silently exported as
pipeline variables for every downstream job that consumes this job
via needs: or dependencies:. Consumed by
dotenv_artifact_flows_to_privileged_deployment.
Marks a Step that downloads a workflow artifact (typically
actions/download-artifact or dawidd6/action-download-artifact).
In workflow_run-triggered consumers, the originating run’s artifacts
were produced from PR context — the consumer must treat their content as
untrusted input even when the consumer itself runs with elevated perms.
Records the deployment environment name on a Step
(e.g. GitLab environment.name: / GHA environment:).
Used by rules that gate on production-like environment names.
Records a Step’s environment:url: value verbatim. Stamped by the GitLab
parser when the job declares an environment: mapping with a url:
field. Consumed by untrusted_ci_var_in_shell_interpolation because
environment:url: is rendered by the GitLab UI and any predefined-CI-var
interpolated into it is a stored-XSS / open-redirect sink.
Marks a Step that belongs to an ADO deployment job whose environment: is
configured with required approvals — a manual gate that breaks automatic
authority propagation. Findings whose path crosses such a node have their
severity reduced by one step (Critical → High → Medium → Low).
Marks a Step in a GHA workflow as carrying an if: condition that
references the standard fork-check pattern
(github.event.pull_request.head.repo.fork == false or the equivalent
head.repo.full_name == github.repository). Stamped by the GHA parser so
rules can credit the step with the compensating control without
re-parsing the YAML expression. Bool stored as "true".
Records the literal cache.key: value declared on a GitLab job (or the
empty string if no cache is declared). Consumed by
cache_key_crosses_trust_boundary to detect cross-trust cache keys.
Records the cache.policy: value declared on a GitLab job
(pull / push / pull-push / pull_push). When absent, the GitLab
runtime default is pull-push. Consumed by
cache_key_crosses_trust_boundary.
Marks a Step (GitLab job) that declares one or more services: entries
matching docker:*-dind or docker:dind. Combined with secret-bearing
HasAccessTo edges it indicates a runtime sandbox-escape primitive — any
inline build step can docker run -v /:/host from inside dind.
Records the comma-joined list of extends: template names a GitLab job
inherits from. Used by scanner-name pattern matching in
security_job_silently_skipped because GitLab security templates are
usually consumed via extends: rather than by job-name match.
Marks a Step (GitLab job) that defines a trigger: block (downstream /
child pipeline). Value is "static" for a fixed downstream project: or
include: of in-tree YAML, and "dynamic" when the include source is an
artifact: (dynamic child pipelines — code-injection sink).
Marks an Identity node as implicitly injected by the platform (e.g. ADO System.AccessToken).
Implicit tokens are structurally accessible to all tasks by platform design — exposure
to untrusted steps is Info-level (structural) rather than Critical (misconfiguration).
Marks a Step that uses an interactive debug action (mxschmitt/action-tmate,
lhotari/action-upterm, actions/tmate, etc.). The cell value is the action
reference (e.g. mxschmitt/action-tmate@v3). A successful debug session
gives the operator an external SSH endpoint with the runner’s full
environment loaded — every secret in scope, the checked-out HEAD, and
write access to whatever the GITHUB_TOKEN holds.
Marks a Step whose body interprets artifact (or other untrusted file)
content into a privileged sink — unzip/tar -x, cat/jq piping
into >> $GITHUB_ENV/>> $GITHUB_OUTPUT, eval, posting to a PR
comment via actions/github-scriptbody:/issue_body:, or evaluating
extracted text. Combined with META_DOWNLOADS_ARTIFACT upstream in the
same job and a workflow_run/pull_request_target trigger this is the
classic mypy_primer / coverage-comment artifact-RCE pattern.
Records the parent job name on every Step node, enabling per-job subgraph
filtering (e.g. taudit map --job build) and downstream consumers that
need to attribute steps back to their containing job. Set by both the GHA
and ADO parsers on every Step they create within a job’s scope.
Graph-level metadata: pipe-delimited list of <job>\t<name>\t<source>
records, one per jobs.<id>.outputs.<name>. Records are joined with |,
fields within a record with \t. source is one of secret (value
reads secrets.*), oidc (value references steps.*.outputs.* from a
step that holds an OIDC identity), step_output (any other
steps.*.outputs.*), or literal. Plain-text rather than JSON to keep
the parser crate free of serde_json. Consumed by
sensitive_value_in_job_output.
Records, on a Step, the upstream job names this step consumes via
GitLab needs: or dependencies:. Comma-separated job names.
Used to build dotenv-flow dependency chains across stages.
Graph-level metadata: marks a GitHub Actions workflow as having NO
top-level permissions: block declared. Set by the GHA parser when
workflow.permissions is absent so rules can detect the negative-space
“no permissions block at all” pattern (which leaves GITHUB_TOKEN at its
broad platform default — contents: write, packages: write, etc.).
Records the OIDC audience (aud:) value of an id_tokens: entry on an
Identity node. GitLab CI emits one Identity per id_tokens: key; the
audience is what trades for downstream cloud creds (Vault path, AWS role,
etc), so audience reuse across MR-context and protected-context jobs is
the precise privilege-overscope signal. Set by the GitLab parser.
Graph-level metadata: identifies the source platform of the parsed
pipeline. Set by every parser to its platform() value
("github-actions", "azure-devops", "gitlab"). Allows platform-scoped
rules to gate their detection without parsing the source file path.
Marks a Step that reads from the runner-managed environment via an
env.<NAME> template reference — ${{ env.X }} in a with: value,
inline script body, or step env: mapping. Distinct from secrets.X
references (which produce a HasAccessTo edge to a Secret node) — env.X
references can be sourced from the ambient runner environment, including
values laundered through $GITHUB_ENV by an earlier step. Stamped by
the GHA parser so secret_via_env_gate_to_untrusted_consumer can find
the gate-laundering chain that the explicit-secret rules miss.
Graph-level metadata: JSON-encoded array of resources.repositories[]
entries declared by the pipeline. Each entry is an object with fields
alias, repo_type, name, optional ref, and used (true when the
alias is referenced via template: x@alias, extends: x@alias, or
checkout: alias somewhere in the same pipeline file). Set by the ADO
parser; consumed by template_extends_unpinned_branch.
Marks a GitLab CI job (Step node) whose rules: or only: clause
restricts execution to protected branches — either via an explicit
if: $CI_COMMIT_REF_PROTECTED == "true" rule, an if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH rule, or an only: [main, ...] allowlist of
platform-protected refs. Set by the GitLab parser. Absence on a
deployment job is a control gap.
Records the raw inline script body of a Step (the text from
script: / bash: / powershell: / pwsh: / run: / task
inputs.script / inputs.Inline / inputs.inlineScript). Stamped by
parsers when the step has an inline script. Consumed by script-aware
rules: vm_remote_exec_via_pipeline_secret,
short_lived_sas_in_command_line, secret_to_inline_script_env_export,
secret_materialised_to_workspace_file, keyvault_secret_to_plaintext,
add_spn_with_inline_script, parameter_interpolation_into_shell.
Stored verbatim — rules apply their own pattern matching.
Marks the synthetic Step node created for a job that delegates to a
reusable workflow with secrets: inherit. The whole secret bag forwards
to the callee regardless of what the callee actually consumes — when the
caller is fired by an attacker-controllable trigger this is a wide-open
exfiltration path. Set on the synthetic step node by the GHA parser.
Records the name of the ADO service connection a step uses (the value of
inputs.azureSubscription / inputs.connectedServiceName*). Set on the
Step node itself (in addition to the Identity node it links to) so rules
can pattern-match on the connection name without traversing edges.
Marks a Step as performing terraform apply ... -auto-approve (either via
an inline script or via a TerraformCLI / TerraformTask task with
command: apply and commandOptions containing auto-approve).
Graph-level metadata: comma-joined list of every entry under on: (e.g.
pull_request_target,issue_comment,workflow_run). Distinct from
META_TRIGGER (singular) which is set only for pull_request_target /
ADO pr to preserve the existing trigger_context_mismatch contract.
Consumers of this list (e.g. risky_trigger_with_authority) must split on
, and treat each token as a trigger name.
Marks an Image node (self-hosted agent pool) as having workspace isolation
configured (workspace: { clean: all } or workspace: { clean: true } in
ADO). When present, the agent workspace is wiped between runs, mitigating
workspace poisoning attacks where a PR build leaves malicious files for the
next privileged pipeline run. Absence of this key on a self-hosted Image
node is the signal for shared_self_hosted_pool_no_isolation.
Returns true if ref_str looks both structurally pinned AND semantically
plausible. Layered on top of is_sha_pinned / is_docker_digest_pinned:
a structurally valid pin can still be obviously bogus (e.g. an all-zero SHA
is syntactically a 40-char hex string but does not refer to any real
commit; an attacker could use it to fake a “pinned” appearance).
Returns true if ref_str is a SHA-pinned action reference.
Checks: contains @, part after @ is >= 40 hex chars.
Single source of truth — used by both parser and rules.