Aident AI

How to Secure GitHub Agentic Workflows Against Prompt Injection
To secure a GitHub Agentic Workflow, treat every issue, pull request, comment, and fetched page as untrusted data. Limit the workflow to the current repository, filter content by author integrity, keep the agent read-only, declare only the safe outputs it needs, block unnecessary network access, and inspect the compiled .lock.yml before enabling the trigger.
The shortest audit is:
Then review every workflow frontmatter block for these boundaries:
This is a defensive template, not a drop-in workflow. Keep only the read permissions and safe outputs required by your task, then compile and validate the actual source file.
Why GitLost Changed the Audit Question
Noma Security disclosed GitLost on July 6, 2026. Its proof of concept used a public issue to steer an Agentic Workflow that could read other public and private repositories and post a public comment. The dangerous chain was not prompt injection alone. It was untrusted input plus cross-repository read access plus a public output path.
GitHub's current Agentic Workflows documentation describes a layered defense: integrity filtering, read-only agent permissions, sandboxing, a network firewall, safe outputs, threat detection, secret redaction, and compile-time validation. Those layers matter, but they do not make an overbroad credential or repository policy harmless. The current security architecture explicitly treats token scope and declarative configuration as security boundaries.
Use this guide to break the attack chain at several independent points.
Prerequisites
You need:
GitHub CLI authenticated to the repository;
the
github/gh-awextension;a clean worktree so generated lock-file changes are easy to review;
permission to inspect Actions settings, workflow secrets, GitHub Apps, and repository access;
a non-production repository or fork for the canary test.
Install and inspect the tooling:
Expected result: GitHub CLI identifies the intended account, gh aw version succeeds, and the worktree has no unexplained changes. Stop if the authenticated account or repository is not the one you meant to audit.
Step 1: Draw the Actual Data Path
For each .github/workflows/*.md source file, write down four things:
Which event starts it?
Which user-controlled fields can enter the agent context?
Which repositories, tools, secrets, and network destinations can it reach?
Which public or private side effects can it request?
Start with triggers that outsiders can influence, including issues, issue_comment, pull_request, pull_request_review, and discussions. An assignment or label added by automation does not make the original issue body trustworthy.
Search the source and compiled workflows:
Expected result: every untrusted trigger has an explicit repository scope, integrity policy, permission set, output policy, and network policy. If one workflow can read private repositories while reacting to a public issue, disable it until that access is narrowed.
Step 2: Upgrade and Recompile the Security Boundary
The Markdown file is the editable workflow source. The generated .lock.yml is the hardened GitHub Actions workflow that runs. Upgrade the extension and repository support files, then review the generated changes:
Expected result: validation passes, each source workflow has a matching generated lock file, Actions are pinned, and no unexpected permission, secret, tool, or network access appears in the diff. Never hand-edit a .lock.yml file. Change the Markdown source and compile again.
If the upgrade changes deprecated fields, review those changes as a security migration. Do not accept a large generated diff without confirming that its effective permissions and repository scope stayed narrow.
Step 3: Scope GitHub Reads to the Task
The current integrity-filtering reference says allowed-repos defaults to "all" when it is omitted. Make the intended scope explicit.
For a workflow that only needs its own repository:
For a workflow that needs a small fixed set:
Do not use an organization-wide personal token to simplify a public-facing workflow. Prefer the default repository token or a GitHub App installation restricted to the exact repositories and read permissions required. If cross-repository access is genuinely necessary, split public intake from private analysis so untrusted issue text and private repository tools never coexist in the same agent stage.
Expected result: the agent cannot enumerate or read a repository outside the explicit allowlist, even if the model follows hostile text.
Step 4: Choose an Integrity Level Deliberately
For public repositories, GitHub currently applies min-integrity: approved automatically when no level is configured. Declare it anyway so the review boundary is visible:
approved admits owners, members, collaborators, and other content that meets GitHub's documented approval rules. Use merged when the workflow should rely only on content already incorporated into the default branch.
Some community triage workflows must read first-time contributors. If that is the job, min-integrity: none is an explicit acceptance of hostile input:
Pair that setting with current-repository access, read-only permissions, no secrets in the agent container, restrictive safe outputs, and no unnecessary network. Do not lower the integrity level merely to make a filtered issue appear in a test.
Step 5: Keep the Agent Read-Only and Writes Structured
GitHub Agentic Workflows separates agent analysis from side effects. The agent should read with least privilege and request a declared safe output instead of receiving write credentials.
For a workflow that may add one comment:
Do not declare create-pull-request, push-to-pull-request-branch, labels, or cross-repository targets unless the workflow needs them. Safe outputs are narrower than a general write token, but their text and target rules still deserve review.
Expected result: the agent job cannot write directly, and an undeclared mutation is rejected rather than improvised.
Step 6: Close Unneeded Network Paths
If the job only reads GitHub through the provided tooling, block outbound network access:
If a package registry or API is essential, add only the documented ecosystem or domain:
Avoid broad wildcard domains and caller-extensible allowlists unless the workflow's threat model requires them. A blocked request is useful evidence. Review it before expanding the allowlist.
After a run, inspect firewall activity:
Expected result: every allowed destination maps to a stated workflow requirement. Unknown or denied destinations should not be solved by enabling unrestricted egress.
Step 7: Inspect the Compiled Workflow With Security Scanners
Run the strict compiler and the supported Actions scanners:
Then inspect the generated security contract:
Expected result: dependencies are pinned, the agent has no unexpected write scope, secrets are not passed to unnecessary containers, and only reviewed outputs and destinations are enabled. Treat scanner findings and compile-time warnings as blockers until they are explained.
Step 8: Run a Benign Prompt-Injection Canary
Test in a disposable public repository or fork with no private-repository access and no production secrets. Create an issue from an account below the configured integrity threshold containing a harmless canary such as:
Do not include exfiltration commands, real secret names, or sensitive paths. Trigger the workflow, then inspect its logs and audit report:
With min-integrity: approved, the unapproved content should be filtered and recorded as an integrity event. With an intentionally public triage workflow using min-integrity: none, the canary may be visible, but the run must remain inside the current repository, use only declared outputs, and make no unexpected network request.
Expected result: changing one trust boundary produces a predictable, auditable difference without exposing any real data.
Common Failure Modes
Symptom | Likely boundary | Safe response |
|---|---|---|
A public issue can trigger a workflow with an organization-wide token | Trigger and credential scopes overlap | Disable the workflow, replace the token with current-repository access, and separate public intake from private analysis |
An outsider's issue disappears from the agent context | Integrity filtering is working | Keep the filter, or design a separate low-privilege public triage workflow |
The agent asks for an undeclared write | Safe outputs are narrower than the prompt expects | Add only the specific reviewed output, or keep the workflow report-only |
A dependency download is blocked | Network allowlist is restrictive | Verify the destination and add only the required domain or ecosystem |
Source and | Frontmatter changed without compilation | Run |
A scan passes but the effective token reaches many repositories | Static workflow checks cannot narrow the external credential | Replace or reinstall the credential with repository-level scope |
Threat detection blocks a run | Output or patch crossed a security rule | Inspect the artifact and input path; do not weaken the detector to make the run green |
Why These Controls Work Together
Prompt text cannot reliably prove that other prompt text is harmless. The durable controls sit outside the model: which data reaches it, which repositories and tools it can access, which network paths exist, and which side effects a separate stage may apply.
GitLost joined three capabilities that should not have shared one trust domain: public input, private reads, and public writes. Repository scoping removes the private read. Integrity filtering limits hostile input. Read-only execution and safe outputs constrain writes. Network policy removes an alternate export path. Compilation, scanning, and audit logs make those controls reviewable.
For another practical security boundary, see how to audit an agent skill before installing it. For a release-time check, use the Codex Security pre-commit guide.
Verify a Read-Only GitHub Schema With Aident Loadout
Aident Loadout can help an agent discover a narrow GitHub Action without receiving a pasted provider token. Install or update it with:
Then inspect authentication and find one repository-scoped issue-reading Action:
Do not execute an Action until its exact schema, repository fields, operation description, and risk level match the task. Use Aident Loadout to inspect one current GitHub Action schema. Measure success as one schema inspected, one repository boundary confirmed, zero provider secrets pasted, and zero repository writes.
Sources
GitLost: How We Tricked GitHub's AI Agent into Leaking Private Repos, Noma Security, published July 6, 2026
GitHub Agentic Workflows public preview announcement, GitHub, published June 11, 2026
Security Architecture, GitHub Agentic Workflows, accessed July 29, 2026
GitHub Integrity Filtering, GitHub Agentic Workflows, accessed July 29, 2026
GitHub Tools Read Permissions, GitHub Agentic Workflows, accessed July 29, 2026
Network Permissions, GitHub Agentic Workflows, accessed July 29, 2026
Safe Outputs, GitHub Agentic Workflows, accessed July 29, 2026
Compilation Process, GitHub Agentic Workflows, accessed July 29, 2026
Aident setup instructions, accessed July 29, 2026
Refresh this guide when GitHub changes the default integrity policy, allowed-repos behavior, safe-output contract, network firewall, threat detection, compiler flags, or credential model.


