Complete batch 012 (golden set diff) and 013 (advisory chat), fix build errors

Sprints completed:
- SPRINT_20260110_012_* (golden set diff layer - 10 sprints)
- SPRINT_20260110_013_* (advisory chat - 4 sprints)

Build fixes applied:
- Fix namespace conflicts with Microsoft.Extensions.Options.Options.Create
- Fix VexDecisionReachabilityIntegrationTests API drift (major rewrite)
- Fix VexSchemaValidationTests FluentAssertions method name
- Fix FixChainGateIntegrationTests ambiguous type references
- Fix AdvisoryAI test files required properties and namespace aliases
- Add stub types for CveMappingController (ICveSymbolMappingService)
- Fix VerdictBuilderService static context issue

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
master
2026-01-11 10:09:07 +02:00
parent a3b2f30a11
commit 7f7eb8b228
232 changed files with 58979 additions and 91 deletions

View File

@@ -0,0 +1,154 @@
-- Golden Set Storage Schema Migration
-- Version: 1.0.0
-- Date: 2026-01-10
-- Description: Initial schema for golden set definitions storage
-- Create schema
CREATE SCHEMA IF NOT EXISTS golden_sets;
-- Main golden set table
CREATE TABLE IF NOT EXISTS golden_sets.definitions (
id TEXT PRIMARY KEY,
component TEXT NOT NULL,
content_digest TEXT NOT NULL UNIQUE,
status TEXT NOT NULL DEFAULT 'draft',
definition_yaml TEXT NOT NULL,
definition_json JSONB NOT NULL,
target_count INTEGER NOT NULL,
author_id TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
reviewed_by TEXT,
reviewed_at TIMESTAMPTZ,
source_ref TEXT NOT NULL,
tags TEXT[] NOT NULL DEFAULT '{}',
schema_version TEXT NOT NULL DEFAULT '1.0.0',
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes for definitions table
CREATE INDEX IF NOT EXISTS idx_goldensets_component ON golden_sets.definitions(component);
CREATE INDEX IF NOT EXISTS idx_goldensets_status ON golden_sets.definitions(status);
CREATE INDEX IF NOT EXISTS idx_goldensets_digest ON golden_sets.definitions(content_digest);
CREATE INDEX IF NOT EXISTS idx_goldensets_tags ON golden_sets.definitions USING gin(tags);
CREATE INDEX IF NOT EXISTS idx_goldensets_created ON golden_sets.definitions(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_goldensets_component_status ON golden_sets.definitions(component, status);
-- Target extraction table (for efficient function lookup)
CREATE TABLE IF NOT EXISTS golden_sets.targets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
golden_set_id TEXT NOT NULL REFERENCES golden_sets.definitions(id) ON DELETE CASCADE,
function_name TEXT NOT NULL,
edges JSONB NOT NULL DEFAULT '[]',
sinks TEXT[] NOT NULL DEFAULT '{}',
constants TEXT[] NOT NULL DEFAULT '{}',
taint_invariant TEXT,
source_file TEXT,
source_line INTEGER
);
-- Indexes for targets table
CREATE INDEX IF NOT EXISTS idx_targets_golden_set ON golden_sets.targets(golden_set_id);
CREATE INDEX IF NOT EXISTS idx_targets_function ON golden_sets.targets(function_name);
CREATE INDEX IF NOT EXISTS idx_targets_sinks ON golden_sets.targets USING gin(sinks);
-- Audit log table
CREATE TABLE IF NOT EXISTS golden_sets.audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
golden_set_id TEXT NOT NULL REFERENCES golden_sets.definitions(id) ON DELETE CASCADE,
action TEXT NOT NULL,
actor_id TEXT NOT NULL,
old_status TEXT,
new_status TEXT,
details JSONB,
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes for audit log
CREATE INDEX IF NOT EXISTS idx_audit_golden_set ON golden_sets.audit_log(golden_set_id);
CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON golden_sets.audit_log(timestamp DESC);
CREATE INDEX IF NOT EXISTS idx_audit_actor ON golden_sets.audit_log(actor_id);
-- Sink registry reference table
CREATE TABLE IF NOT EXISTS golden_sets.sink_registry (
sink_name TEXT PRIMARY KEY,
category TEXT NOT NULL,
description TEXT,
cwe_ids TEXT[] NOT NULL DEFAULT '{}',
severity TEXT NOT NULL DEFAULT 'medium'
);
-- Seed common sinks
INSERT INTO golden_sets.sink_registry (sink_name, category, cwe_ids, severity, description) VALUES
-- Memory corruption sinks
('memcpy', 'memory', ARRAY['CWE-120', 'CWE-787'], 'high', 'Buffer copy without bounds checking'),
('strcpy', 'memory', ARRAY['CWE-120', 'CWE-787'], 'high', 'String copy without bounds checking'),
('strncpy', 'memory', ARRAY['CWE-120'], 'medium', 'String copy with size - may not null-terminate'),
('sprintf', 'memory', ARRAY['CWE-120', 'CWE-134'], 'high', 'Format string to buffer without bounds'),
('gets', 'memory', ARRAY['CWE-120'], 'critical', 'Read input without bounds - NEVER USE'),
('strcat', 'memory', ARRAY['CWE-120', 'CWE-787'], 'high', 'String concatenation without bounds'),
-- Memory management
('free', 'memory', ARRAY['CWE-415', 'CWE-416'], 'high', 'Memory deallocation - double-free/use-after-free risk'),
('realloc', 'memory', ARRAY['CWE-416'], 'medium', 'Memory reallocation - use-after-free risk'),
('malloc', 'memory', ARRAY['CWE-401'], 'low', 'Memory allocation - leak risk'),
-- OpenSSL memory
('OPENSSL_malloc', 'memory', ARRAY['CWE-401'], 'low', 'OpenSSL memory allocation'),
('OPENSSL_free', 'memory', ARRAY['CWE-415', 'CWE-416'], 'medium', 'OpenSSL memory deallocation'),
-- Command injection
('system', 'command_injection', ARRAY['CWE-78'], 'critical', 'Execute shell command'),
('exec', 'command_injection', ARRAY['CWE-78'], 'critical', 'Execute command'),
('popen', 'command_injection', ARRAY['CWE-78'], 'high', 'Open pipe to command'),
-- Code injection
('dlopen', 'code_injection', ARRAY['CWE-427'], 'high', 'Dynamic library loading'),
('LoadLibrary', 'code_injection', ARRAY['CWE-427'], 'high', 'Windows DLL loading'),
-- Path traversal
('fopen', 'path_traversal', ARRAY['CWE-22'], 'medium', 'File open'),
('open', 'path_traversal', ARRAY['CWE-22'], 'medium', 'POSIX file open'),
-- Network
('connect', 'network', ARRAY['CWE-918'], 'medium', 'Network connection'),
('send', 'network', ARRAY['CWE-319'], 'medium', 'Send data over network'),
('recv', 'network', ARRAY['CWE-319'], 'medium', 'Receive data from network'),
-- SQL injection
('sqlite3_exec', 'sql_injection', ARRAY['CWE-89'], 'high', 'SQLite execute'),
('mysql_query', 'sql_injection', ARRAY['CWE-89'], 'high', 'MySQL query'),
('PQexec', 'sql_injection', ARRAY['CWE-89'], 'high', 'PostgreSQL execute'),
-- Cryptographic
('EVP_DecryptUpdate', 'crypto', ARRAY['CWE-327'], 'medium', 'OpenSSL decrypt update'),
('EVP_EncryptUpdate', 'crypto', ARRAY['CWE-327'], 'medium', 'OpenSSL encrypt update'),
('d2i_ASN1_OCTET_STRING', 'crypto', ARRAY['CWE-295'], 'medium', 'DER to ASN1 octet string'),
('PKCS12_parse', 'crypto', ARRAY['CWE-295'], 'medium', 'Parse PKCS12 structure'),
('PKCS12_unpack_p7data', 'crypto', ARRAY['CWE-295'], 'medium', 'Unpack PKCS7 data')
ON CONFLICT (sink_name) DO UPDATE SET
category = EXCLUDED.category,
description = EXCLUDED.description,
cwe_ids = EXCLUDED.cwe_ids,
severity = EXCLUDED.severity;
-- Create function for automatic updated_at timestamp
CREATE OR REPLACE FUNCTION golden_sets.update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- Create trigger for updated_at
DROP TRIGGER IF EXISTS update_definitions_updated_at ON golden_sets.definitions;
CREATE TRIGGER update_definitions_updated_at
BEFORE UPDATE ON golden_sets.definitions
FOR EACH ROW
EXECUTE FUNCTION golden_sets.update_updated_at_column();
-- Comments
COMMENT ON TABLE golden_sets.definitions IS 'Ground-truth vulnerability code-level manifestation facts';
COMMENT ON TABLE golden_sets.targets IS 'Individual vulnerable code targets extracted from definitions';
COMMENT ON TABLE golden_sets.audit_log IS 'Audit trail for golden set changes';
COMMENT ON TABLE golden_sets.sink_registry IS 'Reference data for known vulnerability sinks';