- 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.
390 lines
10 KiB
Markdown
390 lines
10 KiB
Markdown
# 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 <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
|
|
|
|
```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 <key>
|
|
```
|
|
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 <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:
|
|
|
|
```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 <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 |
|
|
|
|
## See Also
|
|
|
|
- [Policy DSL Reference](dsl.md)
|
|
- [VEX Trust Model](vex-trust-model.md)
|
|
- [Policy Governance](governance.md)
|
|
- [Scoring Profiles](scoring-profiles.md)
|