{"slug": "your-llm-writes-github-actions-like-it-s-2022", "title": "Your LLM Writes GitHub Actions Like It's 2022", "summary": "A 2026 arXiv audit of real-world Java workflows found only 4% compliance with least-privilege permission controls, and model-generated GitHub Actions workflows often inherit over-permissive habits from training data, such as `permissions: write-all` and `pull_request_target` triggers. Ji-ho Choi argues that teams should gate the permissions block before merge rather than write custom checkers, citing the March 2025 tj-actions/changed-files compromise (CVE-2025-30066) that affected over 23,000 repositories and leaked secrets from over-scoped tokens. The recommended fix is to enforce policy in CI with existing tools like actionlint, not homegrown scripts.", "body_md": "[Security](https://sourcefeed.dev/c/security)Article\n\n# Your LLM Writes GitHub Actions Like It's 2022\n\nModel-generated workflows inherit the permissive habits of their training data; gate the permissions block, not just the syntax.\n\n[Ji-ho Choi](https://sourcefeed.dev/u/jiho_choi)\n\nAsk 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`\n\n, trigger on `pull_request_target`\n\n, 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.\n\n## Models write CI like it's 2022\n\nThe over-provisioning isn't a mystery, and it isn't malice. It's the training corpus. Until February 2023, every repo's `GITHUB_TOKEN`\n\ndefaulted 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`\n\nblock entirely (inheriting whatever the repo default is) or slap on broad scopes because that's what made the red X go away in 2021.\n\nThe 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.\n\nThere's a second, subtler pressure. A workflow that requests too little permission fails visibly — `Resource not accessible by integration`\n\n— 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.\n\n## The token sets the blast radius\n\nWhy 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`\n\nand no secrets in the job leaked read access. A workflow with `write-all`\n\nleaked the keys to the repo.\n\nModel-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.\n\n## Gate the diff, don't write a checker\n\nThe dev.to post's answer is a custom Python script that rejects `contents: write`\n\nand 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`\n\nwith checkout of the PR head, unpinned tags, template injection via `${{ github.event.issue.title }}`\n\n, `id-token: write`\n\nenabling OIDC impersonation), and a 40-line script covers three of them while producing a false sense of coverage.\n\nThe tooling already exists. Here's the gate that actually works, in adoption order:\n\n-\n**Flip the org default.** Settings → Actions → workflow permissions → read-only. One click, and every workflow that omits`permissions`\n\n— 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`\n\nerrors you fix by adding explicit, minimal grants. -\n**Run** Its[zizmor](https://zizmor.sh/)in CI.`excessive-permissions`\n\naudit 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. -\n**Put** A diff that touches a`.github/workflows/`\n\nbehind CODEOWNERS.`permissions:`\n\nblock or adds a`secrets.`\n\nreference is a security review, not a code review. Start every generated workflow at`contents: read`\n\n, and add scopes back one at a time, each one justified in the PR:\n\n```\npermissions:\n  contents: read\n```\n\nThat'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.\n\n## GitHub's own agents don't get write tokens\n\nIf 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.\n\nThat'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/`\n\nand merging on green checks.\n\nThis 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.\n\n## Sources & further reading\n\n-\n[Model-Generated GitHub Actions Need a Permission Gate](https://dev.to/hackrs_6393/model-generated-github-actions-need-a-permission-gate-5570)— dev.to -\n[How Compliant Are GitHub Actions Workflows? A Checklist-Based Study with LLM-Assisted Auditing](https://arxiv.org/abs/2605.02091)— arxiv.org -\n[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 -\n[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 -\n[zizmor - Static Analysis for GitHub Actions](https://zizmor.sh/)— zizmor.sh -\n[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 -\n[GitHub Actions Security Pt 2: AI-Powered Actions Analysis](https://www.wiz.io/blog/github-actions-security-ai-powered-actions-vulnerabilities)— wiz.io\n\n[Ji-ho Choi](https://sourcefeed.dev/u/jiho_choi)· Security & Cloud Editor\n\nJi-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.\n\n## Discussion 0\n\nNo comments yet\n\nBe the first to weigh in.", "url": "https://wpnews.pro/news/your-llm-writes-github-actions-like-it-s-2022", "canonical_source": "https://sourcefeed.dev/a/your-llm-writes-github-actions-like-its-2022", "published_at": "2026-08-17 13:08:40+00:00", "updated_at": "2026-08-17 13:11:15.814253+00:00", "lang": "en", "topics": ["ai-safety", "ai-policy", "developer-tools"], "entities": ["GitHub", "Ji-ho Choi", "tj-actions/changed-files", "CVE-2025-30066", "CISA", "arXiv", "Wiz", "actionlint"], "alternates": {"html": "https://wpnews.pro/news/your-llm-writes-github-actions-like-it-s-2022", "markdown": "https://wpnews.pro/news/your-llm-writes-github-actions-like-it-s-2022.md", "text": "https://wpnews.pro/news/your-llm-writes-github-actions-like-it-s-2022.txt", "jsonld": "https://wpnews.pro/news/your-llm-writes-github-actions-like-it-s-2022.jsonld"}}