Files
git.stella-ops.org/docs/policy/starter-guide.md
StellaOps Bot 56e2dc01ee 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.
2025-12-23 09:23:42 +02:00

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 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

- 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:

  1. Update the affected package to a fixed version
  2. 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
    
  3. 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:

  1. Ensure SBOMs are complete with package versions
  2. Check for unsupported package ecosystems
  3. Temporarily increase threshold in non-production:
    settings:
      unknownsThreshold: 0.15
    

"Production deployment requires signed SBOM"

Cause: Attempting production deployment without signed SBOM.

Solutions:

  1. Sign SBOM during build:
    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:

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

See Also