Skip to content

TGPSKI/security-context-spec

Security Context Spec

Structured, portable, machine-readable security context for code repositories.

SARIF (2020, OASIS) standardized scanner output. This spec standardizes scanner input — the security-relevant context that every scanner rediscovers on every run.

Why

Every security scanner asks the same questions about your code: Is this deployed? Where? Is it public-facing? Who owns it? Is this CVE actually reachable? None of them remember the answers.

The result is a staggering amount of repeated work — by humans and by AI agents:

  • Triaging the same false positives across Snyk, Trivy, Semgrep, and CodeQL because each has its own ignore file format
  • Re-explaining deployment context to every new tool, every scan, every quarter
  • Burning tokens and compute as AI agents re-discover "this runs on Kubernetes behind a WAF" from scratch on every invocation
  • Duplicating severity adjustments — manually downgrading the same CVE in four dashboards because no scanner knows it's behind a VPN
  • Wasting engineering hours answering "is this actually exploitable?" when the context to answer that question already exists — just not in a format any scanner can read

A single .security-context.yaml eliminates this entire class of repetitive work. Write it once. Every scanner, every AI agent, every triage workflow reads it. Context stops being a discovery problem and becomes a lookup.

Design Principle

Every field must either change a security finding or eliminate a security-relevant discovery step.

A field that doesn't adjust a severity, waive a finding, or eliminate a step a scanner needs to assess a vulnerability doesn't belong in v1.0.

What It Does

Drop a .security-context.yaml in your repo root. Scanners consume it to:

  • Adjust severity — a vulnerability behind a VPC and WAF is less severe than one on the public internet
  • Suppress false positives — CWE-level suppression with rationale, portable across any scanner
  • Route ownership — findings in vendored paths go to the right team
  • Assess blast radius — cross-repo trust relationships reveal what compromising repo A grants over system B
  • Skip discovery — no more re-discovering "is this deployed?", "is this ephemeral?", "who owns this?" on every scan

Quick Start

# .security-context.yaml
metadata:
  schema_version: "1.0"
  repo: org/my-service
  status: production
  service_tier: standard
  owner:
    team: platform-team

security_properties:
  exposure: internal
  platform: kubernetes
  ephemeral: false
  network_isolated: true

Sections (v1.0)

Section Purpose
metadata Identity, lifecycle, classification, ownership scope
security_properties Flat security-relevant deployment facts
prerequisites What an attacker must already have
relationships Cross-repo blast radius and trust boundaries
dependencies Unreachable CVEs and base image context
accepted_risks Intentional design tradeoffs with expiry and audit trail
scanning_directives Finding modifiers — suppress, prioritize, false positive patterns

Prior Art

This spec complements existing standards — it does not replace them:

Standard Overlap Relationship
SARIF (OASIS) None — different direction SARIF = output, this = input
VEX (OASIS) dependencies.known_unreachable, accepted_risks Entries MAY reference VEX document IDs
OSCAL SSP (NIST) Conceptual (system security context) OSCAL is compliance-oriented; this is developer-maintained
CycloneDX (v1.5+) Build environment metadata Complementary; some overlap
OpenSSF Security Insights metadata.status, metadata.owner Complementary repo-level metadata
Scanner ignore files .trivyignore, .snyk, .semgrepignore Per-scanner, not portable. scanning_directives is portable.

Repository Layout

├── spec/
│   ├── security-context-latest.md      # Symlink → current version
│   └── versions/
│       └── security-context-v1.0.md    # Normative specification (v1.0)
├── decisions/
│   ├── TEMPLATE.md                     # Proposal template
│   ├── proposals/                      # Active proposals
│   ├── accepted/                       # Accepted decisions
│   └── rejected/                       # Rejected with rationale
├── schema/
│   └── security-context-v1.schema.json # JSON Schema for IDE/tooling
├── tools/
│   └── validate/                       # Go reference validator (single binary)
├── skills/
│   └── generate-security-context/      # Agent skill (agentskills.io)
│       ├── SKILL.md                    # Multi-phase directed workflow
│       ├── scripts/scan.go             # Deterministic repo scanner
│       └── references/                 # Phase instructions
├── examples/                           # 8 example files (minimal → data-pipeline)
├── .github/
│   ├── rulesets/                        # Branch and tag protection rules
│   ├── workflows/ci.yml                # CI: two-tier (fast gate + cross-platform)
│   ├── ISSUE_TEMPLATE/                 # Bug, feature, proposal templates
│   └── CODEOWNERS
├── Makefile
├── AGENTS.md
├── CONTRIBUTING.md
├── SECURITY.md
├── CODE_OF_CONDUCT.md
├── CHANGELOG.md
└── LICENSE                             # Apache-2.0

Usage

make help              # Show all targets
make check             # Full CI: lint + fmt-check + test + validate
make validate          # Validate all examples
make validate-file FILE=.security-context.yaml
make scan REPO=/path/to/repo  # Scan a repo for detectable security properties
make current           # Show current spec version
make versions          # List all spec versions
make release VERSION=1.1  # Snapshot current spec as a new version
make proposal NAME=add-runtime-details  # Create a new proposal
make proposals         # List proposals by status
make accept PROPOSAL=add-runtime-details
make reject PROPOSAL=add-runtime-details

Validation

The reference validator is a single Go binary with one dependency (gopkg.in/yaml.v3). Validation logic is Go structs — no JSON Schema library at runtime.

make build
./tools/validate/security-context-validate .security-context.yaml
# OK: .security-context.yaml is valid

The JSON Schema (schema/security-context-v1.schema.json) ships alongside for IDE autocompletion and CI tooling that already consumes JSON Schema.

For Scanner Authors

To consume .security-context.yaml:

  1. Look for .security-context.yaml in the repository root
  2. Parse YAML; validate metadata.schema_version is "1.0"
  3. Use security_properties to adjust finding severity
  4. Use prerequisites to assess attacker cost
  5. Use scanning_directives.suppress to filter findings — but report what was suppressed
  6. Use accepted_risks to annotate findings with existing risk acceptances — flag expired ones
  7. Use relationships for cross-repo blast radius analysis

Trust model: The file is maintained by the team whose code is being scanned. Treat it as a declaration of context, not a grant of authority. Your scanner decides how much weight to give each field.

License

Apache-2.0

About

Structured, portable, machine-readable security context for code repositories. SARIF standardized scanner output; this spec standardizes scanner input.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors