GitHub Actions Security Audit
Pricing
from $20.00 / 1,000 github actions audit calls
GitHub Actions Security Audit
Audits .github/workflows/*.yml for supply-chain risks: script injection, leaked tokens, unpinned actions, broad permissions, pull_request_target pitfalls. MCP-native - call from Claude Desktop, Cursor, n8n, or any MCP client. Pay-per-event. Built by Unbearable Labs.
Pricing
from $20.00 / 1,000 github actions audit calls
Rating
0.0
(0)
Developer
Noel Himer
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
MCP server that audits
.github/workflows/*.ymlfiles for supply-chain risks. Catches script injection, leaked tokens, unpinned actions, broad permissions, andpull_request_targetfoot-guns — the patterns behind several 2024-2025 supply-chain incidents.
Built by Unbearable Labs. Free to use — bring your own Apify token.
Available on
- Apify Actor Store — primary
- Smithery
Newsletter: Unbearable TechTips Weekly · All Actors: github.com/UnbearableDev
What it does
Point any MCP-capable client (Claude Desktop, Cursor, n8n, Make, Zapier, custom agents) at this server, hand it a workflow YAML, and get back structured findings with:
- Severity — critical / high / medium / low / info
- Affected job and step — exact location of the problem
- Description — why it matters, with the actual attack vector
- Remediation — what to do about it
- Fix snippet — YAML you can paste directly
Tools
| Tool | Purpose |
|---|---|
audit_workflow(workflow_yaml? | workflow_url?, min_severity='low') | Run all checks |
check_secrets(...) | Secret-leakage paths only |
check_permissions(...) | GITHUB_TOKEN scope issues only |
check_action_pinning(...) | Action version-pinning only |
check_runner_security(...) | Self-hosted runner + script injection |
check_workflow_config(...) | Timeout / config hygiene |
check_supply_chain_advanced(...) | TeamPCP-class supply-chain patterns (GHA-201..208) |
list_checks(category?) | Browse the catalog |
Provide exactly one of workflow_yaml (paste the content) or workflow_url (HTTPS URL — typically a GitHub raw URL to a specific workflow file).
Example
Input:
on:pull_request_target:types: [opened]jobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v3with:ref: ${{ github.event.pull_request.head.sha }}- uses: tj-actions/changed-files@v35- name: Echo titlerun: echo "${{ github.event.pull_request.title }}"
Output:
[{"check_id": "GHA-203","severity": "critical","job": "build","step": null,"message": "'pull_request_target' + checkout of PR head SHA — grants write-token access to untrusted code","remediation": "Use 'pull_request' trigger instead, or do not check out the PR head when using pull_request_target"},{"check_id": "GHA-201","severity": "high","job": "build","step": null,"message": "Third-party action 'tj-actions/changed-files' pinned to mutable semver tag '@v35'","remediation": "Pin to a full commit SHA: 'tj-actions/changed-files@<40-char-sha> # v35'"},{"check_id": "GHA-204","severity": "high","job": "build","step": "Echo title","message": "PR title interpolated into 'run:' — attacker can inject shell commands via crafted PR title","remediation": "Move to an env var and reference $PR_TITLE in the run step"}]
Check catalog (v2: 21 checks)
| ID | Category | Severity | Title |
|---|---|---|---|
| GHA-001 | secrets | high | Secret interpolated directly into run: script |
| GHA-002 | secrets | high | Secret printed via echo / set-output |
| GHA-003 | secrets | medium | Secret used in if: condition |
| GHA-004 | secrets | high | Hardcoded credential pattern in env: |
| GHA-010 | permissions | high | permissions: write-all granted |
| GHA-011 | permissions | medium | No top-level permissions: (inherits broad default) |
| GHA-013 | permissions | high | pull_request_target + checkout PR head = PWNing pattern |
| GHA-020 | action_pinning | high | Third-party action pinned to mutable tag |
| GHA-021 | action_pinning | high | Third-party action pinned to mutable branch |
| GHA-022 | action_pinning | medium | First-party action not SHA-pinned |
| GHA-030 | runner_security | medium | Self-hosted runner used on pull_request from forks |
| GHA-032 | runner_security | high | Script injection via untrusted github.event.* interpolation |
| GHA-040 | workflow_config | low | No timeout-minutes on job |
| GHA-201 | supply_chain_advanced | high | Action pinned to unpinned branch ref (@main/@master) |
| GHA-202 | supply_chain_advanced | high | Action pinned to mutable tag — SHA pin recommended |
| GHA-203 | supply_chain_advanced | critical | pull_request_target + checkout of PR head SHA/ref (codecov/tj-actions exploitation path) |
| GHA-204 | supply_chain_advanced | high | Script injection via github.event.* user-controlled field in run: |
| GHA-205 | supply_chain_advanced | medium | Action from non-allowlisted owner (untrusted 3rd-party) |
| GHA-206 | supply_chain_advanced | high | Top-level permissions: write-all or contents: write without per-job scoping |
| GHA-207 | supply_chain_advanced | medium | Secret logged via echo / cat in run: block |
| GHA-208 | supply_chain_advanced | low | Action uses a known-retired tag |
Pricing
Free to use — hosted on Apify, bring your own Apify token.
Connecting from Claude Desktop
{"mcpServers": {"gha-audit": {"transport": "streamable-http","url": "https://unbearable-dev--github-actions-audit.apify.actor/mcp","headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }}}}
Sibling MCPs from Unbearable Labs
docker-compose-audit—docker-compose.ymlsecurity auditdockerfile-audit— Dockerfile security & qualityk8s-manifest-audit— Kubernetes manifest audithu-postcode-validator— Hungarian postcode lookup
What's NOT covered (yet)
- Reusable workflow auditing (multi-file resolution)
- CodeQL-grade dataflow tracking
- Marketplace-listed action reputation scoring
Source / contact
Source: github.com/UnbearableDev/github-actions-audit.
Issues + ideas: unbearabledev@gmail.com.
Built by Noel @ Unbearable Labs — more like this in the weekly newsletter: https://unbearabletechtips.beehiiv.com
