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.
This commit is contained in:
master
2025-12-18 18:35:30 +02:00
parent 811f35cba7
commit 0dc71e760a
70 changed files with 8904 additions and 163 deletions

View File

@@ -0,0 +1,256 @@
# 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:
```javascript
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:
```python
def vulnerable(user_input):
exec(user_input) # dangerous!
```
Normalized to remove:
- Docstrings
- Comments
- Variable names
## Database Schema
```sql
-- 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:**
```json
{
"cveId": "CVE-2024-12345",
"ecosystem": "nuget",
"packageName": "Newtonsoft.Json",
"vulnVersion": "13.0.1",
"fixedVersion": "13.0.2"
}
```
**Response:**
```json
{
"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
- [Vuln Surfaces Sprint](../implplan/SPRINT_3700_0002_0001_vuln_surfaces_core.md)
- [Reachability Architecture](../reachability/README.md)
- [RichGraph Contract](./richgraph-v1.md)