What is Policy as Code?

Policy as Code treats security policies as configuration files that can be evaluated by tools to make runtime decisions. This approach reduces the cost of compliance by automating the grunt work required to audit for policy violations.

Why Use Policy as Code?

Manual verification and approval of new software components is tedious, error-prone, and incomplete. It’s impossible to manually analyze a 3rd party dependency and all its transitive dependencies. Organizational software supply chain policies should be codified so tools can automatically evaluate every artifact for compliance.

Common Policy Examples

Vulnerability Policies

Dependencies must not have known critical vulnerabilities

Maintenance Policies

Dependencies must be actively maintained

Popularity Policies

Dependencies must have an extensive user base

Security Standards

Publishers must follow security standards like SLSA

How Filter Suites Work

A Filter Suite allows you to combine multiple security policies into a single, comprehensive ruleset. Instead of writing individual filters, you can express complex organizational policies in a structured format.

Example Filter Suite

Here’s a comprehensive filter suite that implements common security policies:

name: Enterprise Security Policy
description: Comprehensive security policy for open source components
filters:
  - name: critical-vulnerabilities
    value: |
      vulns.critical.size() > 0
    
  - name: high-vulnerabilities
    value: |
      vulns.high.size() > 5
    
  - name: approved-licenses
    value: |
      !licenses.exists(p, p in ["MIT", "Apache-2.0", "BSD-3-Clause", "ISC"])
    
  - name: minimum-maintenance
    value: |
      scorecard.scores.Maintained < 5
    
  - name: security-score
    value: |
      scorecard.Score < 3
  

Using Filter Suites

Basic Usage

Apply a filter suite to scan a project:

vet scan -D /path/to/project \
  --filter-suite /path/to/policy.yml \
  --filter-fail

Directory Scanning

Scan multiple manifest files:

vet scan -D /path/to/monorepo \
  --filter-suite .vet/security-policy.yml \
  --filter-fail

CI/CD Integration

Use filter suites in your CI pipeline:

# GitHub Actions
- name: Security Policy Check
  uses: safedep/vet-action@v1
  with:
    policy: '.github/vet-policy.yml'
    fail-on-violation: true

Advanced Policy Examples

License Compliance Policy

name: License Compliance
description: Ensure only approved licenses are used
filters:
  - name: copyleft-licenses
    value: |
      licenses.exists(p, p in ["GPL-2.0", "GPL-3.0", "AGPL-3.0"])
    
  - name: unknown-licenses
    value: |
      licenses.size() == 0 || licenses.exists(p, p == "UNKNOWN")

Supply Chain Security Policy

name: Supply Chain Security
description: Advanced supply chain security checks
filters:
  - name: unsigned-packages
    value: |
      !package.signed
    
  - name: suspicious-maintainers
    value: |
      package.maintainers.size() == 1 && 
      package.published_at > timestamp("2023-01-01T00:00:00Z")
    
  - name: typosquatting-risk
    value: |
      package.name.size() < 3 || 
      package.name.contains("_") && package.downloads < 1000

Development vs Production Policies

name: Development Policy
description: Relaxed policy for development environments
filters:
  - name: critical-vulns-only
    value: |
      vulns.critical.size() > 0
  
  - name: major-license-violations
    value: |
      licenses.exists(p, p in ["GPL-3.0", "AGPL-3.0"])

Filter Suite Evaluation

Filter suites are evaluated as:

  1. Ordered list of filters as defined in the suite file
  2. Stop on first match for each package
  3. Return violation if any filter matches

Order your filters from most specific to most general for optimal performance.

Best Practices

CEL Language Reference

The Common Expression Language (CEL) provides the foundation for writing policies. Key concepts:

Available Data Fields

  • vulns.critical, vulns.high, vulns.medium, vulns.low - Vulnerability arrays
  • licenses - Array of license identifiers
  • scorecard.scores.* - OpenSSF Scorecard metrics
  • package.* - Package metadata (name, version, published_at, etc.)

Common Operations

  • size() - Get array length
  • exists(item, condition) - Check if condition exists for any item
  • in - Check membership in array
  • contains() - String contains check