Files
git.stella-ops.org/docs/contracts/vuln-surface-v1.md
master 0dc71e760a feat: Add PathViewer and RiskDriftCard components with templates and styles
- Implemented PathViewerComponent for visualizing reachability call paths.
- Added RiskDriftCardComponent to display reachability drift results.
- Created corresponding HTML templates and SCSS styles for both components.
- Introduced test fixtures for reachability analysis in JSON format.
- Enhanced user interaction with collapsible and expandable features in PathViewer.
- Included risk trend visualization and summary metrics in RiskDriftCard.
2025-12-18 18:35:30 +02:00

7.6 KiB

Vuln Surface Contract v1

Sprint: SPRINT_3700_0002_0001
Task: SURF-024
Schema: stella.ops/vulnSurface@v1

Overview

A Vulnerability Surface represents the specific methods that changed between a vulnerable and fixed version of a package. This enables precise reachability analysis by identifying the exact "trigger" methods that are dangerous rather than treating the entire package as vulnerable.

Use Cases

  1. Noise Reduction - Only flag findings where code actually calls vulnerable methods
  2. Confidence Tiers - "Confirmed reachable" (calls trigger) vs "Potentially reachable" (uses package)
  3. Remediation Guidance - Show developers exactly which API calls to avoid
  4. VEX Precision - Automatically generate VEX "not_affected" for unreachable triggers

Data Model

VulnSurface

Root object representing a computed vulnerability surface.

Field Type Required Description
surface_id integer Yes Database ID
cve_id string Yes CVE identifier (e.g., "CVE-2024-12345")
package_id string Yes Package identifier in PURL format
ecosystem string Yes Package ecosystem: nuget, npm, maven, pypi
vuln_version string Yes Vulnerable version analyzed
fixed_version string Yes First fixed version used for diff
sinks VulnSurfaceSink[] Yes Changed methods (vulnerability triggers)
trigger_count integer Yes Number of callers to sink methods
status VulnSurfaceStatus Yes Computation status
confidence number Yes Confidence score (0.0-1.0)
computed_at string Yes ISO 8601 timestamp

VulnSurfaceSink

A method that changed between vulnerable and fixed versions.

Field Type Required Description
sink_id integer Yes Database ID
method_key string Yes Fully qualified method signature
method_name string Yes Simple method name
declaring_type string Yes Containing class/module
namespace string No Namespace/package
change_type MethodChangeType Yes How the method changed
is_public boolean Yes Whether method is publicly accessible
parameter_count integer No Number of parameters
return_type string No Return type
source_file string No Source file (from debug symbols)
start_line integer No Starting line number
end_line integer No Ending line number

VulnSurfaceTrigger

A call site that invokes a vulnerable sink method.

Field Type Required Description
trigger_id integer Yes Database ID
sink_id integer Yes Reference to sink
scan_id UUID Yes Scan where trigger was found
caller_node_id string Yes Call graph node ID
caller_method_key string Yes FQN of calling method
caller_file string No Source file of caller
caller_line integer No Line number of call
reachability_bucket string Yes Reachability classification
path_length integer No Shortest path from entrypoint
confidence number Yes Confidence score (0.0-1.0)
call_type string Yes Call type: direct, virtual, interface, reflection
is_conditional boolean Yes Whether call is behind a condition

Enums

VulnSurfaceStatus

Value Description
pending Surface computation queued
computing Currently being computed
computed Successfully computed
failed Computation failed
stale Needs recomputation (new version available)

MethodChangeType

Value Description
added Method added in fix (not in vulnerable version)
removed Method removed in fix (was in vulnerable version)
modified Method body changed between versions
unknown Change type could not be determined

Reachability Buckets

Bucket Description Risk Level
entrypoint Sink is directly exposed as entrypoint Critical
direct Reachable from entrypoint with no authentication gates High
runtime Reachable but behind runtime conditions/auth Medium
unknown Reachability could not be determined Medium
unreachable No path from any entrypoint Low

Fingerprinting Methods

cecil-il (NuGet/.NET)

Uses Mono.Cecil to compute SHA-256 hash of IL instruction sequence:

IL_0000: ldarg.0
IL_0001: call System.Object::.ctor()
IL_0006: ret

Normalized to remove:

  • NOP instructions
  • Debug sequence points
  • Local variable indices (replaced with placeholders)

babel-ast (npm/Node.js)

Uses Babel to parse JavaScript/TypeScript and compute hash of normalized AST:

function vulnerable(input) {
  eval(input); // dangerous!
}

Normalized to remove:

  • Comments
  • Whitespace
  • Variable names (renamed to positional)

asm-bytecode (Maven/Java)

Uses ASM to compute hash of Java bytecode:

ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V
RETURN

Normalized to remove:

  • Line number tables
  • Local variable tables
  • Stack map frames

python-ast (PyPI)

Uses Python's ast module to compute hash of normalized AST:

def vulnerable(user_input):
    exec(user_input)  # dangerous!

Normalized to remove:

  • Docstrings
  • Comments
  • Variable names

Database Schema

-- Surfaces table
CREATE TABLE scanner.vuln_surfaces (
    id UUID PRIMARY KEY,
    tenant_id UUID NOT NULL,
    cve_id TEXT NOT NULL,
    package_ecosystem TEXT NOT NULL,
    package_name TEXT NOT NULL,
    vuln_version TEXT NOT NULL,
    fixed_version TEXT,
    fingerprint_method TEXT NOT NULL,
    total_methods_vuln INTEGER,
    total_methods_fixed INTEGER,
    changed_method_count INTEGER,
    computed_at TIMESTAMPTZ DEFAULT now(),
    UNIQUE (tenant_id, cve_id, package_ecosystem, package_name, vuln_version)
);

-- Sinks table
CREATE TABLE scanner.vuln_surface_sinks (
    id UUID PRIMARY KEY,
    surface_id UUID REFERENCES scanner.vuln_surfaces(id) ON DELETE CASCADE,
    method_key TEXT NOT NULL,
    method_name TEXT NOT NULL,
    declaring_type TEXT NOT NULL,
    change_type TEXT NOT NULL,
    UNIQUE (surface_id, method_key)
);

-- Triggers table
CREATE TABLE scanner.vuln_surface_triggers (
    id UUID PRIMARY KEY,
    sink_id UUID REFERENCES scanner.vuln_surface_sinks(id) ON DELETE CASCADE,
    scan_id UUID NOT NULL,
    caller_node_id TEXT NOT NULL,
    reachability_bucket TEXT NOT NULL,
    confidence REAL NOT NULL,
    UNIQUE (sink_id, scan_id, caller_node_id)
);

API Endpoints

POST /api/v1/surfaces/compute

Request surface computation for a CVE + package.

Request:

{
  "cveId": "CVE-2024-12345",
  "ecosystem": "nuget",
  "packageName": "Newtonsoft.Json",
  "vulnVersion": "13.0.1",
  "fixedVersion": "13.0.2"
}

Response:

{
  "surfaceId": "uuid",
  "status": "pending"
}

GET /api/v1/surfaces/{surfaceId}

Get computed surface with sinks.

GET /api/v1/surfaces/{surfaceId}/triggers?scanId={scanId}

Get triggers for a surface in a specific scan.

Integration Points

  1. Concelier - Feeds CVE + affected version ranges
  2. Scanner - Computes surfaces during SBOM analysis
  3. Call Graph - Provides reachability analysis
  4. VEX Lens - Uses surfaces for automated VEX decisions
  5. UI - Displays surface details and trigger paths

References