ci-cd-ssdf-security
- Repo stars 0
- Author repo skills-registry
Context
CI/CD pipelines are high-value targets — they hold secrets, produce deployable artifacts, and run with elevated permissions. A misconfigured GitHub Actions workflow can leak credentials, allow unauthorized deployments, or execute attacker-controlled code with write access to the repository. This skill covers GitHub Actions permission hardening, pinned action SHAs, secret hygiene, OIDC federation, pull_request_target risks, release security, and alignment with NIST SSDF practices — including AI-specific considerations from SP 800-218A.
Best used for
GitHub Actions, Azure DevOps, release workflows, and compliance-sensitive repos. Use this skill when reviewing workflow files, pipeline configurations, deployment processes, and any CI/CD changes that affect build integrity or secret handling.
Primary references
- NIST SP 800-218 Secure Software Development Framework (SSDF): https://csrc.nist.gov/pubs/sp/800/218/final
- NIST SP 800-218A Generative AI and SSDF Practices: https://csrc.nist.gov/pubs/sp/800/218/a/final
- GitHub Actions Security Hardening: https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions
- Microsoft Learn — Custom CodeQL Queries: https://learn.microsoft.com/en-us/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning
Patterns
GITHUB_TOKEN minimum permissions
Without a permissions: block, the token defaults to write-all. Every workflow must declare minimum permissions at the workflow level, granting additional scopes only at the job level where needed.
Least-privilege baseline (workflow level):
permissions: {} # deny all at workflow level; grant per job only
Scope only what each job needs:
jobs:
build:
permissions:
contents: read
release:
permissions:
contents: write
attestations: write
id-token: write
Pinned action SHAs
Tags like @v4 are mutable — a compromised upstream can retag to malicious code. Pin to full commit SHAs with version comments. Use npx pin-github-action .github/workflows/*.yml to automate.
Secrets in workflows
- Always use
${{ secrets.NAME }}— never pass secrets through environment variable indirection. - Never
echoa secret. GitHub masks known secrets, but novel derivations may leak. - Use
::add-mask::for dynamically generated sensitive values. Note: masking only applies to log output after the line where it is set — any value logged before the mask command remains visible. - Never pass secrets to untrusted third-party actions — audit source first.
pull_request_target risk
pull_request_target runs in the base repository context with write permissions and access to secrets — even for fork PRs. If the workflow checks out fork code, an attacker controls what runs with elevated privileges.
If pull_request_target is genuinely required (e.g., labeling), never check out or execute code from the PR head — only read metadata.
OIDC federation vs long-lived credentials
Long-lived cloud credentials stored as secrets do not expire, cannot be scoped to a single run, and are hard to rotate. Prefer OIDC federation (id-token: write) for Azure, AWS, and GCP — tokens are short-lived, audience-scoped, and tied to the specific workflow run.
Build reproducibility
Reproducible builds require deterministic dependency resolution:
- Commit
packages.lock.jsonand restore with--locked-mode. - Pin all tool versions (SDK, runtime, Node.js) in
global.jsonor workflowsetup-*actions. - Avoid floating refs in action inputs (e.g.,
dotnet-version: 8.x— use8.0.401).
Static analysis in CI
Enable CodeQL or GitHub Advanced Security. Requires security-events: write to upload SARIF results to the Security tab. Configure for all project languages; run on every PR and push to the default branch.
Release security
- Environment protection rules: require manual approval for production.
- Required reviewers: at least one reviewer before deployment.
- Artifact attestation:
actions/attest-build-provenancefor signed SLSA provenance (requiresattestations: writeandid-token: writepermissions). - Branch protection: require CI pass and PR reviews before merge to
main; disallow direct pushes.
SSDF alignment
- PO.1 (Define security requirements): CI/CD pipelines should enforce security requirements automatically — static analysis, dependency review, secret scanning.
- PW.4 (Reuse existing, well-secured software): pin action versions, verify third-party actions before adoption, prefer official actions from
actions/*and verified publishers. - RV.1 (Identify vulnerabilities): integrate CodeQL, dependency review, and secret scanning into every PR.
- RV.2 (Assess, prioritize, and remediate): track and triage findings from CI security tools within defined SLAs.
AI-generated workflow considerations (SP 800-218A)
AI tools can generate or modify GitHub Actions workflows. Risks include:
- Suggesting
pull_request_targetwithout understanding the security implications. - Omitting
permissions:blocks (defaulting to overly broad access). - Using mutable action tags instead of pinned SHAs.
- Introducing workflow steps that echo or expose secrets.
- Generating composite actions with unnecessary
GITHUB_TOKENusage.
Review action: treat all AI-generated workflow changes as untrusted input. Review line-by-line against this skill's patterns before merging.
Anti-Patterns
- No
permissions:block in workflow (defaults towrite-all). pull_request_targetwithactions/checkoutreferencinggithub.event.pull_request.head.sha.- Secrets echoed to logs:
echo ${{ secrets.TOKEN }}orenv | grep. - Mutable action tags (
@v4,@main) instead of pinned SHAs. - Long-lived cloud credentials as secrets instead of OIDC federation.
- No branch protection rules on
main— direct pushes allowed. - CodeQL or security scanning not enabled on repositories with deployed services.
- Missing
environment:gates for production deployments. - AI-generated workflow files merged without manual security review.
Examples
BAD — no permissions, mutable tags, secret echo, untrusted action:
on: push
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: echo "Deploying with token ${{ secrets.DEPLOY_TOKEN }}"
- uses: some-org/deploy-action@main
with:
token: ${{ secrets.DEPLOY_TOKEN }}
GOOD — minimal permissions, pinned SHAs, OIDC, environment gate:
permissions:
contents: read
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- run: dotnet publish -c Release
BAD — pull_request_target checking out fork code:
on: pull_request_target
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
ref: ${{ github.event.pull_request.head.sha }}
- run: dotnet test # attacker-controlled code runs with write token
GOOD — pull_request for untrusted code:
on: pull_request
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- run: dotnet test
Review cues
- Every workflow file has an explicit
permissions:block at the workflow or job level. - Permissions follow least privilege — only the scopes the job actually needs.
- All
uses:references are pinned to full commit SHAs with version comments. - No
pull_request_targetworkflows check out or execute PR head code. - Secrets are accessed only via
${{ secrets.NAME }}— never echoed, printed, or passed to untrusted actions. - Cloud authentication uses OIDC federation, not long-lived credential secrets.
- Production deployments use
environment:with protection rules and required reviewers. - CodeQL or equivalent static analysis runs on every PR and pushes to default branch.
-
security-events: writeis granted only to jobs that upload SARIF results. - Branch protection requires CI pass and PR review before merge to
main. - AI-generated workflow changes have been manually reviewed against these patterns.
- Artifact attestation is configured for release artifacts.
Good looks like
- Every workflow declares
permissions: contents: readat minimum, with additional scopes only at job level. - All action references are pinned to immutable SHAs with descriptive version comments.
- Cloud auth uses OIDC federation — no long-lived credential secrets in the repository.
pull_request_targetis not used, or is used only for metadata operations (labeling) without checking out PR code.- Secrets are never logged;
::add-mask::is used for dynamically generated sensitive values. - CodeQL runs on every PR; SARIF results are uploaded to GitHub Security tab.
- Production deployments require environment approval gates and reviewer sign-off.
- Build artifacts have signed provenance attestations.
- Branch protection is enforced: CI must pass, PRs required, no direct pushes to
main. - AI-generated workflow modifications are flagged for manual review in the PR process.
Common findings / likely remediations
| Finding | Severity | Likely remediation |
|---|---|---|
No permissions: block (defaults to write-all) |
High | Add explicit permissions: with minimum required scopes |
pull_request_target with checkout of PR head |
Critical | Switch to pull_request trigger or remove checkout of untrusted ref |
| Secrets echoed to workflow logs | Critical | Remove echo statements; use ::add-mask:: for dynamic values |
Mutable action tags (@v4, @main) |
Medium | Pin to full SHA; add version comment; use pin-github-action tooling |
| Long-lived cloud credentials as secrets | High | Migrate to OIDC federation with id-token: write permission |
| No branch protection on default branch | High | Enable required PR reviews, required CI checks, disallow direct push |
| CodeQL / static analysis not configured | Medium | Add CodeQL workflow with security-events: write; configure for project languages |
| No environment protection for production | High | Create production environment with required reviewers and wait timer |
| AI-generated workflow merged without review | Medium | Establish team policy: all workflow changes require manual security review |
| No artifact attestation on release builds | Medium | Add actions/attest-build-provenance to release workflow |
<!-- tomevault:4.0:skill_md:2026-05-22 -->Source: betaio/LLMTestProject — distributed by TomeVault.
- Fluxly category
- DevOps
- Author-declared agents
- No explicit declaration found; this is not inferred or tested compatibility
- Static check
- 88 / 100 · heuristic scan, not runtime safety proof
- Author / version / license
- @tomevault-io · no license declared
- Fluxly token estimate
- Lean
- Fluxly setup estimate
- Manual integration
- External API key
- Required · GitHub
- Detected OS requirements
- Linux
- Runtime requirements
- Node.js
- Detected file/system behavior
-
- Read-only
- Write / modify
- Shell exec
- Env read
- Detected network behavior
- External requests
- Install commands
- None (reference only)
Profile is derived at build time from SKILL.md and install vectors. Subject to drift from author intent.
Heads up: 未限定 allowed-tools,默认拥有全部工具权限。
The current SKILL.md does not define a fixed output example. CI/CD pipelines are high-value targets — they hold secrets, produce deployable artifacts, and run with elevated permissions. A misconfigured GitHub Actions workflow can leak credentials, allow unauthorized deployments, or execute attacker-controlled code with…
GitHub Actions, Azure DevOps, release workflows, and compliance-sensitive repos. Use this skill when reviewing workflow files, pipeline configurations, deployment processes, and any CI/CD changes that affect build integrity or secret handling.
NIST SP 800-218 Secure Software Development Framework (SSDF): https://csrc.nist.gov/pubs/sp/800/218/final NIST SP 800-218A Generative AI and SSDF Practices: https://csrc.nist.gov/pubs/sp/800/218/a/final GitHub Actions Security Hardening:…
Patterns
Without a permissions: block, the token defaults to write-all. Every workflow must declare minimum permissions at the workflow level, granting additional scopes only at the job level where needed. Least-privilege baseline (workflow level):
Tags like @v4 are mutable — a compromised upstream can retag to malicious code. Pin to full commit SHAs with version comments. Use npx pin-github-action .github/workflows/.yml to automate.
## Context
CI/CD pipelines are high-value targets — they hold secrets, produce deployable artifacts, and run with elevated permissions. A misconfigured GitHub Actions workflow can leak credentials, allow unauthorized deployments, or execute attacker-controlled code with write access to the repository. This skill covers GitHub Actions permission hardening, pinned action SHAs, secret hygiene, OIDC federation, `pull_request_target` risks, release security, and alignment with NIST SSDF practices — including AI-specific considerations from SP 800-218A.
## Best used for
GitHub Actions, Azure DevOps, release workflows, and compliance-sensitive repos. Use this skill when reviewing workflow files, pipeline configurations, deployment processes, and any CI/CD changes that affect build integrity or secret handling.
## Primary references
- NIST SP 800-218 Secure Software Development Framework (SSDF): https://csrc.nist.gov/pubs/sp/800/218/final
- NIST SP 800-218A Generative AI and SSDF Practices: https://csrc.nist.gov/pubs/sp/800/218/a/final
- GitHub Actions Security Hardening: https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions
- Microsoft Learn — Custom CodeQL Queries: https://learn.microsoft.com/en-us/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning
## Patterns
### `GITHUB_TOKEN` minimum permissions
Without a `permissions:` block, the token defaults to `write-all`. Every workflow must declare minimum permissions at the workflow level, granting additional scopes only at the job level where needed.
**Least-privilege baseline (workflow level):**
```yaml
permissions: {} # deny all at workflow level; grant per job only
```
… Author text anchors workflow facts; Fluxly only indexes current sections, terms, files, and commands.
sections -> Context → Best used for → Primary references → Patterns → GITHUBTOKEN minimum permissions → Pinned action SHAs
terms -> Least-privilege baseline (workflow level) · Scope only what each job needs · after · base repository context · Environment protection rules · Required reviewers · Artifact attestation · Branch protection
files/cmd -> pullrequesttarget · GITHUBTOKEN · permissions: · write-all · @v4 · npx pin-github-action .github/workflows/.yml · ${{ secrets.NAME }} · echo
body sha256 -> fe8ae0be78ad
Decide Fit First
Design Intent
How To Use It
Boundaries And Review