agentleFS
GitHubKnown publishergithub/squad/.copilot/skills/security-review/SKILL.md

security-review

Skill3.4k starsChanged 2 months agoMITView on GitHub

How to review PRs for security — credentials, injection, workflow permissions, supply chain, git operation safety

  • Reads credentials
  • Deletes or force-pushes
  • Commits and pushes

192 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use linkerd-patterns, dependency-cve-sweep and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • xfstudioSkill

    linkerd-patterns

    Implement Linkerd service mesh patterns for lightweight, security-focused service mesh deployments. Use when setting up Linkerd, configuring traffic policies, or implementing zero-trust networking with minimal overhead.

    Also in 5 projects that use this

  • berntpoppSkill

    dependency-cve-sweep

    Use when handling Dependabot PRs, CodeQL/Trivy alerts, or doing a routine dependency/CVE sweep for this repo.

    Also in 12 projects that use this

  • berntpoppSkill

    fleet-standard-adoption

    Use when bringing this repo into compliance with a GeneFoundry fleet standard (tool-naming, response-envelope, container-hardening, versioning, MCP transport, or logging) or closing its tracking issue.

    Also in 12 projects that use this

  • HABUBUSSSkill

    project-guidelines-example

    Also in 16 projects that use this

  • niloykumarbarmanSkill

    agent-sort

    Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

    Also in 13 projects that use this

  • royaluniondesign-sysSkill

    configure-ecc

    Interactive installer for Everything Claude Code — guides users through selecting and installing skills and rules to user-level or project-level directories, verifies paths, and optionally optimizes installed files.

    Also in 11 projects that use this

  • +2 more from berntpopp

The file

Show its rules and text

We split this skill into the rules it gives an agent

17 rules. 0 are common, 8 are distinctive, and 9 are very specific to this project.

  • 0

    Common

    Most of the 167 edited versions we read keep these.

  • 8

    Distinctive

    This author's own choices. Worth a look.

  • 9

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every PR that touches authentication, credentials, environment variables, file system operations, child process execution, user input …

    line 11
  2. Distinctive:

    Use this skill when a PR includes any of:

    line 13
  3. Distinctive:

    Test fixtures that contain real credentials from copy-paste

    line 39
  4. Very specific:

    If a new process.env.X reference is added, is the variable documented?

    line 58
  5. Distinctive:

    If user input determines a file path, verify the code constrains writes to a known safe directory

    line 68
  6. Very specific:

    If the PR modifies gh-cli.ts or adds new gh commands, check for injection vectors

    line 81
  7. Very specific:

    If a PR adds pull_request_target, verify it does NOT checkout ${{ github.event.pull_request.head.ref }} or ${{ …

    line 88
  8. Very specific:

    Follow principle of least privilege — no unnecessary write permissions

    line 92
  9. Very specific:

    If the PR adds permissions: write-all or omits permissions (defaults to broad), flag it

    line 93
  10. Very specific:

    If a workflow uses a PAT (Personal Access Token) instead of GITHUB_TOKEN, it CAN trigger downstream workflows — verify this is intentional

    line 97
  11. Very specific:

    Check for typos in export names (e.g., FSStorageProvidr vs.

    line 125
  12. Distinctive:

    Verify new re-exports actually reference existing modules

    line 126
  13. Distinctive:

    If the PR renames an export, confirm all import sites are updated

    line 127
  14. Very specific:

    When the gh CLI is used in contexts where multiple GitHub accounts might be active:

    line 143
  15. Distinctive:

    Verify that auth tokens are scoped to the correct account

    line 144
  16. Very specific:

    Check that gh auth status is validated before operations

    line 145
  17. Distinctive:

    If the PR adds GitHub API calls, verify it handles auth failures gracefully

    line 146

“Common” is measured: kept by at least 6 in 10 of the 167 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Context

Every PR that touches authentication, credentials, environment variables, file system operations, child process execution, user input handling, GitHub API calls, or workflow files must be reviewed for security. This skill provides a systematic checklist for catching security issues before they reach production.

Use this skill when a PR includes any of:

  • Changes to .github/workflows/ files
  • New or modified environment variable usage
  • File system read/write operations driven by user input
  • Child process execution (child_process.exec, child_process.spawn)
  • GitHub API calls (Octokit, gh CLI wrappers)
  • New npm dependencies
  • Credential or token handling
  • Template rendering with dynamic values

Patterns

1. Secrets and Credentials

No secrets in source code — ever.

Review checklist:

  • ❌ No API keys, tokens, passwords, or connection strings in committed files
  • ❌ No hardcoded GITHUB_TOKEN, NPM_TOKEN, or similar values
  • ❌ No .env files committed (verify .gitignore covers them)
  • ✅ Secrets must be referenced via process.env.X or ${{ secrets.X }} in workflows
  • ✅ If the PR adds a new secret reference, verify it's documented in setup instructions

Watch for disguised secrets:

  • Base64-encoded strings that decode to tokens
  • URLs with embedded credentials (https://user:token@host)
  • Test fixtures that contain real credentials from copy-paste

2. Personal Data in Committed Files

Personal data (especially email addresses) must never be written to committed files.

Squad-specific rule: git config user.email is explicitly banned from being written to any file that gets committed. This prevents PII leakage into the repository.

Review checklist:

  • ❌ No email addresses written to committed files (even in config generation)
  • ❌ No git config user.email output captured and stored in source
  • ✅ If user identity is needed at runtime, read it dynamically and never persist to a committed file

3. Environment Variable Safety

Review checklist:

  • Are environment variables validated before use? (e.g., checking for undefined)
  • Are sensitive environment variables excluded from logs and error messages?
  • Does the PR avoid writing environment variable values to committed files?
  • If a new process.env.X reference is added, is the variable documented?

4. File System Safety

Path traversal prevention:

  • ❌ No direct concatenation of user input into file paths (path.join(baseDir, userInput) without validation)
  • ✅ Validate that resolved paths stay within expected boundaries (use path.resolve and verify the result starts with the expected base directory)
  • ✅ Reject paths containing .., absolute paths when relative are expected, or null bytes

Arbitrary file write prevention:

  • If user input determines a file path, verify the code constrains writes to a known safe directory
  • Template rendering that writes files should validate output paths against a whitelist or known directory

5. Child Process Safety

Shell injection prevention:

  • ❌ No unsanitized user input passed to child_process.exec() (exec uses a shell and is vulnerable to injection)
  • ✅ Prefer child_process.execFile() or child_process.spawn() with argument arrays (no shell interpretation)
  • ✅ If exec must be used, validate/sanitize all interpolated values
  • ✅ Check for template literals in shell commands — exec(\git commit -m "${userMessage}"`)` is injectable

Review checklist for gh CLI wrappers:

  • The gh-cli.ts module wraps GitHub CLI calls. Verify that arguments are passed as array elements, not interpolated into a shell string
  • If the PR modifies gh-cli.ts or adds new gh commands, check for injection vectors

6. GitHub Actions Workflow Security

pull_request_target safety:

  • pull_request_target + checking out PR code = critical security risk (the workflow runs with write token but executes untrusted code from the fork)
  • pull_request_target + NO code checkout = safe (write token used only with trusted workflow code)
  • If a PR adds pull_request_target, verify it does NOT checkout ${{ github.event.pull_request.head.ref }} or ${{ github.event.pull_request.head.sha }}

Token scope minimization:

  • Workflows should declare explicit permissions: blocks
  • Follow principle of least privilege — no unnecessary write permissions
  • If the PR adds permissions: write-all or omits permissions (defaults to broad), flag it

Recursion safety:

  • GITHUB_TOKEN-generated events do NOT trigger new workflow runs (GitHub prevents infinite loops)
  • If a workflow uses a PAT (Personal Access Token) instead of GITHUB_TOKEN, it CAN trigger downstream workflows — verify this is intentional

Secrets in workflows:

  • ❌ No ${{ secrets.X }} in workflow run: steps where the value could leak to logs
  • ✅ Use ::add-mask:: to mask secret values in workflow output
  • ✅ Minimize the number of steps that have access to secrets

7. Git Operation Safety

These rules are from the project's mandatory Git Safety guidelines:

Staging safety:

  • ❌ No git add . or git add -A — these stage unintended deletions from incomplete working trees
  • ❌ No git commit -a — same risk
  • ✅ Only git add path/to/specific/file.ts with explicit file paths

Push safety:

  • ❌ No git push --force or --force-with-lease to shared branches (dev, main)
  • ❌ No direct push to dev or main — must use a PR
  • ✅ Feature branches only: squad/{issue-number}-{slug}

If a PR adds git operations (e.g., in a script, workflow, or agent action), verify every git add, git commit, and git push command follows these rules.

8. Export/Import Integrity

Typos in export names cause silent runtime failures — the export resolves to undefined instead of throwing.

Review checklist:

  • Check for typos in export names (e.g., FSStorageProvidr vs. FSStorageProvider)
  • Verify new re-exports actually reference existing modules
  • If the PR renames an export, confirm all import sites are updated
  • Watch for export { X as Y } where X doesn't exist — TypeScript may not catch this in all configurations

9. Dependency Supply Chain

New npm dependencies should be audited:

  • Is the package well-maintained? (check last publish date, download count, open issues)
  • Does the package have known vulnerabilities? (npm audit)
  • Is there a built-in Node.js alternative? (prefer node:fs, node:path, node:crypto over third-party equivalents)
  • Does the package pull in a large transitive dependency tree?
  • Is the package from a trusted publisher?

Squad-specific: Protected bootstrap files must use ONLY node:* built-in modules. New dependencies in these files are a critical finding.

10. Multi-Account Auth Isolation

When the gh CLI is used in contexts where multiple GitHub accounts might be active:

  • Verify that auth tokens are scoped to the correct account
  • Check that gh auth status is validated before operations
  • If the PR adds GitHub API calls, verify it handles auth failures gracefully

Examples

Example 1: Critical — Shell injection in git command

PR adds:
  exec(`git commit -m "${commitMessage}"`)

Finding: [critical] Shell injection — commitMessage is user-controlled.
A message containing "; rm -rf /" would execute arbitrary commands.
Fix: Use execFile('git', ['commit', '-m', commitMessage]) instead.

Example 2: Critical — pull_request_target with checkout

PR adds workflow:
  on: pull_request_target
  steps:
    - uses: actions/checkout@v4
      with:
        ref: ${{ github.event.pull_request.head.ref }}
    - run: npm test

Finding: [critical] pull_request_target + PR head checkout = untrusted
code execution with write token. An attacker can modify package.json
scripts in their fork to exfiltrate GITHUB_TOKEN.
Fix: Use 'pull_request' trigger instead, or do not checkout PR code.

Example 3: High — Email written to committed file

PR adds to init.ts:
  const email = execSync('git config user.email').toString().trim();
  fs.writeFileSync('.squad/config.json', JSON.stringify({ author: email }));

Finding: [high] Personal data (email) written to committed file.
This violates the PII-in-source rule. Squad config files are committed
to the repo and shared across contributors.
Fix: Read email at runtime only, never persist to committed files.

Example 4: Medium — Overly broad workflow permissions

PR adds workflow with no permissions block (inherits default write-all):
  on: push
  jobs:
    deploy:
      runs-on: ubuntu-latest

Finding: [medium] No explicit permissions block. Workflow inherits
default permissions which may be overly broad.
Fix: Add 'permissions:' block with minimum required scopes.

Example 5: Medium — New dependency when built-in exists

PR adds to package.json:
  "dependencies": { "mkdirp": "^3.0.0" }

Finding: [medium] mkdirp is unnecessary — Node.js built-in
fs.mkdirSync(path, { recursive: true }) provides the same functionality.
Fix: Use node:fs built-in instead of adding a new dependency.

Example 6: Low — Missing environment variable validation

PR uses process.env.SQUAD_API_KEY without checking if it's defined:
  const apiKey = process.env.SQUAD_API_KEY;
  fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });

Finding: [low] No validation that SQUAD_API_KEY is defined.
If undefined, the Bearer token will be "Bearer undefined" which
may produce confusing auth errors.
Fix: Check for undefined and throw a descriptive error early.

Review Output Format

Structure your security review with severity levels:

## Security Review

**Verdict:** APPROVE | APPROVE WITH NOTES | REQUEST CHANGES | REJECT

### Findings

1. [severity: critical] — description
   - File(s): path/to/file.ts:L42
   - Risk: what could go wrong
   - Fix: specific remediation

2. [severity: high] — ...

3. [severity: medium] — ...

4. [severity: low] — ...

### Severity Guide
- **Critical:** Exploitable vulnerability, credential exposure, or code execution risk. Must fix before merge.
- **High:** Security design flaw that could lead to exploitation. Must fix before merge.
- **Medium:** Security best practice violation. Should fix before merge.
- **Low:** Minor hardening opportunity. Can fix in a follow-up PR.

### Summary
Brief overview of security posture and required actions.

Anti-Patterns

  • ❌ Approving PRs with exec() and user-controlled input ("it's just a commit message")
  • ❌ Ignoring pull_request_target trigger changes ("the workflow looks fine otherwise")
  • ❌ Skipping dependency audit for "small" packages ("it's only 10 lines of code")
  • ❌ Treating git add . in scripts as acceptable ("it works on my machine")
  • ❌ Allowing secrets in test fixtures ("it's just a test, not production")
  • ❌ Approving workflows without explicit permissions: blocks ("defaults are probably fine")
  • ❌ Dismissing PII in committed files ("it's just an email address")
  • ❌ Ignoring export typos ("TypeScript would catch that") — not always true with re-exports
  • ❌ Allowing force pushes to shared branches in scripts ("we know what we're doing")
  • ❌ Skipping review of new node_modules additions in bootstrap files ("it's a small package")

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.