diff --git a/docs/THREAT_MODEL.md b/docs/THREAT_MODEL.md new file mode 100644 index 0000000..604811e --- /dev/null +++ b/docs/THREAT_MODEL.md @@ -0,0 +1,285 @@ +# Security Threat Model - Releaseo GitHub Action + +This document describes the threat model for the Releaseo GitHub Action, which automates version bumping and release PR creation. + +## Overview + +Releaseo is a composite GitHub Action that: +1. Reads a VERSION file and bumps the semantic version +2. Updates version references in YAML files (e.g., Helm charts) +3. Optionally runs `helm-docs` to regenerate documentation +4. Creates a release branch and pull request via the GitHub API + +## Trust Boundaries + +``` +┌─────────────────────────────────────────────────────────────────────┐ +│ GitHub Actions Runner │ +│ ┌───────────────────────────────────────────────────────────────┐ │ +│ │ Workflow Environment │ │ +│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │ +│ │ │ Inputs │───▶│ Releaseo │───▶│ GitHub API │ │ │ +│ │ │ (untrusted) │ │ Action │ │ (authenticated)│ │ │ +│ │ └─────────────┘ └──────┬──────┘ └─────────────────┘ │ │ +│ │ │ │ │ +│ │ ┌──────▼──────┐ │ │ +│ │ │ File System │ │ │ +│ │ │ (repo clone)│ │ │ +│ │ └─────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────────┘ +``` + +### Trust Boundary 1: Action Inputs → Action Code +- **Boundary**: User-provided workflow inputs enter the action +- **Risk Level**: High - inputs are untrusted and could be malicious +- **Controls**: Input validation, allowlists, environment variable usage + +### Trust Boundary 2: Action Code → File System +- **Boundary**: Action reads/writes files in the repository +- **Risk Level**: Medium - path traversal could access unintended files +- **Controls**: Path validation, working directory restrictions + +### Trust Boundary 3: Action Code → External Commands +- **Boundary**: Action executes `helm-docs` binary +- **Risk Level**: High - command injection risk +- **Controls**: Argument allowlist validation + +### Trust Boundary 4: Action Code → GitHub API +- **Boundary**: Action authenticates to GitHub and creates branches/PRs +- **Risk Level**: Medium - token scope determines blast radius +- **Controls**: Minimum required token permissions + +## Data Flow + +``` +┌──────────────┐ ┌──────────────┐ ┌──────────────┐ +│ Workflow │ │ action.yml │ │ main.go │ +│ (caller) │────▶│ (shell) │────▶│ (binary) │ +└──────────────┘ └──────────────┘ └──────────────┘ + │ │ │ + │ bump_type │ INPUT_BUMP_TYPE │ Config.BumpType + │ version_file │ INPUT_VERSION_FILE │ Config.VersionFile + │ helm_docs_args │ INPUT_HELM_DOCS_ARGS│ Config.HelmDocsArgs + │ version_files │ VERSION_FILES_YAML │ Config.VersionFiles + │ token │ GITHUB_TOKEN │ Config.Token + │ base_branch │ INPUT_BASE_BRANCH │ Config.BaseBranch + ▼ ▼ ▼ +``` + +## Assets + +| Asset | Description | Sensitivity | +|-------|-------------|-------------| +| GITHUB_TOKEN | Authentication token for GitHub API | Critical | +| Repository files | Source code and configuration files | High | +| VERSION file | Current semantic version | Low | +| YAML configs | Helm charts, values files | Medium | +| Git history | Commit and branch state | Medium | + +## Threat Actors + +### 1. Malicious Workflow Author +- **Capability**: Can craft malicious input values in workflow files +- **Motivation**: Code execution, data exfiltration, supply chain compromise +- **Likelihood**: Medium (requires repo write access) + +### 2. Malicious Pull Request Author +- **Capability**: Can submit PRs with modified workflow files +- **Motivation**: Inject malicious code into release process +- **Likelihood**: Medium (PRs from forks have limited token scope) + +### 3. Compromised Dependency +- **Capability**: Malicious code in go-github, go-yaml, or helm-docs +- **Motivation**: Supply chain attack +- **Likelihood**: Low (but high impact) + +### 4. Insider Threat +- **Capability**: Legitimate access but malicious intent +- **Motivation**: Various +- **Likelihood**: Low + +## Threats and Mitigations + +### T1: Shell Injection via Action Inputs +| | | +|---|---| +| **STRIDE Category** | Tampering, Elevation of Privilege | +| **Attack Vector** | Crafted `bump_type` or other inputs with shell metacharacters | +| **Impact** | Arbitrary command execution on runner | +| **Likelihood** | High (without mitigation) | +| **Mitigation** | ⏸️ Not implemented - accepted risk for maintainer-triggered workflows | +| **Residual Risk** | **Accepted** - see practical note | + +> **Practical Note**: This threat requires the attacker to control workflow inputs. Since this action is designed to be triggered only by maintainers (via `workflow_dispatch` or similar), an attacker would already need maintainer access to exploit this—at which point they could push malicious code directly. **Risk accepted**: Implementing shell injection mitigations provides minimal security benefit for the intended use case. + +### T2: Command Injection via helm-docs Arguments +| | | +|---|---| +| **STRIDE Category** | Tampering, Elevation of Privilege | +| **Attack Vector** | Malicious flags in `helm_docs_args` (e.g., `--execute=malicious.sh`) | +| **Impact** | Arbitrary command execution | +| **Likelihood** | High (without mitigation) | +| **Mitigation** | ⏸️ Not implemented - accepted risk for maintainer-triggered workflows | +| **Residual Risk** | **Accepted** - see practical note | + +> **Practical Note**: Same as T1—requires attacker to control inputs. Since maintainers configure `helm_docs_args` in the workflow file, they already have write access. **Risk accepted**. + +### T3: Path Traversal via File Paths +| | | +|---|---| +| **STRIDE Category** | Information Disclosure, Tampering | +| **Attack Vector** | `version_file` or `version_files[].file` containing `../` sequences | +| **Impact** | Read/write files outside repository root | +| **Likelihood** | Medium (without mitigation) | +| **Mitigation** | ⏸️ Not implemented - accepted risk for maintainer-triggered workflows | +| **Residual Risk** | **Accepted** - see practical note | + +> **Practical Note**: Same as T1—requires attacker to control inputs. Maintainers configure file paths in the workflow file. **Risk accepted**. + +### T4: YAML Injection +| | | +|---|---| +| **STRIDE Category** | Tampering | +| **Attack Vector** | Malicious YAML path expressions in `version_files[].path` | +| **Impact** | Modify unintended YAML values | +| **Likelihood** | Low | +| **Mitigation** | ✅ Path is used for lookup only, value replacement is surgical | +| **Residual Risk** | Low | + +> **Practical Note**: This mitigation is inherent to the implementation design, not a separate security control. The YAML library handles path lookup safely. + +### T5: Token Exposure +| | | +|---|---| +| **STRIDE Category** | Information Disclosure | +| **Attack Vector** | Token logged, included in error messages, or exposed via outputs | +| **Impact** | Unauthorized repository access | +| **Likelihood** | Medium (without mitigation) | +| **Mitigation** | ⚠️ Token passed via environment variable, not logged | +| **Mitigation** | ⚠️ GitHub automatically masks tokens in logs | +| **Residual Risk** | Medium - depends on token scope | + +### T6: Denial of Service via Large Files +| | | +|---|---| +| **STRIDE Category** | Denial of Service | +| **Attack Vector** | Extremely large VERSION or YAML files | +| **Impact** | Runner resource exhaustion | +| **Likelihood** | Low | +| **Mitigation** | ⚠️ No explicit file size limits | +| **Residual Risk** | Low (GitHub runner limits provide implicit protection) | + +### T7: Supply Chain - Dependency Compromise +| | | +|---|---| +| **STRIDE Category** | Tampering, Elevation of Privilege | +| **Attack Vector** | Malicious code in dependencies (go-github, go-yaml, helm-docs) | +| **Impact** | Arbitrary code execution | +| **Likelihood** | Low | +| **Mitigation** | ⚠️ Use go.sum for dependency verification | +| **Mitigation** | ⚠️ Pin helm-docs version in workflows | +| **Residual Risk** | Medium | + +### T8: Git Branch/Tag Manipulation +| | | +|---|---| +| **STRIDE Category** | Tampering, Repudiation | +| **Attack Vector** | Creating release branches that conflict or overwrite existing ones | +| **Impact** | Release integrity compromise | +| **Likelihood** | Low | +| **Mitigation** | ⚠️ Branch names are deterministic (`release/vX.Y.Z`) | +| **Residual Risk** | Low (branch protection rules should be used) | + +## Practical Risk Assessment + +This section provides context on realistic threats based on how the action is intended to be used. + +### Intended Usage Pattern + +Releaseo is designed to be triggered by **trusted maintainers** when preparing a release, typically via: +- `workflow_dispatch` (manual trigger) +- Repository dispatch events +- Protected branch pushes + +### Threat Realism by Trigger Type + +| Trigger Type | Input-Based Threats (T1-T4) | Supply Chain (T7) | Notes | +|--------------|----------------------------|-------------------|-------| +| `workflow_dispatch` (maintainer) | **Low** - Attacker needs maintainer access | **Medium** | Primary realistic threat | +| `push` to protected branch | **Low** - Requires write access | **Medium** | Branch protection helps | +| `pull_request` (if misconfigured) | **High** - External PRs could inject inputs | **Medium** | ⚠️ Do not use this trigger | +| `pull_request_target` | **High** - Dangerous with checkout | **Medium** | ⚠️ Avoid this pattern | + +### Key Insight + +**For maintainer-triggered releases, the most realistic threats are:** + +1. **Supply chain compromise (T7)** - Malicious code in dependencies or `helm-docs` +2. **Compromised maintainer credentials** - Stolen GitHub credentials used to trigger releases +3. **Accidental misconfiguration** - Adding `pull_request` trigger that exposes inputs to untrusted sources + +**Input-based threats (T1-T4) are primarily defense-in-depth** because: +- They require the attacker to control workflow inputs +- If the action is only triggered by maintainers, the attacker already needs write access +- A maintainer with write access could push malicious code directly without using this action + +### Accepted Risks + +Given the maintainer-only trigger model, the following input-based threats have been **accepted** rather than mitigated: + +| Threat | Reason for Acceptance | +|--------|----------------------| +| T1: Shell Injection | Attacker would need maintainer access, at which point they have write access anyway | +| T2: Command Injection | Maintainers control `helm_docs_args` in the workflow file | +| T3: Path Traversal | Maintainers control file paths in the workflow file | + +**Important**: If the action's usage model changes to allow untrusted inputs (e.g., `pull_request` trigger), these risks should be re-evaluated and mitigations implemented. + +## Security Controls Summary + +### Implemented Controls ✅ + +| Control | Description | Threats Mitigated | +|---------|-------------|-------------------| +| Surgical YAML updates | Values replaced precisely, structure preserved | T4 | +| Token via environment | Token passed as env var, not in command args | T5 | + +### Not Implemented (Accepted Risk) ⏸️ + +| Control | Description | Reason | +|---------|-------------|--------| +| Environment variable inputs | Inputs passed via env vars, not shell interpolation | Maintainer-only access model | +| Input validation | `bump_type` validated against allowlist | Maintainer-only access model | +| Helm-docs argument allowlist | Only permitted flags accepted | Maintainer-only access model | +| Path validation | `ValidatePath()` prevents directory traversal | Maintainer-only access model | + +### Recommended Additional Controls ⚠️ + +| Control | Description | Threats Mitigated | Priority | +|---------|-------------|-------------------|----------| +| Token scope documentation | Document minimum required permissions | T5 | High | +| Dependency scanning | Enable Dependabot/Renovate | T7 | Medium | + +## Minimum Token Permissions + +The action requires the following GitHub token permissions: + +```yaml +permissions: + contents: write # Create branches and commits + pull-requests: write # Create pull requests + issues: write # Add labels to PRs (optional) +``` + +**Recommendation**: Use a fine-grained personal access token (PAT) or GitHub App token with minimum required permissions rather than `GITHUB_TOKEN` when possible. + +## Security Checklist for Users + +- [ ] Use a token with minimum required permissions +- [ ] Enable branch protection on `main` branch +- [ ] Require PR reviews before merge +- [ ] Enable required status checks +- [ ] Review the allowlist of helm-docs flags if using that feature +- [ ] Pin the action version (e.g., `@v1.0.11`) rather than using `@main` +- [ ] Enable Dependabot for security updates