# Starter Policy Pack Guide This guide covers the StellaOps starter policy pack (`starter-day1`), a production-ready policy designed for organizations beginning their software supply chain security journey. ## Quick Start Install and activate the starter policy in under 5 minutes: ```bash # Install the starter policy pack stellaops policy install starter-day1 # Validate a policy file stellaops policy validate policies/starter-day1.yaml # Simulate policy against a scan stellaops policy simulate --policy policies/starter-day1.yaml --scan ``` ## Overview The starter policy implements a sensible security posture: | What | Action | Rationale | |------|--------|-----------| | Reachable HIGH/CRITICAL vulnerabilities | **Block** | Highest risk - exploitable code paths | | Reachable MEDIUM vulnerabilities | **Warn** | Moderate risk - review recommended | | Unreachable vulnerabilities | **Allow** (logged) | Low risk - no exploitable path | | VEX-covered vulnerabilities | **Allow** | Evidence-based exception | | Unknowns > 5% of packages | **Block** | Quality gate for metadata coverage | | Unsigned SBOM (production) | **Block** | Integrity requirement | | Unsigned verdict (production) | **Block** | Compliance attestation | ## Rule-by-Rule Explanation ### Rule 1: Block Reachable HIGH/CRITICAL ```yaml - name: block-reachable-high-critical description: "Block deployments with reachable HIGH or CRITICAL vulnerabilities" match: severity: - CRITICAL - HIGH reachability: reachable unless: vexStatus: not_affected vexJustification: - vulnerable_code_not_present - vulnerable_code_cannot_be_controlled_by_adversary - inline_mitigations_already_exist action: block message: "Reachable {severity} vulnerability {cve} must be remediated or have VEX justification" ``` **What it does**: Blocks any deployment containing HIGH or CRITICAL severity vulnerabilities where the vulnerable code is reachable (can be executed). **VEX bypass**: If a VEX statement marks the vulnerability as `not_affected` with proper justification, the block is bypassed. Valid justifications: - `vulnerable_code_not_present` - The vulnerable function isn't compiled in - `vulnerable_code_cannot_be_controlled_by_adversary` - Input cannot reach vulnerable code - `inline_mitigations_already_exist` - Application-level mitigations in place ### Rule 2: Warn on Reachable MEDIUM ```yaml - name: warn-reachable-medium description: "Warn on reachable MEDIUM severity vulnerabilities" match: severity: MEDIUM reachability: reachable unless: vexStatus: not_affected action: warn message: "Reachable MEDIUM vulnerability {cve} should be reviewed" ``` **What it does**: Generates a warning (but allows deployment) for MEDIUM severity reachable vulnerabilities. **When to upgrade**: If your security posture matures, consider changing `action: warn` to `action: block`. ### Rule 3: Allow Unreachable ```yaml - name: ignore-unreachable description: "Allow unreachable vulnerabilities but log for awareness" match: reachability: unreachable action: allow log: true message: "Vulnerability {cve} is unreachable - allowing" ``` **What it does**: Allows vulnerabilities where static analysis proves the code cannot be reached. **Logging**: Even allowed findings are logged for audit purposes. ### Rule 4: Unknowns Budget ```yaml - name: fail-on-unknowns description: "Block if too many packages have unknown metadata" type: aggregate match: unknownsRatio: gt: ${settings.unknownsThreshold} action: block message: "Unknown packages exceed threshold ({unknownsRatio}% > {threshold}%)" ``` **What it does**: Blocks deployment if more than 5% of packages lack sufficient metadata for analysis. **Why**: High unknowns ratio indicates poor SBOM quality or unsupported package ecosystems. ### Rules 5-6: Signed Artifacts (Production) ```yaml - name: require-signed-sbom-prod match: environment: production require: signedSbom: true action: block message: "Production deployment requires signed SBOM" - name: require-signed-verdict-prod match: environment: production require: signedVerdict: true action: block message: "Production deployment requires signed verdict" ``` **What they do**: Require cryptographically signed SBOM and verdict attestations for production environments. **Why**: Ensures integrity and non-repudiation of security assessments. ### Rule 7: Default Allow ```yaml - name: default-allow description: "Allow everything not matched by above rules" match: always: true action: allow ``` **What it does**: Explicit default action for any finding not matched by prior rules. ## Environment Overrides The starter policy supports environment-specific overrides: ### Development (`overrides/development.yaml`) ```yaml apiVersion: policy.stellaops.io/v1 kind: PolicyOverride metadata: name: starter-day1-dev parent: starter-day1 environment: development spec: settings: defaultAction: warn # Never block in dev unknownsThreshold: 0.20 # Allow more unknowns (20%) ruleOverrides: - name: block-reachable-high-critical action: warn # Downgrade to warn - name: require-signed-sbom-prod enabled: false # Disable signing requirements - name: require-signed-verdict-prod enabled: false ``` ### Staging (`overrides/staging.yaml`) ```yaml apiVersion: policy.stellaops.io/v1 kind: PolicyOverride metadata: name: starter-day1-staging parent: starter-day1 environment: staging spec: settings: unknownsThreshold: 0.10 # 10% unknowns budget ruleOverrides: - name: require-signed-sbom-prod enabled: false # No signing in staging ``` ### Production (Default) Production uses the base policy with all rules enabled. ## Customization Guide ### Adjusting Severity Thresholds To block MEDIUM vulnerabilities too: ```yaml ruleOverrides: - name: warn-reachable-medium action: block ``` ### Changing Unknowns Budget To allow 10% unknowns: ```yaml settings: unknownsThreshold: 0.10 ``` ### Adding Custom Rules Insert rules before `default-allow`: ```yaml rules: # ... existing rules ... # Custom: Block specific CVE - name: block-specific-cve match: cve: CVE-2024-1234 action: block message: "CVE-2024-1234 is explicitly blocked by policy" - name: default-allow match: always: true action: allow ``` ### Source Allowlists Trust only specific VEX sources: ```yaml settings: vexSources: allowlist: - redhat-csaf - canonical-usn - vendor-security requireTrustScore: 0.7 ``` ## Troubleshooting ### "Reachable HIGH vulnerability must be remediated" **Cause**: A HIGH/CRITICAL vulnerability exists in code that can execute. **Solutions**: 1. Update the affected package to a fixed version 2. Create a VEX statement if the vulnerability doesn't apply: ```bash stellaops vex create --cve CVE-2024-1234 --status not_affected \ --justification vulnerable_code_not_present ``` 3. Apply a temporary exception (with approval): ```yaml exceptions: - cve: CVE-2024-1234 expires: 2025-02-01 approver: security-team reason: "Patch scheduled for next sprint" ``` ### "Unknown packages exceed threshold" **Cause**: Too many packages lack metadata for vulnerability analysis. **Solutions**: 1. Ensure SBOMs are complete with package versions 2. Check for unsupported package ecosystems 3. Temporarily increase threshold in non-production: ```yaml settings: unknownsThreshold: 0.15 ``` ### "Production deployment requires signed SBOM" **Cause**: Attempting production deployment without signed SBOM. **Solutions**: 1. Sign SBOM during build: ```bash stellaops sbom sign --sbom sbom.json --key-id ``` 2. Verify signing is configured in CI/CD pipeline ### Rule Not Matching as Expected Use simulation mode to debug: ```bash stellaops policy simulate --policy policy.yaml --scan --verbose ``` Check: - Rule order (first match wins) - Severity casing (use uppercase: HIGH, CRITICAL) - Reachability values (reachable, unreachable, unknown) ## Migration Path to Custom Policies ### Step 1: Start with Starter Policy Deploy `starter-day1` as-is to establish baseline. ### Step 2: Monitor and Tune Review policy decisions for 2-4 weeks: - Which rules trigger most? - Which findings need exceptions? - What patterns emerge? ### Step 3: Create Overlays Add overlays for organization-specific needs: ```yaml apiVersion: policy.stellaops.io/v1 kind: PolicyOverride metadata: name: acme-corp-policy parent: starter-day1 spec: ruleOverrides: - name: block-reachable-high-critical unless: # Add company-specific VEX sources vexSource: - acme-security-team ``` ### Step 4: Graduate to Custom Policy When ready, fork the starter policy and customize fully: ```bash # Export starter policy as starting point stellaops policy pull --from registry.stellaops.io/policies/starter-day1:1.0.0 \ --output ./my-custom-policy/ # Modify as needed vim ./my-custom-policy/base.yaml # Validate changes stellaops policy validate ./my-custom-policy/ # Push to your registry stellaops policy push --policy ./my-custom-policy/base.yaml \ --to myregistry.example.com/policies/acme-policy:1.0.0 --sign ``` ## CLI Reference | Command | Description | |---------|-------------| | `stellaops policy validate ` | Validate policy against schema | | `stellaops policy install ` | Install policy pack | | `stellaops policy list-packs` | List available policy packs | | `stellaops policy simulate --policy --scan ` | Simulate policy evaluation | | `stellaops policy push --policy --to ` | Push to OCI registry | | `stellaops policy pull --from ` | Pull from OCI registry | | `stellaops policy export-bundle --policy --output ` | Create offline bundle | | `stellaops policy import-bundle --bundle ` | Import offline bundle | ## See Also - [Policy DSL Reference](dsl.md) - [VEX Trust Model](vex-trust-model.md) - [Policy Governance](governance.md) - [Scoring Profiles](scoring-profiles.md)