pat-privileged-trigger
WARN
Workflow trigger that runs base-context code with a write token
`pull_request_target` runs in the base repository with a writable token while the code it runs came from an outside fork. The trigger is not an attack on its own, so it is a WARN that tells a reviewer which files to read; what makes it fatal is the checkout of the head, which is the rule below. `workflow_run` and `issue_comment` are deliberately not in this pattern: both are real vectors and neither is the reported shape, so naming them here would cost coverage in false positives instead of buying it.
Detector pattern engine
Roles workflow
Suppressible yes
pat-secret-dump
HIGH
Secret interpolated into something that displays or writes it
`${{ secrets.X }}` in a `run:` line reaches the job log, where it stays readable to anyone who can see the artifact, and into `GITHUB_ENV`, where every later step inherits it. Passing a secret to a step through `env:` or `with:` is not this rule: that is how a workflow uses a secret, and it is the negative case. A line that masks the value first (`::add-mask::`) is the one echo that is deliberate hygiene.
Detector ci_surface (code)
Roles workflow
Suppressible yes
pat-ptr-head-checkout
HIGH
Privileged trigger combined with a checkout of the pull request head
This is the combination that turns a fork pull request into code execution with a write token: the trigger gives the base context and permissions, and the head ref gives the attacker's tree to run. A `pull_request` trigger with the same checkout is reviewed code, and a `pull_request_target` that leaves the default base ref is the safe form, so the rule needs the trigger, a head ref and a checkout step in one file. `ARCHITECTURE.md` 11 worries about exactly this class of weakness in the design document itself.
Detector ci_surface (code)
Roles workflow
Suppressible yes
pat-lifecycle-fetch
WARN
Install hook or lifecycle script reaches the network
A `postinstall` script and a commit hook both run without a developer choosing them, so a downloader named in one is a payload server the reviewer cannot see in a lockfile. The bare host name stays out of this: a `repository.url` in the same manifest is not a fetch, which is why the pattern asks for a client verb or an install-from-URL argument rather than any `https://` text.
Detector pattern engine
Roles package-manifest, install-hook
Suppressible yes
pat-lifecycle-exec
HIGH
Lifecycle script or hook runs what it fetched
The fetch rule becomes this one when the same line also hands the result to an interpreter or a shell, which is the PolinRider dropper shape: the server chooses the payload after install, so nothing in the repository or the lockfile describes what runs. An interpreter named without a fetch is a build step, and a fetch without an interpreter is the WARN above.
Detector ci_surface (code)
Roles package-manifest, install-hook
Suppressible yes
pat-editor-command-path
WARN
Editor setting that names an interpreter or executable
`.vscode/settings.json` is the second half of the editor auto-run surface: `tasks.json` says what can run, and these keys say what the editor runs by itself when a folder opens. A path to an interpreter or a compiler directory is loaded by the extension host, so a planted one needs no user action. Preferences with nothing executable behind them are not reported, which is what keeps this a WARN about a handful of key names rather than about the file.
Detector pattern engine
Roles editor-autorun
Suppressible yes