PRD: Secure Actions — Supply Chain Security for CI Pipeline Actions

Status: Draft Author: CTO Agent Date: 2026-04-03 Updated: 2026-04-04 Issue: CAS-91


Problem

CI pipeline actions (GitHub Actions, GitLab CI templates, etc.) are a critical supply chain vector that most teams leave unmanaged. The majority of workflows pin actions to mutable version tags (actions/checkout@v4) that can be silently replaced by upstream maintainers — or by attackers who compromise an action repo. Even SHA-pinned actions can reference vulnerable dependency trees that no one audits.

CascadeGuard secures container images through the full lifecycle (build, scan, sign, quarantine, publish). The CI pipeline that runs those protections is itself unprotected. A compromised action in a workflow can exfiltrate secrets, inject malicious code into builds, or tamper with artifacts before signing — bypassing every downstream control.

There is no integrated tooling that applies the same supply chain principles (pinning, quarantine delays, vulnerability scanning, allowlisting) to CI pipeline actions. Existing point solutions (StepSecurity Harden-Runner, Socket) address subsets but don’t integrate with the image security posture CascadeGuard already provides.

Scope note: v1 targets GitHub Actions as the initial CI platform. The architecture, CLI, policy schema, and catalog are designed to be CI-platform-agnostic so that GitLab CI, CircleCI, and other providers can be added without breaking changes.

Goals

  1. Extend CascadeGuard’s supply chain model to CI pipelines — actions get the same pin, scan, quarantine treatment as container images
  2. Enforce action integrity — every action reference in a workflow resolves to an immutable, audited commit SHA
  3. Detect upstream risk — continuously monitor action repos for tag moves, force pushes, maintainer changes, and dependency vulnerabilities
  4. Unify the security posture view — actions appear alongside images in the CascadeGuard dashboard with the same vulnerability, compliance, and trust metrics
  5. Noun-verb CLI design — new functionality lives under cascadeguard actions <verb>, and existing flat verbs migrate to noun groups in this release

Non-Goals

  • Replacing platform-native action allowlist policies (we augment them with scanning and quarantine)
  • Running or executing actions (we analyze them statically)
  • Building a hosted action marketplace or mirror (v1 is policy + scanning only)
  • Forking or vendoring actions into customer repos

User Personas

DevSecOps Engineer (Primary)

Responsible for CI/CD security posture across 10–100 repos. Needs to enforce action pinning org-wide, respond to upstream action compromises, and report compliance status. Currently does this manually or not at all.

Application Developer

Writes and maintains CI workflows. Needs a frictionless way to pin actions, update them safely, and understand when an action they depend on has a known vulnerability. Does not want to manually look up commit SHAs.

Security Lead / CISO

Needs a single dashboard view of supply chain risk across both container images and CI pipelines. Requires audit evidence that all CI dependencies are pinned, scanned, and policy-compliant.


Functional Requirements

FR-1: SHA Pin Enforcement

IDRequirementPriorityAcceptance Criteria
FR-1.1CI check fails any workflow file containing a mutable action reference (@v4, @main, @master, @latest)P0Given a workflow with actions/checkout@v4, when the check runs, then the check fails with a message identifying the unpinned reference and its file:line location
FR-1.2CI check passes workflow files where all action references are full 40-char commit SHAsP0Given a fully-pinned workflow, when the check runs, then the check passes
FR-1.3Policy exceptions can allowlist specific actions for tag-based references with documented justificationP1Given an action in the exception list, when the check runs, then the check passes with an info-level annotation noting the exception

FR-2: Action Pinning & Update CLI (cascadeguard actions pin)

IDRequirementPriorityAcceptance Criteria
FR-2.1cascadeguard actions pin resolves all mutable tag references in workflow files to their current commit SHAP0Given a workflow with actions/checkout@v4, when the command runs, then the reference is replaced with actions/checkout@<sha> # v4.2.2
FR-2.2Pinning preserves a human-readable version comment after the SHAP0The output format is owner/repo@<40-char-sha> # <resolved-tag>
FR-2.3cascadeguard actions pin --check exits non-zero if any unpinned references exist, without modifying filesP1Exit code 1 with a list of unpinned references; exit code 0 if all pinned
FR-2.4cascadeguard actions pin enforces all configured supply chain controls — delay window (refuses to pin a version released less than N hours ago), allowlist/denylist policy, and trust score thresholdsP1Given delay_window_hours: 72 and an action version released 24h ago, the command skips that action and reports the remaining delay. Given a denied action, the command refuses to pin it
FR-2.5cascadeguard actions pin --update updates already-pinned SHAs to the latest version that satisfies all supply chain controls (delay window, policy, trust)P1Given an action with a newer version released 5 days ago and a 72h delay window, when the command runs, then the SHA is updated to the new version
FR-2.6cascadeguard actions pin --update --dry-run shows what would change without modifying filesP1Output lists each action, current version, available version, and whether supply chain controls are satisfied

FR-3: Action Audit CLI (cascadeguard actions audit)

IDRequirementPriorityAcceptance Criteria
FR-3.1cascadeguard actions audit produces a report of all actions used across workflow files with: owner, repo, pinned SHA (or tag), resolved version, known CVE countP0Output is a table (terminal) or JSON (--json) listing every unique action reference
FR-3.2Audit flags actions whose pinned SHA no longer matches the tag it was pinned from (drift detection)P1If v4 now points to a different SHA than what’s pinned, the report flags it as “drifted”
FR-3.3Audit flags actions from repos with fewer than 100 stars, no verified org badge, or last commit older than 12 monthsP2Trust signal warnings appear in the report for actions below threshold

FR-4: Actions Policy Configuration

IDRequirementPriorityAcceptance Criteria
FR-4.1Actions policy is defined as an extension of the existing .cascadeguard/config.yaml (or as a dedicated file in .cascadeguard/actions-policy.yaml). Both single-file and folder-based config layouts are supportedP0The schema is documented; cascadeguard actions policy validate validates the config regardless of layout
FR-4.2Default policy is deny — any action not in the allowlist fails the CI checkP1Given an action not in the allowlist, when the CI check runs, then it fails
FR-4.3cascadeguard actions policy init generates a starter policy from current workflow usageP1Running the command in a repo produces a policy pre-populated with all currently-used action owners and actions

FR-5: Action Vulnerability Scanning

IDRequirementPriorityAcceptance Criteria
FR-5.1For each pinned action, resolve its action.yml and identify runtime dependencies (Node package.json, Docker base images, composite sub-actions)P1Dependency tree is resolved and stored
FR-5.2Run Grype/Trivy against the resolved dependency tree and report CVEs with severityP1CVEs appear in cascadeguard actions audit output and in the dashboard
FR-5.3Composite actions are resolved recursively through the full transitive closure of sub-action referencesP1A composite action referencing another composite action is fully resolved
FR-5.4Action vulnerability data appears in the same catalog API that serves image vulnerabilitiesP1GET /api/catalog/actions/{owner}/{repo} returns vulnerability data in the same schema as image entries

FR-6: Upstream Monitoring

IDRequirementPriorityAcceptance Criteria
FR-6.1Subscribe to GitHub’s webhook/event firehose for monitored action repos to receive real-time notifications of releases, tag moves, and push eventsP1System receives events within minutes of occurrence; falls back to polling for repos that cannot be webhooked
FR-6.2Detect when an action tag is moved to a different commit SHA (tag tampering)P1Alert generated within 1 hour of detection
FR-6.3Detect force pushes to an action repo’s default branchP2Alert generated within 1 hour of detection
FR-6.4Detect changes to the action repo’s maintainer/collaborator listP2Alert generated within 24 hours of detection

Detection mechanism: The primary feed is GitHub’s webhook events API. For each action in a customer’s policy, CascadeGuard registers for release, push, member, and public events on the action’s source repo. For repos where webhooks cannot be installed (third-party public repos), a polling fallback checks git ls-remote refs and the GitHub API collaborators/releases endpoints on a configurable interval (default: 15 minutes). The expected cardinality is manageable — a typical enterprise uses 20–50 unique actions; even large orgs rarely exceed 200.

FR-7: Dashboard & Catalog Integration

IDRequirementPriorityAcceptance Criteria
FR-7.1”Actions” tab in the CascadeGuard dashboard shows all monitored actions with: name, pinned version, latest version, CVE count, policy compliance status, trust scoreP1Tab is visible to authenticated users; data updates within 1 hour of scan
FR-7.2Actions catalog API provides the same query, filter, and status interface as the images catalogP1GET /api/catalog/actions returns paginated action entries with vulnerability and compliance data
FR-7.3Actions and images are queryable through a unified searchP2Searching “CVE-2024-XXXX” returns both image and action results

Non-Functional Requirements

IDRequirementTargetMeasurement
NFR-1actions pin completes for a repo with 20 workflow files< 30 seconds (p95)CI timing data
NFR-2actions audit completes for a repo with 50 unique action references< 60 seconds (p95)CI timing data
NFR-3CI policy check adds to workflow runtime< 10 seconds (p95)CI step timing
NFR-4Upstream tag-move detection latency< 1 hour from eventMonitoring SLA
NFR-5Action vulnerability scan freshnessUpdated within 24 hours of upstream CVE database updateScan timestamp delta

CLI Design: Noun-Verb Pattern

All CascadeGuard CLI commands adopt a noun-verb pattern to group related operations under a resource namespace. This is consistent with kubectl, docker, gh, and other modern CLIs.

Actions commands

cascadeguard actions pin [--check] [--dry-run] [--update]
cascadeguard actions audit [--json] [--severity critical,high]
cascadeguard actions policy init
cascadeguard actions policy validate

Images commands (migration from flat verbs)

cascadeguard images validate     # was: cascadeguard validate
cascadeguard images enrol        # was: cascadeguard enrol
cascadeguard images check        # was: cascadeguard check
cascadeguard images build        # was: cascadeguard build
cascadeguard images status       # was: cascadeguard status

Policies commands

cascadeguard policies lint       # unified policy validation

Note: We are pre-v1 — there is no backwards-compatibility obligation. Flat verbs are removed in favour of the noun-verb structure.


Policy File Schema

Actions policy can be defined as part of the existing .cascadeguard/config.yaml under an actions key, or as a standalone .cascadeguard/actions-policy.yaml file, or as a file inside a .cascadeguard/ config folder (e.g. .cascadeguard/policies/actions.yaml). The CLI auto-discovers whichever layout is present.

# .cascadeguard/actions-policy.yaml (standalone)
# OR .cascadeguard/config.yaml under `actions:` key
# OR .cascadeguard/policies/actions.yaml (folder layout)
 
version: 1
 
# Default posture: deny requires explicit allowlisting; warn logs but does not fail
default: deny  # deny | warn | allow
 
# New action versions must be this old before pin commands accept them
delay_window_hours: 72
 
# Trusted action owners — all actions from these orgs are allowed
allowed_owners:
  - actions          # GitHub official
  - docker
  - sigstore
  - anchore
  - aquasecurity
 
# Specific allowed actions from non-trusted owners
allowed_actions:
  - cloudflare/wrangler-action
  - google-github-actions/auth
 
# Explicitly denied patterns
denied_actions:
  - "*/*@master"
  - "*/*@main"
  - "*/*@latest"
 
# Per-action exceptions with justification
exceptions:
  - action: internal-org/custom-action
    reason: "Internal action, pre-approved by security team"
    pin_required: false
    delay_window_hours: 0

Integration with Existing Features

CascadeGuard FeatureSecure Actions Integration
Image quarantine / delay windowSame delay model for action version adoption
Grype/Trivy scanningExtended to scan action dependency trees
SBOM generation (future)Generate SBOMs for action dependency trees
Cosign signing (future)Sign the actions-policy.yaml as attestation
generate-ci commandEmit SHA-pinned action refs by default
Dashboard / CVE view”Actions” tab alongside “Images” tab
Catalog APIExtend to include action entries

Dogfooding: Internal Rollout

Apply Secure Actions to CascadeGuard’s own repos before shipping to customers.

RepoCurrent StateAction Needed
cascadeguard-appFully SHA-pinnedAdd policy file, enable drift detection
cascadeguard-open-secure-imagesMostly SHA-pinned (2 anchore actions were unresolvable)Resolve anchore/setup-grype and anchore/setup-syft SHAs
cascadeguard (core CLI)Tag-pinnedRun actions pin, add policy file
cascadeguard-exemplarTag-pinned (auto-generated workflows)Update generate-ci to emit SHAs, regenerate
argocd-edaTag-pinned, trivy-action@masterPin all, replace @master reference
cascadeguard-state (formerly image-factory-state)Needs rename and policy fileRename repo, add policy file

Highest-risk finding: Multiple repos reference trivy-action@master — an unversioned, mutable reference to a security-critical action. This should be remediated immediately regardless of this PRD’s timeline.


Open Questions

  1. Delay window granularity — global default with per-action override, or per-owner override too? Recommendation: global + per-action.
  2. Action mirror/proxy — do we need a hosted cache of approved action SHAs (like our image proxy), or is policy enforcement sufficient for v1? Recommendation: policy-only for v1, mirror for v2.
  3. GitHub App vs reusable workflow — CI enforcement can be a GitHub App check (auto-runs on all PRs) or a reusable workflow (repo must opt in). Recommendation: ship reusable workflow first (lower barrier), GitHub App second. This goes in our core open source CLI tool.

Success Criteria

v1 (MVP)

v1 is the minimum viable product — it must be viable enough for customers to adopt.

  • cascadeguard actions pin correctly resolves tags to SHAs across all workflow files
  • cascadeguard actions pin --update updates pinned SHAs to latest versions satisfying supply chain controls
  • cascadeguard actions audit produces an accurate inventory with CVE data
  • Actions policy configuration defined and validated (supports all config layouts)
  • CI check (reusable workflow) enforces pin and policy requirements
  • Delay window enforcement operational
  • Action dependency scanning integrated with Grype/Trivy
  • Upstream tag-move and force-push detection active
  • Dashboard “Actions” tab live with vulnerability and compliance data
  • Actions catalog API operational with same schema as images
  • All CascadeGuard-owned repos are fully SHA-pinned with policy files
  • Existing flat CLI verbs migrated to noun-verb pattern
  • Customer documentation published

Growth Metrics

  • 80% of repos with CascadeGuard CI also adopt actions policy within 90 days of feature launch
  • Mean time to detect upstream action compromise < 1 hour
  • Zero unpinned action references across all customer repos using the policy check