Goal of the next 30 minutes: why third-party actions are a supply-chain risk, the ten principles that address it, the four teams that share the work, and the settings checklist you can use for a gap assessment.
The full guide, with a step-by-step story of a fictional company (Contoso), is linked at the end.
Ask the audience: how many distinct third-party actions run in your enterprise today? Who approved them? At which version?
Out of scope today: building internal actions, general workflow hardening (pull_request_target, script injection), runner platform design.
Public record: CVE-2025-30066 / GHSA-mw4p-6x4p-x5m5.
The Trivy case is why "review the code that actually runs" includes nested actions.
This is the post-mortem of the fictional Contoso in the guide, built from the real incident. Each row maps to one of the ten principles on the next two slides.
What it cost: the leaked build bot token could read and write every repository. The attacker cloned all 2,100 private repositories, harvested old secrets from Git history, pushed workflows to 40 repositories to steal their secrets, and found the Azure deploy service principal's client secret. With it: customer data copied out of storage, and new secrets on other Entra ID app registrations for persistence. A commit to a shared npm package shipped in 70 services for 9 days. Breach notification, a three-week release freeze, 250+ credentials rotated.
Why it took so long: four teams each held part of the answer, and none of them knew it. No audit log streaming, so the clones were spotted a day late. Nobody owned the Actions policy: three hours to find out who could change it, a day to block. No inventory: four days to find every usage. The Infra team heard on day 3; the persistence in Entra ID turned up in week 3.
1: if approval takes weeks, people copy the code into their repo or pick something worse. Security that slows everyone down gets routed around.
4: wait until the repo is 2 months old and the SHA 7 days old; security fixes skip the wait, never the review.
5: an action can read every secret in its job. Split jobs, environment secrets and OIDC keep secrets away.
6: the Infra team runs the runners and owns their egress rules. A new destination is declared in the request, approved, and recorded in the catalog's network: field.
8: pinning switches off Dependabot alerts for actions, so you need a replacement safety net: Advisory Database matching, audit log to SIEM.
10: blocking takes one allowlist entry. Knowing which runs and secrets were exposed takes data you must already be collecting.
Trusted publishers in the Contoso story: GitHub, Microsoft and Azure, allowed per repository rather than with the "Allow actions created by GitHub" checkbox, which also covers archived repositories.
Ideally the egress rules change through a pull request to an egress-as-code repository, generated from the catalog.
Target in the story: the egress rule for a new destination lands within the onboarding window.
Onboarding targets in the story: 1–2 business days for trusted publishers, 3–5 for everyone else. An egress rule for a new destination lands within the same window.
Break-glass: 72 hours by default, 7 days at most, approved by platform and security. Never for a compromised SHA or unreviewed code.
In the story, the platform, security, Infra and dev teams sit in one room for the first time, and share one channel for third-party actions from then on.
Payoff in Chapter 9: two minutes after the alert, Security opened the incident in the shared channel, where Platform and the sponsor already were. The action was blocked in 29 minutes. In 2025, the first hour went on finding out who owned the policy.
Red team drill in the story: a copy of the build bot's token, cloning from a laptop outside the network. Same pattern as the 2025 incident.
Exclude bots that clone everything by design, like a backup app. Token data on Git events is in public preview.
Suspending a bot for an hour costs some red builds; letting it clone for an hour costs your source code. Blocking an action stays a human call: the SIEM sees the token, not the action that leaked it.
After the drill, Contoso narrowed the bot's tokens to the repositories each job needs.
Use this as a live gap assessment: walk through each box and mark green / amber / red for the customer's enterprise.
SHA pinning applies to every remote action, internal ones too, so migrate first (pinact, Renovate or a script).
Standard GitHub-hosted runners have no egress control. When a job needs both third-party code and sensitive data: egress-controlled self-hosted runners, GitHub-hosted runners with private networking, or accept the risk in writing.
Detections worth starting with: Actions policy changes outside automation; a third-party job receiving a secret its catalog entry doesn't allow; a CI token cloning far more than usual, contained automatically; a self-hosted runner blocking outbound traffic while a third-party action runs.
Tools: poutine or a script for the declared inventory (lockfiles on GitHub Enterprise Cloud), job logs for what ran, pinact for pinning, zizmor and OpenSSF Scorecard for review. A dependency graph SBOM only sees direct uses: on the default branch, never what ran.
Break-glass works from day one, so enforcement never leaves a team stuck.
Offer next steps: a gap assessment against the checklist, or a pilot on one organization following the bootstrap steps.