|
| 1 | +--- |
| 2 | +name: 🔒 Security: CI/CD Workflow Security Hardening |
| 3 | +about: Strengthen CI/CD workflow security configuration and permissions |
| 4 | +title: 'Security: Harden CI/CD workflows against advanced attack vectors' |
| 5 | +labels: ['security', 'ci', 'workflow', 'medium-priority'] |
| 6 | +assignees: [] |
| 7 | +--- |
| 8 | + |
| 9 | +## Security Issue: CI/CD Workflow Security Hardening |
| 10 | + |
| 11 | +### Summary |
| 12 | +While the current CI/CD workflows implement some security best practices, there are additional hardening measures that could prevent sophisticated supply chain attacks and improve overall security posture. |
| 13 | + |
| 14 | +### Current Security Analysis |
| 15 | + |
| 16 | +#### Positive Security Measures ✅ |
| 17 | +- Uses `step-security/harden-runner` with egress policy restrictions |
| 18 | +- Pins GitHub Actions to specific commit SHAs (good practice) |
| 19 | +- Separates staging and production deployments |
| 20 | +- Implements deployment failure notifications |
| 21 | +- Uses CodeQL for static analysis |
| 22 | +- Implements dependency review on PRs |
| 23 | + |
| 24 | +#### Areas for Improvement ⚠️ |
| 25 | +- Missing explicit workflow permissions (defaults to broad permissions) |
| 26 | +- No protection against fork pull request attacks |
| 27 | +- Long-lived API tokens instead of OIDC |
| 28 | +- No supply chain security attestation |
| 29 | +- Missing workflow run provenance |
| 30 | +- No secrets scanning in CI |
| 31 | + |
| 32 | +### Potential Attack Vectors |
| 33 | + |
| 34 | +#### 1. Malicious Fork Pull Requests |
| 35 | +- **Scenario**: Attacker creates fork, modifies workflows, opens PR |
| 36 | +- **Risk**: Could extract secrets or modify deployment process |
| 37 | +- **Likelihood**: Medium |
| 38 | +- **Impact**: Critical (supply chain compromise) |
| 39 | + |
| 40 | +#### 2. Compromised Dependencies During CI |
| 41 | +- **Scenario**: Malicious npm package runs during `npm install` in CI |
| 42 | +- **Risk**: Could exfiltrate secrets or modify build output |
| 43 | +- **Likelihood**: Medium-High |
| 44 | +- **Impact**: Critical |
| 45 | + |
| 46 | +#### 3. GitHub Actions Supply Chain Attack |
| 47 | +- **Scenario**: Compromised third-party action executes malicious code |
| 48 | +- **Risk**: Full CI environment compromise |
| 49 | +- **Likelihood**: Low-Medium |
| 50 | +- **Impact**: Critical |
| 51 | + |
| 52 | +#### 4. Privilege Escalation |
| 53 | +- **Scenario**: Workflows with excessive permissions exploited |
| 54 | +- **Risk**: Unauthorized repository modifications or secret access |
| 55 | +- **Likelihood**: Medium |
| 56 | +- **Impact**: High |
| 57 | + |
| 58 | +### Recommended Security Hardening |
| 59 | + |
| 60 | +#### High Priority |
| 61 | + |
| 62 | +##### 1. Implement Explicit Workflow Permissions |
| 63 | +```yaml |
| 64 | +permissions: |
| 65 | + contents: read |
| 66 | + deployments: write |
| 67 | + id-token: write # For OIDC |
| 68 | +``` |
| 69 | +
|
| 70 | +##### 2. Add Fork PR Protection |
| 71 | +```yaml |
| 72 | +# Only run on approved PRs from forks |
| 73 | +if: github.event.pull_request.head.repo.full_name == github.repository || contains(github.event.label.name, 'safe to test') |
| 74 | +``` |
| 75 | +
|
| 76 | +##### 3. Implement OIDC Authentication |
| 77 | +- Replace `CF_API_TOKEN` with OIDC token authentication |
| 78 | +- Reduces long-lived secret exposure risk |
| 79 | +- Provides better audit trail |
| 80 | + |
| 81 | +##### 4. Add Secrets Scanning |
| 82 | +```yaml |
| 83 | +- name: Run Secrets Scan |
| 84 | + uses: trufflesecurity/trufflehog@main |
| 85 | + with: |
| 86 | + path: ./ |
| 87 | + base: main |
| 88 | + head: HEAD |
| 89 | +``` |
| 90 | + |
| 91 | +#### Medium Priority |
| 92 | + |
| 93 | +##### 5. Enhanced Supply Chain Security |
| 94 | +```yaml |
| 95 | +- name: Generate SLSA Provenance |
| 96 | + uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected] |
| 97 | +``` |
| 98 | + |
| 99 | +##### 6. Implement Workflow Attestation |
| 100 | +- Sign workflow runs with Sigstore |
| 101 | +- Create verifiable supply chain attestations |
| 102 | +- Enable verification of deployment provenance |
| 103 | + |
| 104 | +##### 7. Add Runtime Security Monitoring |
| 105 | +```yaml |
| 106 | +- name: Monitor Runtime Security |
| 107 | + uses: step-security/harden-runner@v2 |
| 108 | + with: |
| 109 | + egress-policy: audit # More restrictive than current 'block' |
| 110 | + disable-sudo: true |
| 111 | + disable-file-monitoring: false |
| 112 | +``` |
| 113 | + |
| 114 | +#### Low Priority |
| 115 | + |
| 116 | +##### 8. Implement Branch Protection Rules |
| 117 | +- Require status checks to pass |
| 118 | +- Require up-to-date branches |
| 119 | +- Require signed commits from maintainers |
| 120 | +- Dismiss stale reviews on new commits |
| 121 | + |
| 122 | +##### 9. Add Deployment Environment Protection |
| 123 | +```yaml |
| 124 | +environment: |
| 125 | + name: production |
| 126 | + url: https://dist.nodejs.org |
| 127 | +``` |
| 128 | + |
| 129 | +##### 10. Enhanced Monitoring and Alerting |
| 130 | +- Monitor for unusual workflow execution patterns |
| 131 | +- Alert on failed security checks |
| 132 | +- Track deployment frequency and patterns |
| 133 | + |
| 134 | +### Specific Workflow Improvements |
| 135 | + |
| 136 | +#### deploy.yml |
| 137 | +```yaml |
| 138 | +# Add explicit permissions |
| 139 | +permissions: |
| 140 | + contents: read |
| 141 | + deployments: write |
| 142 | + id-token: write |
| 143 | +
|
| 144 | +# Add environment protection for production |
| 145 | +environment: |
| 146 | + name: ${{ github.event_name == 'workflow_dispatch' && 'production' || 'staging' }} |
| 147 | +
|
| 148 | +# Replace API token with OIDC |
| 149 | +- name: Deploy with OIDC |
| 150 | + uses: cloudflare/wrangler-action@v3 |
| 151 | + with: |
| 152 | + # Remove: apiToken: ${{ secrets.CF_API_TOKEN }} |
| 153 | + accountId: ${{ secrets.CF_ACCOUNT_ID }} |
| 154 | + command: deploy --env ${{ github.event_name == 'workflow_dispatch' && 'prod' || 'staging' }} |
| 155 | +``` |
| 156 | + |
| 157 | +#### test.yml |
| 158 | +```yaml |
| 159 | +# Add fork protection |
| 160 | +if: | |
| 161 | + github.event.pull_request.head.repo.full_name == github.repository || |
| 162 | + contains(github.event.label.name, 'safe to test') |
| 163 | +
|
| 164 | +# Add explicit permissions |
| 165 | +permissions: |
| 166 | + contents: read |
| 167 | + checks: write |
| 168 | + pull-requests: write |
| 169 | +``` |
| 170 | + |
| 171 | +#### New: security-scan.yml |
| 172 | +```yaml |
| 173 | +name: Security Scan |
| 174 | +
|
| 175 | +on: |
| 176 | + push: |
| 177 | + branches: [main] |
| 178 | + pull_request: |
| 179 | + branches: [main] |
| 180 | + schedule: |
| 181 | + - cron: '0 0 * * 0' # Weekly |
| 182 | +
|
| 183 | +permissions: |
| 184 | + contents: read |
| 185 | + security-events: write |
| 186 | +
|
| 187 | +jobs: |
| 188 | + secrets-scan: |
| 189 | + runs-on: ubuntu-latest |
| 190 | + steps: |
| 191 | + - uses: actions/checkout@v4 |
| 192 | + with: |
| 193 | + fetch-depth: 0 |
| 194 | + |
| 195 | + - name: Run Trufflehog |
| 196 | + uses: trufflesecurity/trufflehog@main |
| 197 | + with: |
| 198 | + path: ./ |
| 199 | + base: ${{ github.event.repository.default_branch }} |
| 200 | + head: HEAD |
| 201 | +``` |
| 202 | + |
| 203 | +### Implementation Plan |
| 204 | + |
| 205 | +#### Phase 1: Critical Security (Week 1) |
| 206 | +- [ ] Add explicit permissions to all workflows |
| 207 | +- [ ] Implement fork PR protection |
| 208 | +- [ ] Add secrets scanning workflow |
| 209 | +- [ ] Update step-security/harden-runner configuration |
| 210 | + |
| 211 | +#### Phase 2: Authentication Hardening (Week 2) |
| 212 | +- [ ] Implement Cloudflare OIDC authentication |
| 213 | +- [ ] Remove long-lived API tokens |
| 214 | +- [ ] Add environment protection for production |
| 215 | +- [ ] Test new authentication flow |
| 216 | + |
| 217 | +#### Phase 3: Supply Chain Security (Week 3) |
| 218 | +- [ ] Implement SLSA provenance generation |
| 219 | +- [ ] Add workflow attestation |
| 220 | +- [ ] Enhance dependency monitoring |
| 221 | +- [ ] Add build reproducibility measures |
| 222 | + |
| 223 | +#### Phase 4: Monitoring and Alerting (Week 4) |
| 224 | +- [ ] Implement advanced monitoring |
| 225 | +- [ ] Add security metrics collection |
| 226 | +- [ ] Create incident response automation |
| 227 | +- [ ] Document new security procedures |
| 228 | + |
| 229 | +### Testing and Validation |
| 230 | + |
| 231 | +#### Security Testing Checklist |
| 232 | +- [ ] Test fork PR protection (create test fork) |
| 233 | +- [ ] Verify OIDC authentication works |
| 234 | +- [ ] Confirm secrets scanning catches test secrets |
| 235 | +- [ ] Validate restricted permissions don't break workflows |
| 236 | +- [ ] Test incident response procedures |
| 237 | + |
| 238 | +#### Rollback Plan |
| 239 | +- Keep current workflows as backup |
| 240 | +- Implement changes incrementally |
| 241 | +- Test each change in isolation |
| 242 | +- Have immediate rollback capability for production |
| 243 | + |
| 244 | +### References |
| 245 | +- [GitHub Actions Security Hardening](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions) |
| 246 | +- [SLSA Supply Chain Framework](https://slsa.dev/) |
| 247 | +- [OpenSSF Scorecard](https://github.com/ossf/scorecard) |
| 248 | +- [Cloudflare OIDC Documentation](https://developers.cloudflare.com/workers/wrangler/ci-cd/#oidc-authentication) |
0 commit comments