feat(pre-push-safety-net): preserve uncertainty in benchmark scoring

This commit is contained in:
Marius Ciepluch
2026-09-12 19:04:20 +02:00
parent 8acada0d98
commit 051f3b0058
13 changed files with 1197 additions and 32 deletions
+45
View File
@@ -44,3 +44,48 @@ Python populations are explicitly missing in `capability_prerequisites`. VAmPI r
known targets (including SQLI), with `vulnerable=1`; these snapshot regressions are not paired pushes.
Libpng is an envelope/unsupported-arithmetic control, not a detection success or a supported miss.
The validator makes no finding, precision, recall, silence, latency or admission claim.
## Frozen diagnostic scoring (task 1.3)
`push_scoring` consumes recorded execution evidence; it does not run the scanner or
implement push delta/admission policy. Freeze the workload and expected configuration
**before** executing it:
```sh
.venv/bin/python -m openultrasast.push_scoring freeze benchmarks/push/inputs.json benchmarks/push/diagnostic-config-v1.json > /tmp/profile.json
.venv/bin/python -m openultrasast.push_scoring score /tmp/profile.json benchmarks/push/input-validation.json benchmarks/push/unmeasured-run-v1.json
```
The committed v1 profile reserves the 11 declared cases and exact tip target locations.
It is a proposed 30-second evidence-mode experiment, not measured performance. The
`unmeasured-run-v1.json` deliberately contains no executions: scoring it exits **1**,
retains all 11 unresolved cases, and earns no recall, coverage or admission. An invalid
profile/runtime identity exits **2**. A fully resolved diagnostic score exits **0**;
that exit status is not capability admission. Freeze a new version when configuration,
source manifest, core, facts, query semantics or scope changes; do not edit a measured
profile to match later execution. Runtime `context` must record the actual values,
not merely copy an expected profile hash. Profiles are content identities, not signatures.
Each `records` entry supplies `case_id`, actual `ranking_mode`, `rank` (or null), exact
`selected`/`deferred` question IDs, `queries`, `alerts`, `delta`, `coverage`, `cache_state`
and nonnegative elapsed `timings` including `total`. Cache states distinguish `cold`,
`warm_changed` and `identical_tip`; stage costs remain beside each outcome. Queries
supply `id`, `status` and `outcome`. A positive needs a finding with the exact frozen
`site` and `family`, a supported `rung`, and a nonempty actual `witness`. A transitive
claim additionally needs a recorded `origin` and ordered `flow` from that region to
the frozen target's path/function. Missing rank never proves transitivity. Negative
answers require the exact `target` and a witnessed discharge; empty/failed queries
cannot earn fixed-side silence. These checks establish evidence association, not the
truth of an arbitrary supplied witness: use engine output and review the attribution.
Alerts are separate from raw findings. Only reviewed `actionable_true` alerts with
`review_evidence`, `question_id` and exact `site` association can contribute precision;
unreviewed/wrong-target alerts remain in its denominator. Benign comment changes retain
vulnerable backlog, so a raw positive is not automatically a new alert. The scorer
consumes a recorded delta; task 5.1 supplies replay, and the policy tasks establish it.
Reports retain unresolved cases, sample counts, Wilson intervals, separate regression
results, per-capability metrics, coverage and cold/warm latency. Missing benign runs
have unknown interruption rate. VAmPI's readable regression may be measured while
independent admission prerequisites remain missing. Unsupported/unreviewed populations
stay visible. All results remain experimental pending the later joint admission gate.
+92
View File
@@ -0,0 +1,92 @@
{
"version": "pre-push-diagnostic-v1-2026-09-12",
"ranking_mode": "evidence",
"engine": "joern-4.0.625",
"facts": "642d643d5b40a20fe482ace566cc77d132870930ecd2f2e881dcecd7dc9a0641",
"queries": "64c1534edb07e770ab8631b48bc156ef54b71ddb8d8ee4357fd5022eb11f0229",
"policy": "diagnostic-only-no-admission-v1",
"scope": "first-party-only; declared vendor exclusion in graph and targets; exact selected/deferred question IDs required per record",
"hardware": "Linux-6.8.0-138-generic-x86_64-with-glibc2.39",
"budget_seconds": 30,
"core": "7ac2bc93b35ce9d0cdcfc543266025519999ff45339657d4a5d283c67957d682",
"targets": {
"pmpro-introduce": {
"path": "classes/class.memberorder.php",
"function": "getMemberOrderByCode",
"family": "injection",
"lines": [
936
]
},
"pmpro-repair": {
"path": "classes/class.memberorder.php",
"function": "getMemberOrderByCode",
"family": "injection",
"lines": [
937
]
},
"pmpro-benign": {
"path": "classes/class.memberorder.php",
"function": "getMemberOrderByCode",
"family": "injection",
"lines": [
937
]
},
"nodegoat-introduce": {
"path": "app/routes/contributions.js",
"function": "handleContributionsUpdate",
"family": "injection",
"lines": [
32,
33,
34
]
},
"nodegoat-repair": {
"path": "app/routes/contributions.js",
"function": "handleContributionsUpdate",
"family": "injection",
"lines": [
32,
33,
34
]
},
"nodegoat-benign": {
"path": "app/routes/contributions.js",
"function": "handleContributionsUpdate",
"family": "injection",
"lines": [
32,
33,
34
]
},
"VAmPI-SQLI": {
"path": "models/user_model.py",
"function": "get_user",
"family": "injection",
"lines": [
73
]
},
"VAmPI-BOLA": {
"path": "api_views/users.py",
"function": "update_password",
"family": "access_control",
"lines": [
187
]
},
"VAmPI-BOLA-BOOKS": {
"path": "api_views/books.py",
"function": "get_by_title",
"family": "access_control",
"lines": [
51
]
}
}
}
+226
View File
@@ -0,0 +1,226 @@
{
"schema_version": 1,
"manifest_sha256": "eec13cb19fe5e2c2402e61ebf4fd17fa809482f321e7a8e615215a12e1bcf845",
"cases": [
{
"id": "pmpro-introduce",
"base": "pmpro-fixed",
"tip": "pmpro-vulnerable",
"label": "vulnerable",
"role": "development",
"capability": "php/wordpress/injection",
"provenance": "Authored replay direction reintroducing the reviewed operation; not a claim about the historical introducing commit.",
"prerequisites": []
},
{
"id": "pmpro-repair",
"base": "pmpro-vulnerable",
"tip": "pmpro-fixed",
"label": "fixed",
"role": "development",
"capability": "php/wordpress/injection",
"provenance": "PMPro upstream2.9.7 to2.9.8 parameter binding fix for CVE-2023-23488.",
"prerequisites": []
},
{
"id": "pmpro-benign",
"base": "pmpro-vulnerable",
"tip": "pmpro-benign",
"label": "benign",
"role": "development",
"capability": "php/wordpress/injection",
"provenance": "Authored comment-only change: no new defect; vulnerable backlog remains. This label does not mean repository-clean.",
"prerequisites": []
},
{
"id": "nodegoat-introduce",
"base": "nodegoat-fixed",
"tip": "nodegoat-vulnerable",
"label": "vulnerable",
"role": "transfer",
"capability": "javascript/express/injection",
"provenance": "Authored replay direction reintroducing the reviewed operation; not a claim about the historical introducing commit.",
"prerequisites": []
},
{
"id": "nodegoat-repair",
"base": "nodegoat-vulnerable",
"tip": "nodegoat-fixed",
"label": "fixed",
"role": "transfer",
"capability": "javascript/express/injection",
"provenance": "Authored replacement of three eval calls with Number conversion; source tutorial also documents alternate numeric parsing.",
"prerequisites": []
},
{
"id": "nodegoat-benign",
"base": "nodegoat-vulnerable",
"tip": "nodegoat-benign",
"label": "benign",
"role": "transfer",
"capability": "javascript/express/injection",
"provenance": "Authored comment-only change: no new defect; vulnerable backlog remains. This label does not mean repository-clean.",
"prerequisites": []
},
{
"id": "VAmPI-SQLI",
"base": "vampi-regression",
"tip": "vampi-regression",
"label": "regression",
"role": "regression",
"capability": "python/flask/injection",
"provenance": "Existing recipe known target, full target population retained; environment vulnerable=1. Snapshot regression, not an introducing push.",
"prerequisites": [
"Reviewed independent vulnerable/fixed/benign push pair required before hook admission."
]
},
{
"id": "VAmPI-BOLA",
"base": "vampi-regression",
"tip": "vampi-regression",
"label": "regression",
"role": "regression",
"capability": "python/flask/access_control",
"provenance": "Existing recipe known target, full target population retained; environment vulnerable=1. Snapshot regression, not an introducing push.",
"prerequisites": [
"Reviewed independent vulnerable/fixed/benign push pair required before hook admission."
]
},
{
"id": "VAmPI-BOLA-BOOKS",
"base": "vampi-regression",
"tip": "vampi-regression",
"label": "regression",
"role": "regression",
"capability": "python/flask/access_control",
"provenance": "Existing recipe known target, full target population retained; environment vulnerable=1. Snapshot regression, not an introducing push.",
"prerequisites": [
"Reviewed independent vulnerable/fixed/benign push pair required before hook admission."
]
},
{
"id": "libpng-CVE-2025-66293",
"base": "libpng-envelope",
"tip": "libpng-envelope",
"label": "unsupported",
"role": "envelope",
"capability": "c/libpng/memory_safety",
"provenance": "Arithmetic/bounds is outside the current abstract domain; measures graph/cost envelope only.",
"prerequisites": []
},
{
"id": "ghost-reserved-population",
"base": "ghost-reserved",
"tip": "ghost-reserved",
"label": "unreviewed",
"role": "reserved_holdout",
"capability": "javascript/express/unreviewed",
"provenance": "Reserved from production API/module/async shape and public security-fix history before scanner results. Manifest6.64.0-rc.0, Express4.22.2. Not an ESM or Express5 coverage claim.",
"prerequisites": [
"Review and freeze supported positive/fixed/benign changes from independent history; select family before scanning.",
"Freeze core and existing facts after development; preserve reservation and record any contamination."
]
}
],
"config": {
"version": "pre-push-diagnostic-v1-2026-09-12",
"ranking_mode": "evidence",
"engine": "joern-4.0.625",
"facts": "642d643d5b40a20fe482ace566cc77d132870930ecd2f2e881dcecd7dc9a0641",
"queries": "64c1534edb07e770ab8631b48bc156ef54b71ddb8d8ee4357fd5022eb11f0229",
"policy": "diagnostic-only-no-admission-v1",
"scope": "first-party-only; declared vendor exclusion in graph and targets; exact selected/deferred question IDs required per record",
"hardware": "Linux-6.8.0-138-generic-x86_64-with-glibc2.39",
"budget_seconds": 30,
"core": "7ac2bc93b35ce9d0cdcfc543266025519999ff45339657d4a5d283c67957d682",
"targets": {
"pmpro-introduce": {
"path": "classes/class.memberorder.php",
"function": "getMemberOrderByCode",
"family": "injection",
"lines": [
936
]
},
"pmpro-repair": {
"path": "classes/class.memberorder.php",
"function": "getMemberOrderByCode",
"family": "injection",
"lines": [
937
]
},
"pmpro-benign": {
"path": "classes/class.memberorder.php",
"function": "getMemberOrderByCode",
"family": "injection",
"lines": [
937
]
},
"nodegoat-introduce": {
"path": "app/routes/contributions.js",
"function": "handleContributionsUpdate",
"family": "injection",
"lines": [
32,
33,
34
]
},
"nodegoat-repair": {
"path": "app/routes/contributions.js",
"function": "handleContributionsUpdate",
"family": "injection",
"lines": [
32,
33,
34
]
},
"nodegoat-benign": {
"path": "app/routes/contributions.js",
"function": "handleContributionsUpdate",
"family": "injection",
"lines": [
32,
33,
34
]
},
"VAmPI-SQLI": {
"path": "models/user_model.py",
"function": "get_user",
"family": "injection",
"lines": [
73
]
},
"VAmPI-BOLA": {
"path": "api_views/users.py",
"function": "update_password",
"family": "access_control",
"lines": [
187
]
},
"VAmPI-BOLA-BOOKS": {
"path": "api_views/books.py",
"function": "get_by_title",
"family": "access_control",
"lines": [
51
]
}
}
},
"gates": {
"precision": 0.95,
"recall": 0.9,
"completion": 0.95,
"warm_p95_seconds": 30.0,
"fixed_false_alerts": 0,
"benign_false_alerts": 0
},
"profile_sha256": "95c26cf474573766fa24c44f4375cfcb506b196412cd421deadff35b4eb9ef3f"
}
+15
View File
@@ -0,0 +1,15 @@
{
"profile_sha256": "95c26cf474573766fa24c44f4375cfcb506b196412cd421deadff35b4eb9ef3f",
"context": {
"ranking_mode": "evidence",
"engine": "joern-4.0.625",
"facts": "642d643d5b40a20fe482ace566cc77d132870930ecd2f2e881dcecd7dc9a0641",
"queries": "64c1534edb07e770ab8631b48bc156ef54b71ddb8d8ee4357fd5022eb11f0229",
"policy": "diagnostic-only-no-admission-v1",
"scope": "first-party-only; declared vendor exclusion in graph and targets; exact selected/deferred question IDs required per record",
"hardware": "Linux-6.8.0-138-generic-x86_64-with-glibc2.39",
"budget_seconds": 30,
"core": "7ac2bc93b35ce9d0cdcfc543266025519999ff45339657d4a5d283c67957d682"
},
"records": []
}