# Your LLM Writes GitHub Actions Like It's 2022

> Source: <https://sourcefeed.dev/a/your-llm-writes-github-actions-like-its-2022>
> Published: 2026-08-17 13:08:40+00:00

[Security](https://sourcefeed.dev/c/security)Article

# Your LLM Writes GitHub Actions Like It's 2022

Model-generated workflows inherit the permissive habits of their training data; gate the permissions block, not just the syntax.

[Ji-ho Choi](https://sourcefeed.dev/u/jiho_choi)

Ask a coding model for "a workflow that builds and publishes the docs" and you'll usually get back clean, plausible YAML. It parses. It passes [actionlint](https://github.com/rhysd/actionlint). It might also carry `permissions: write-all`

, trigger on `pull_request_target`

, and touch a repository secret in a step that never needed one. A recent dev.to post put the rule memorably — "a valid YAML file is not a valid action" — and argued that model-generated workflows need a permission gate before merge. The diagnosis is correct. The homegrown fix the post reaches for is where most teams will go wrong.

## Models write CI like it's 2022

The over-provisioning isn't a mystery, and it isn't malice. It's the training corpus. Until February 2023, every repo's `GITHUB_TOKEN`

defaulted to read-write, and [GitHub](https://docs.github.com/en/actions)'s switch to read-only defaults only applied to *new* repos and orgs — existing ones kept the permissive setting. So the millions of public workflows a model learned from overwhelmingly either omit the `permissions`

block entirely (inheriting whatever the repo default is) or slap on broad scopes because that's what made the red X go away in 2021.

The numbers back this up. A 2026 checklist-based audit of real-world Java workflows on arXiv found 28% overall compliance with documented best practices — and 4% compliance on permission controls specifically. Four percent. When least-privilege permissions are the rarest pattern in the wild, a model reproducing the statistical center of its training data will hand you an over-privileged workflow almost every time. Wiz's analysis of AI-related actions found the same shape from the other side: most delegate permission validation entirely to the workflow author, who is increasingly a model.

There's a second, subtler pressure. A workflow that requests too little permission fails visibly — `Resource not accessible by integration`

— while one that requests too much fails never. Every feedback loop a model has ever seen rewards the broad grant. You have to supply the counter-pressure yourself, because nothing in the generation loop will.

## The token sets the blast radius

Why this matters stopped being theoretical in March 2025. When tj-actions/changed-files was compromised (CVE-2025-30066), the attackers retroactively repointed nearly every version tag at a malicious commit that dumped runner memory — access keys, PATs, npm tokens, RSA keys — into workflow logs. It hit workflows in over 23,000 repositories, and CISA issued an alert. The lesson wasn't "audit your third-party actions harder," though everyone said that. The lesson was that *the permissions and secrets in scope when a step runs determine the damage*, because you will not catch the compromise itself in time. A workflow with `contents: read`

and no secrets in the job leaked read access. A workflow with `write-all`

leaked the keys to the repo.

Model-generated workflows multiply the left side of that equation. Every over-scoped token a model ships is pre-positioned blast radius waiting for the next tj-actions.

## Gate the diff, don't write a checker

The dev.to post's answer is a custom Python script that rejects `contents: write`

and secret references. The instinct — enforce policy in CI, after linting — is exactly right. Writing your own checker is exactly wrong, for the same reason you don't write your own actionlint: the failure modes are legion (`pull_request_target`

with checkout of the PR head, unpinned tags, template injection via `${{ github.event.issue.title }}`

, `id-token: write`

enabling OIDC impersonation), and a 40-line script covers three of them while producing a false sense of coverage.

The tooling already exists. Here's the gate that actually works, in adoption order:

-
**Flip the org default.** Settings → Actions → workflow permissions → read-only. One click, and every workflow that omits`permissions`

— which is most of what models generate — becomes safe-by-default instead of privileged-by-default. This is the single highest-leverage change and it costs nothing but a few`Resource not accessible`

errors you fix by adding explicit, minimal grants. -
**Run** Its[zizmor](https://zizmor.sh/)in CI.`excessive-permissions`

audit flags both explicit broad grants and the implicit kind — workflows that declare nothing and inherit repo defaults. It also catches the injection and untrusted-input patterns your script never will, emits SARIF, and lands findings in code scanning on the PR itself.[OpenSSF Scorecard](https://scorecard.dev/)'s token-permissions check gives you the same signal if you're already running it. -
**Put** A diff that touches a`.github/workflows/`

behind CODEOWNERS.`permissions:`

block or adds a`secrets.`

reference is a security review, not a code review. Start every generated workflow at`contents: read`

, and add scopes back one at a time, each one justified in the PR:

```
permissions:
  contents: read
```

That's the whole gate. Lint for syntax, scan for policy, require a human on the privilege escalation path. None of it is novel — which is the point. The novel part is refusing to treat model output as trusted just because you prompted for it.

## GitHub's own agents don't get write tokens

If you want confirmation that this is the right architecture, look at what GitHub built when it put agents *inside* Actions. [GitHub Agentic Workflows](https://github.com/githubnext/gh-aw) gives its agents zero secret access, a read-only GitHub MCP server for repository state, and buffers every write through a separate "safe outputs" stage where deterministic checks filter and limit operations before anything lands. The compiler turns an agent's intent into a workflow with explicit permission constraints. GitHub, with every incentive to make agents feel frictionless, decided model-driven CI gets read-only by default and earns each write.

That's the tell. The company that owns the platform won't hand its own models a write token on trust. The gap right now is that this discipline exists in GitHub's agentic architecture and in opt-in tools like zizmor, but not in the default path where most model-generated YAML actually enters repos: a developer pasting Copilot or Claude output into `.github/workflows/`

and merging on green checks.

This one's a genuine problem, not AI-security hype — the corpus really is over-privileged, models really do reproduce it, and the 2025 supply-chain incidents already showed what scoped-too-wide tokens cost. But the fix isn't new tooling or a bespoke checker. It's an afternoon: flip the org default, add zizmor, gate the workflows directory. Do it before the next tj-actions, because there will be one.

## Sources & further reading

-
[Model-Generated GitHub Actions Need a Permission Gate](https://dev.to/hackrs_6393/model-generated-github-actions-need-a-permission-gate-5570)— dev.to -
[How Compliant Are GitHub Actions Workflows? A Checklist-Based Study with LLM-Assisted Auditing](https://arxiv.org/abs/2605.02091)— arxiv.org -
[GitHub Actions - Updating the default GITHUB_TOKEN permissions to read-only](https://github.blog/changelog/2023-02-02-github-actions-updating-the-default-github_token-permissions-to-read-only/)— github.blog -
[Supply Chain Compromise of Third-Party tj-actions/changed-files (CVE-2025-30066)](https://www.cisa.gov/news-events/alerts/2025/03/18/supply-chain-compromise-third-party-tj-actionschanged-files-cve-2025-30066-and-reviewdogaction)— cisa.gov -
[zizmor - Static Analysis for GitHub Actions](https://zizmor.sh/)— zizmor.sh -
[Under the hood: Security architecture of GitHub Agentic Workflows](https://github.blog/ai-and-ml/generative-ai/under-the-hood-security-architecture-of-github-agentic-workflows/)— github.blog -
[GitHub Actions Security Pt 2: AI-Powered Actions Analysis](https://www.wiz.io/blog/github-actions-security-ai-powered-actions-vulnerabilities)— wiz.io

[Ji-ho Choi](https://sourcefeed.dev/u/jiho_choi)· Security & Cloud Editor

Ji-ho covers the increasingly tangled overlap between cloud architecture and security, drawing on a background as a penetration tester to keep his reporting grounded in real-world attack paths. He never lets a vendor claim go unquestioned and insists that every buzzword come with a proof of concept.

## Discussion 0

No comments yet

Be the first to weigh in.
