- Created `StellaOps.AuditPack.Tests.csproj` for unit testing the AuditPack library. - Implemented comprehensive unit tests in `index.test.js` for AST parsing, covering various JavaScript and TypeScript constructs including functions, classes, decorators, and JSX. - Added `sink-detect.test.js` to test security sink detection patterns, validating command injection, SQL injection, file write, deserialization, SSRF, NoSQL injection, and more. - Included tests for taint source detection in various contexts such as Express, Koa, and AWS Lambda.
10 KiB
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:
# 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 <scan-id>
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
- 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 invulnerable_code_cannot_be_controlled_by_adversary- Input cannot reach vulnerable codeinline_mitigations_already_exist- Application-level mitigations in place
Rule 2: Warn on Reachable MEDIUM
- 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
- 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
- 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)
- 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
- 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)
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)
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:
ruleOverrides:
- name: warn-reachable-medium
action: block
Changing Unknowns Budget
To allow 10% unknowns:
settings:
unknownsThreshold: 0.10
Adding Custom Rules
Insert rules before default-allow:
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:
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:
- Update the affected package to a fixed version
- Create a VEX statement if the vulnerability doesn't apply:
stellaops vex create --cve CVE-2024-1234 --status not_affected \ --justification vulnerable_code_not_present - Apply a temporary exception (with approval):
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:
- Ensure SBOMs are complete with package versions
- Check for unsupported package ecosystems
- Temporarily increase threshold in non-production:
settings: unknownsThreshold: 0.15
"Production deployment requires signed SBOM"
Cause: Attempting production deployment without signed SBOM.
Solutions:
- Sign SBOM during build:
stellaops sbom sign --sbom sbom.json --key-id <key> - Verify signing is configured in CI/CD pipeline
Rule Not Matching as Expected
Use simulation mode to debug:
stellaops policy simulate --policy policy.yaml --scan <scan-id> --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:
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:
# 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 <path> |
Validate policy against schema |
stellaops policy install <name> |
Install policy pack |
stellaops policy list-packs |
List available policy packs |
stellaops policy simulate --policy <path> --scan <id> |
Simulate policy evaluation |
stellaops policy push --policy <path> --to <ref> |
Push to OCI registry |
stellaops policy pull --from <ref> |
Pull from OCI registry |
stellaops policy export-bundle --policy <path> --output <file> |
Create offline bundle |
stellaops policy import-bundle --bundle <file> |
Import offline bundle |