Agents now write and edit CI workflows, and increasingly run inside them on untrusted issue and PR text. The common mistakes are the ones attackers use: actions pinned to a movable tag, an issue title expanded straight into a shell script, pull_request_target checking out fork code, a default token with write access to everything. This loadout gives your agent the hardening rules from GitHub's secure-use guide and Security Lab, a pattern for agent workflows that separates thinking (read-only) from acting (narrow writes), and a skill that runs zizmor offline and fixes each audit. The verifier runs zizmor 1.31.1 on the example workflow (clean) and on an unsafe agent-triage workflow.
What's in it
- Actions pinned to full commit SHAs, kept current by Dependabot
- permissions: {} at the top; per-job grants; persist-credentials: false
- Untrusted event text through env, never inline in run
- Agent jobs read-only; a separate narrow job applies their output
- zizmor --offline as the check, no token needed
You'll need
- Tools:
uv,gh
Verification
| Check | Result | What we found |
|---|---|---|
| Listinglisting.yaml matches the schema and declares every file in the folder. | Pass | Schema valid; 5 files declared, none missing or extra
|
| Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. | Pass | All 5 files parse; front matter valid |
| AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. | Pass | CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
|
| Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. | Pass | Correct paths for all 6 agents; layouts re-discovered
|
| MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. | Not applicable | No MCP servers in this loadout |
| Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode or prompt-injection wording, and the listing's network flag is honest. | Pass | Clean: no credentials, risky shell or hidden text
|
| ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. | Pass | 2 references between files resolve for every agent |
| Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. | Pass | 5 files, 5.8 KB total; largest AGENTS.md 2.3 KB
|
| LicenceA recognised SPDX licence, with the licence text available. | Pass | MIT, by Agent Loadout; text in the repository LICENSE |
| Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. | Pass | zizmor 1.31.1 (offline) passes the harden-workflow skill's example workflow with no findings and reports template injection, pull_request_target, unpinned actions, persisted credentials and default permissions in an agent-triage workflow
|
What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results ("tested with agent") are separate and stay untested until an agent actually runs.
Install
Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.
Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/AGENTS.md curl -fsSL --create-dirs -o CLAUDE.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/CLAUDE.md curl -fsSL --create-dirs -o .claude/skills/harden-workflow/SKILL.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/SKILL.md curl -fsSL --create-dirs -o .claude/skills/harden-workflow/references/issue-triage.yml https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/references/issue-triage.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
CLAUDE.md | CLAUDE.md |
skills/harden-workflow/SKILL.md | .claude/skills/harden-workflow/SKILL.md |
skills/harden-workflow/references/issue-triage.yml | .claude/skills/harden-workflow/references/issue-triage.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Codex CLI reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/SKILL.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/SKILL.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/references/issue-triage.yml https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/references/issue-triage.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/harden-workflow/SKILL.md | .agents/skills/harden-workflow/SKILL.md |
skills/harden-workflow/references/issue-triage.yml | .agents/skills/harden-workflow/references/issue-triage.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Cursor reads AGENTS.md + .cursor/rules/*.mdc and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/SKILL.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/SKILL.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/references/issue-triage.yml https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/references/issue-triage.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/harden-workflow/SKILL.md | .agents/skills/harden-workflow/SKILL.md |
skills/harden-workflow/references/issue-triage.yml | .agents/skills/harden-workflow/references/issue-triage.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Gemini CLI reads GEMINI.md (imports AGENTS.md with @./AGENTS.md) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/AGENTS.md curl -fsSL --create-dirs -o GEMINI.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/GEMINI.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/SKILL.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/SKILL.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/references/issue-triage.yml https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/references/issue-triage.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
GEMINI.md | GEMINI.md |
skills/harden-workflow/SKILL.md | .agents/skills/harden-workflow/SKILL.md |
skills/harden-workflow/references/issue-triage.yml | .agents/skills/harden-workflow/references/issue-triage.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Antigravity CLI reads AGENTS.md (read natively; GEMINI.md is also read) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/SKILL.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/SKILL.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/references/issue-triage.yml https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/references/issue-triage.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/harden-workflow/SKILL.md | .agents/skills/harden-workflow/SKILL.md |
skills/harden-workflow/references/issue-triage.yml | .agents/skills/harden-workflow/references/issue-triage.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
GitHub Copilot reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/SKILL.md https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/SKILL.md curl -fsSL --create-dirs -o .agents/skills/harden-workflow/references/issue-triage.yml https://loadout.jnw-it.com/raw/github-actions-hardening/1.0.0/skills/harden-workflow/references/issue-triage.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/harden-workflow/SKILL.md | .agents/skills/harden-workflow/SKILL.md |
skills/harden-workflow/references/issue-triage.yml | .agents/skills/harden-workflow/references/issue-triage.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Files
Rules AGENTS.md Rules for writing and changing GitHub Actions workflows, including ones that run AI agents. 33 lines
# AGENTS.md: GitHub Actions hardening
Rules for writing or changing anything under `.github/workflows/`, including workflows that run AI agents on issues
and pull requests. A workflow is code that runs with the repository's tokens and secrets; review it like code.
## Every workflow
- Pin every third-party action to a full commit SHA with the version in a comment:
`uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1`. Tags and branches can be moved.
Keep pins current with Dependabot (`package-ecosystem: github-actions`), not by switching back to tags.
- `permissions: {}` at the top, then grant each job only what it needs (`contents: read`, `issues: write`, ...).
- `actions/checkout` with `persist-credentials: false` unless a later step must push.
- Never write `${{ github.event.* }}`, `${{ github.head_ref }}` or other attacker-controllable values inside `run:`.
Pass them through `env:` and quote the variable: `TITLE: ${{ github.event.issue.title }}` then `"$TITLE"`.
- Secrets only in the steps that need them, through `env:` or `with:`. Never echo them or write them to files that
are uploaded as artifacts.
- Pin runner images (`ubuntu-24.04`, not `ubuntu-latest`) when reproducibility matters.
## Triggers
- Avoid `pull_request_target` and `workflow_run`. If one is unavoidable, never check out or run the pull request's
code in that job, and never give it secrets.
- Code from forks runs under `pull_request`, with a read-only token and no secrets. Keep it that way.
## Workflows that run AI agents
- Issue and PR text is untrusted input to the agent. Run the agent job with a read-only token and no write secrets.
- Split "think" from "act": the agent job writes its proposal to an artifact or output; a separate job with narrow
write permission applies it after checks (labels from a fixed list, comments only, no pushes to default branches).
- Pin agent actions and CLIs to exact versions, and cap spend and turns where the tool supports it.
## Before finishing
- Run the `harden-workflow` skill: `uvx zizmor@1.31.1 --offline .github/workflows` must report no findings, or each
remaining finding is justified in a comment and the PR description.
- Do not push workflow changes to the default branch or re-run workflows with secrets unless the user asks. Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 10 lines
# CLAUDE.md
@AGENTS.md
## Claude Code notes
- Skills from this loadout live in `.claude/skills/`: `harden-workflow`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From the Agent Loadout "GitHub Actions hardening for agent workflows" v1.0.0 — https://loadout.jnw-it.com/loadouts/github-actions-hardening/ --> Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 10 lines
# GEMINI.md
@./AGENTS.md
## Gemini CLI notes
- Skills from this loadout live in `.agents/skills/`: `harden-workflow`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From the Agent Loadout "GitHub Actions hardening for agent workflows" v1.0.0 — https://loadout.jnw-it.com/loadouts/github-actions-hardening/ --> Skill skills/harden-workflow/SKILL.md Audit with zizmor and fix each finding. 26 lines
---
name: harden-workflow
description: Audit and fix GitHub Actions workflows with zizmor before they are committed. Pins actions to commit SHAs, narrows permissions, removes template injection and unsafe triggers. Use for any change under .github/workflows.
---
# Harden a workflow
Example of the target shape: `references/issue-triage.yml`.
1. Audit offline (no token needed): `uvx zizmor@1.31.1 --offline .github/workflows`. Exit code 0 means no findings.
With a `GH_TOKEN`, drop `--offline` to enable the online audits (known-vulnerable actions, impostor commits).
2. Fix by audit name:
- `unpinned-uses`: resolve the SHA for the tag you want with
`gh api repos/OWNER/REPO/git/ref/tags/TAG --jq .object.sha`. If `.object.type` is `tag` (annotated),
follow it once more with `gh api repos/OWNER/REPO/git/tags/SHA --jq .object.sha`. Write
`uses: OWNER/REPO@SHA # TAG`.
- `template-injection`: move the expression into `env:` and reference `"$VAR"` in the script.
- `excessive-permissions`: add `permissions: {}` at the top and per-job grants.
- `artipacked`: set `persist-credentials: false` on checkout.
- `dangerous-triggers`: switch `pull_request_target` to `pull_request`, or split privileged work into a job that
never touches PR code.
3. Re-run zizmor until clean. If you must keep a finding, add an inline `# zizmor: ignore[audit-name]` comment with
the reason, and mention it to the user.
4. Check the workflow still parses: `gh workflow view <file>` on a pushed branch, or `actionlint` if installed.
5. Summarise the changes for the user. Do not push to the default branch yourself. Skill file skills/harden-workflow/references/issue-triage.yml Hardened example workflow. 38 lines
# Labels new issues from their title. Shows the hardened shape: SHA pins, no default permissions,
# per-job grants, no persisted credentials, untrusted text passed through env.
name: issue-triage
on:
issues:
types: [opened]
permissions: {}
jobs:
triage:
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Pick a label from a fixed list
id: pick
env:
TITLE: ${{ github.event.issue.title }}
run: |
label=question
case "${TITLE,,}" in
*bug*|*crash*|*error*) label=bug ;;
*feature*|*request*) label=enhancement ;;
esac
echo "label=$label" >> "$GITHUB_OUTPUT"
- name: Apply the label
env:
GH_TOKEN: ${{ github.token }}
ISSUE: ${{ github.event.issue.number }}
LABEL: ${{ steps.pick.outputs.label }}
run: gh issue edit "$ISSUE" --repo "$GITHUB_REPOSITORY" --add-label "$LABEL" All files: source zip · Licence MIT · By Agent Loadout · First listed
Credits
Public work that inspired this loadout. The wording here is our own; follow the links for the originals.
Installing and testing
How do I install GitHub Actions hardening for agent workflows in Claude Code?
From your project root, put AGENTS.md, CLAUDE.md, skills/harden-workflow/SKILL.md at .claude/skills/harden-workflow/SKILL.md, skills/harden-workflow/references/issue-triage.yml at .claude/skills/harden-workflow/references/issue-triage.yml. The "Claude Code" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/github-actions-hardening/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install GitHub Actions hardening for agent workflows in Codex CLI?
From your project root, put AGENTS.md, skills/harden-workflow/SKILL.md at .agents/skills/harden-workflow/SKILL.md, skills/harden-workflow/references/issue-triage.yml at .agents/skills/harden-workflow/references/issue-triage.yml. The "Codex CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/github-actions-hardening/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install GitHub Actions hardening for agent workflows in Cursor?
From your project root, put AGENTS.md, skills/harden-workflow/SKILL.md at .agents/skills/harden-workflow/SKILL.md, skills/harden-workflow/references/issue-triage.yml at .agents/skills/harden-workflow/references/issue-triage.yml. The "Cursor" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/github-actions-hardening/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install GitHub Actions hardening for agent workflows in Gemini CLI?
From your project root, put AGENTS.md, GEMINI.md, skills/harden-workflow/SKILL.md at .agents/skills/harden-workflow/SKILL.md, skills/harden-workflow/references/issue-triage.yml at .agents/skills/harden-workflow/references/issue-triage.yml. The "Gemini CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/github-actions-hardening/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install GitHub Actions hardening for agent workflows in Antigravity CLI?
From your project root, put AGENTS.md, skills/harden-workflow/SKILL.md at .agents/skills/harden-workflow/SKILL.md, skills/harden-workflow/references/issue-triage.yml at .agents/skills/harden-workflow/references/issue-triage.yml. The "Antigravity CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/github-actions-hardening/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install GitHub Actions hardening for agent workflows in GitHub Copilot?
From your project root, put AGENTS.md, skills/harden-workflow/SKILL.md at .agents/skills/harden-workflow/SKILL.md, skills/harden-workflow/references/issue-triage.yml at .agents/skills/harden-workflow/references/issue-triage.yml. The "GitHub Copilot" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/github-actions-hardening/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
Has GitHub Actions hardening for agent workflows been tested?
It passed the Level 1 automated install checks on 2026-10-17: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.
More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.