mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-20 13:10:30 -06:00
233 lines
5.8 KiB
Plaintext
233 lines
5.8 KiB
Plaintext
---
|
|
description: Security best practices and guidelines for writing GitHub Actions and workflows
|
|
globs: .github/workflows/*.yml,.github/workflows/*.yaml,.github/actions/*/action.yml,.github/actions/*/action.yaml
|
|
---
|
|
|
|
# GitHub Actions Security Best Practices
|
|
|
|
## Required Security Measures
|
|
|
|
### 1. Set Minimum GITHUB_TOKEN Permissions
|
|
|
|
Always explicitly set the minimum required permissions for GITHUB_TOKEN:
|
|
|
|
```yaml
|
|
permissions:
|
|
contents: read
|
|
# Only add additional permissions if absolutely necessary:
|
|
# pull-requests: write # for commenting on PRs
|
|
# issues: write # for creating/updating issues
|
|
# checks: write # for publishing check results
|
|
```
|
|
|
|
### 2. Add Harden-Runner as First Step
|
|
|
|
For **every job** on `ubuntu-latest`, add Harden-Runner as the first step:
|
|
|
|
```yaml
|
|
- name: Harden the runner
|
|
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0
|
|
with:
|
|
egress-policy: audit # or 'block' for stricter security
|
|
```
|
|
|
|
### 3. Pin Actions to Full Commit SHA
|
|
|
|
**Always** pin third-party actions to their full commit SHA, not tags:
|
|
|
|
```yaml
|
|
# ❌ BAD - uses mutable tag
|
|
- uses: actions/checkout@v4
|
|
|
|
# ✅ GOOD - pinned to immutable commit SHA
|
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
```
|
|
|
|
### 4. Secure Variable Handling
|
|
|
|
Prevent command injection by properly quoting variables:
|
|
|
|
```yaml
|
|
# ❌ BAD - potential command injection
|
|
run: echo "Processing ${{ inputs.user_input }}"
|
|
|
|
# ✅ GOOD - properly quoted
|
|
env:
|
|
USER_INPUT: ${{ inputs.user_input }}
|
|
run: echo "Processing ${USER_INPUT}"
|
|
```
|
|
|
|
Use `${VARIABLE}` syntax in shell scripts instead of `$VARIABLE`.
|
|
|
|
### 5. Environment Variables for Secrets
|
|
|
|
Store sensitive data in environment variables, not inline:
|
|
|
|
```yaml
|
|
# ❌ BAD
|
|
run: curl -H "Authorization: Bearer ${{ secrets.TOKEN }}" api.example.com
|
|
|
|
# ✅ GOOD
|
|
env:
|
|
API_TOKEN: ${{ secrets.TOKEN }}
|
|
run: curl -H "Authorization: Bearer ${API_TOKEN}" api.example.com
|
|
```
|
|
|
|
## Workflow Structure Best Practices
|
|
|
|
### Required Workflow Elements
|
|
|
|
```yaml
|
|
name: "Descriptive Workflow Name"
|
|
|
|
on:
|
|
# Define specific triggers
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
# Always set explicit permissions
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
job-name:
|
|
name: "Descriptive Job Name"
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 30 # tune per job; standardize repo-wide
|
|
|
|
# Set job-level permissions if different from workflow level
|
|
permissions:
|
|
contents: read
|
|
|
|
steps:
|
|
# Always start with Harden-Runner on ubuntu-latest
|
|
- name: Harden the runner
|
|
uses: step-security/harden-runner@v2
|
|
with:
|
|
egress-policy: audit
|
|
|
|
# Pin all actions to commit SHA
|
|
- name: Checkout code
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
```
|
|
|
|
### Input Validation for Actions
|
|
|
|
For composite actions, always validate inputs:
|
|
|
|
```yaml
|
|
inputs:
|
|
user_input:
|
|
description: "User provided input"
|
|
required: true
|
|
|
|
runs:
|
|
using: "composite"
|
|
steps:
|
|
- name: Validate input
|
|
shell: bash
|
|
run: |
|
|
# Harden shell and validate input format/content before use
|
|
set -euo pipefail
|
|
|
|
USER_INPUT="${{ inputs.user_input }}"
|
|
|
|
if [[ ! "${USER_INPUT}" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
|
echo "❌ Invalid input format"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
## Docker Security in Actions
|
|
|
|
### Pin Docker Images to Digests
|
|
|
|
```yaml
|
|
# ❌ BAD - mutable tag
|
|
container: node:18
|
|
|
|
# ✅ GOOD - pinned to digest
|
|
container: node:18@sha256:a1ba21bf0c92931d02a8416f0a54daad66cb36a85d6a37b82dfe1604c4c09cad
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Secure File Operations
|
|
|
|
```yaml
|
|
- name: Process files securely
|
|
shell: bash
|
|
env:
|
|
FILE_PATH: ${{ inputs.file_path }}
|
|
run: |
|
|
set -euo pipefail # Fail on errors, undefined vars, pipe failures
|
|
|
|
# Use absolute paths and validate
|
|
SAFE_PATH=$(realpath "${FILE_PATH}")
|
|
if [[ "$SAFE_PATH" != "${GITHUB_WORKSPACE}"/* ]]; then
|
|
echo "❌ Path outside workspace"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
### Artifact Handling
|
|
|
|
```yaml
|
|
- name: Upload artifacts securely
|
|
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
|
with:
|
|
name: build-artifacts
|
|
path: |
|
|
dist/
|
|
!dist/**/*.log # Exclude sensitive files
|
|
retention-days: 30
|
|
```
|
|
|
|
### GHCR authentication for pulls/scans
|
|
|
|
```yaml
|
|
# Minimal permissions required for GHCR pulls/scans
|
|
permissions:
|
|
contents: read
|
|
packages: read
|
|
|
|
steps:
|
|
- name: Log in to GitHub Container Registry
|
|
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
```
|
|
|
|
## Security Checklist
|
|
|
|
- [ ] Minimum GITHUB_TOKEN permissions set
|
|
- [ ] Harden-Runner added to all ubuntu-latest jobs
|
|
- [ ] All third-party actions pinned to commit SHA
|
|
- [ ] Input validation implemented for custom actions
|
|
- [ ] Variables properly quoted in shell scripts
|
|
- [ ] Secrets stored in environment variables
|
|
- [ ] Docker images pinned to digests (if used)
|
|
- [ ] Error handling with `set -euo pipefail`
|
|
- [ ] File paths validated and sanitized
|
|
- [ ] No sensitive data in logs or outputs
|
|
- [ ] GHCR login performed before pulls/scans (packages: read)
|
|
- [ ] Job timeouts configured (`timeout-minutes`)
|
|
|
|
## Recommended Additional Workflows
|
|
|
|
Consider adding these security-focused workflows to your repository:
|
|
|
|
1. **CodeQL Analysis** - Static Application Security Testing (SAST)
|
|
2. **Dependency Review** - Scan for vulnerable dependencies in PRs
|
|
3. **Dependabot Configuration** - Automated dependency updates
|
|
|
|
## Resources
|
|
|
|
- [GitHub Security Hardening Guide](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions)
|
|
- [Step Security Harden-Runner](https://github.com/step-security/harden-runner)
|
|
- [Secure-Repo Best Practices](https://github.com/step-security/secure-repo)
|