Add unit tests for AST parsing and security sink detection
- 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.
This commit is contained in:
389
docs/policy/starter-guide.md
Normal file
389
docs/policy/starter-guide.md
Normal file
@@ -0,0 +1,389 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user