Files
Open_Ultra_SAST/benchmarks/measurements/2026-09-19-family-detection-census.json
T

364 lines
13 KiB
JSON
Raw Normal View History

{
"schema_version": 1,
"experiment": "family-detection-census-v1",
"date": "2026-09-19",
"harness": "benchmarks/push/family_census.py",
"claim_scope": "Detection only, on two inspected teaching repositories. No comparison, no novelty, no admission, no capability qualified. These subjects developed the analyser and cannot qualify it.",
"question": "Which of the seven declared vulnerability families establish a finding on real code, and what does each silent family mean?",
"subjects": {
"nodegoat": {
"schema_version": 1,
"experiment": "family-detection-census-v1",
"subject": "nodegoat",
"root": "/cache/nodegoat/c5cb68a7084e",
"claim_scope": "Detection only. No comparison, no novelty, no admission, no capability enabled.",
"inputs": {
"files": 44,
"bytes": 95411,
"regions": 44
},
"regions_by_family": {
"access_control": 35,
"config_secrets": 44,
"injection": 44,
"output_encoding": 44,
"path": 44,
"prototype": 44,
"untrusted_destination": 44
},
"languages": {
"javascript": 44
},
"scan": {
"seconds": 137.3,
"build_seconds": 28.66,
"query_seconds": 74.48,
"hook_table_hooks": 0,
"degradations": [
"vendor_semantics_unresolved"
],
"questions_total": 299,
"questions_completed": 299
},
"families": {
"access_control": {
"regions_offering": 35,
"questions_asked": 35,
"questions_completed": 35,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "answered, nothing found"
},
"config_secrets": {
"regions_offering": 44,
"questions_asked": 44,
"questions_completed": 44,
"findings": 1,
"rungs": {
"model_entailed": 1
},
"examples": [
{
"site": "server.js:78:?",
"rung": "model_entailed",
"witness": "session({\n // genid: (req) => {\n // return genuuid() // use UUIDs for session IDs\n //},\n secret: cookieSecret,\n // Both mandatory in Express v4\n saveUninit",
"reached_from": 1
}
],
"verdict": "establishes findings"
},
"injection": {
"regions_offering": 44,
"questions_asked": 44,
"questions_completed": 44,
"findings": 3,
"rungs": {
"model_entailed": 3
},
"examples": [
{
"site": "app/routes/contributions.js:32:<lambda>2",
"rung": "model_entailed",
"witness": "req.body.preTax -> eval(req.body.preTax) in app/routes/contributions.js (line 32, 1 steps)",
"reached_from": 1
},
{
"site": "app/routes/contributions.js:33:<lambda>2",
"rung": "model_entailed",
"witness": "req.body.afterTax -> eval(req.body.afterTax) in app/routes/contributions.js (line 33, 1 steps)",
"reached_from": 1
},
{
"site": "app/routes/contributions.js:34:<lambda>2",
"rung": "model_entailed",
"witness": "req.body.roth -> eval(req.body.roth) in app/routes/contributions.js (line 34, 1 steps)",
"reached_from": 1
}
],
"verdict": "establishes findings"
},
"output_encoding": {
"regions_offering": 44,
"questions_asked": 44,
"questions_completed": 44,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "answered, nothing found"
},
"path": {
"regions_offering": 44,
"questions_asked": 44,
"questions_completed": 44,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "answered, nothing found"
},
"prototype": {
"regions_offering": 44,
"questions_asked": 44,
"questions_completed": 44,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "answered, nothing found"
},
"untrusted_destination": {
"regions_offering": 44,
"questions_asked": 44,
"questions_completed": 44,
"findings": 1,
"rungs": {
"model_entailed": 1
},
"examples": [
{
"site": "app/routes/index.js:72:<lambda>1",
"rung": "model_entailed",
"witness": "req.query.url -> res.redirect(req.query.url) in app/routes/index.js (line 72, 1 steps)",
"reached_from": 1
}
],
"verdict": "establishes findings"
}
},
"summary": {
"answered, nothing found": 4,
"establishes findings": 3
}
},
"vampi": {
"schema_version": 1,
"experiment": "family-detection-census-v1",
"subject": "vampi",
"root": "/cache/vampi/f16052dce83f",
"claim_scope": "Detection only. No comparison, no novelty, no admission, no capability enabled.",
"inputs": {
"files": 11,
"bytes": 19907,
"regions": 25
},
"regions_by_family": {
"config_secrets": 25,
"deserialization": 25,
"injection": 25,
"output_encoding": 25,
"path": 25,
"untrusted_destination": 25,
"access_control": 8
},
"languages": {
"python": 25
},
"scan": {
"seconds": 85.3,
"build_seconds": 8.82,
"query_seconds": 52.26,
"hook_table_hooks": 0,
"degradations": [],
"questions_total": 35,
"questions_completed": 35
},
"families": {
"access_control": {
"regions_offering": 8,
"questions_asked": 8,
"questions_completed": 8,
"findings": 2,
"rungs": {
"model_entailed": 2
},
"examples": [
{
"site": "api_views/books.py:51:get_by_title",
"rung": "model_entailed",
"witness": "get_by_title line 51: no discharging guard, while 1 sibling handler(s) are guarded (add_new_book)",
"reached_from": 1
},
{
"site": "api_views/users.py:187:update_password",
"rung": "model_entailed",
"witness": "update_password line 187: no discharging guard, while 3 sibling handler(s) are guarded (delete_user, me, update_email)",
"reached_from": 1
}
],
"verdict": "establishes findings"
},
"config_secrets": {
"regions_offering": 25,
"questions_asked": 25,
"questions_completed": 25,
"findings": 1,
"rungs": {
"model_entailed": 1
},
"examples": [
{
"site": "app.py:17:<module>",
"rung": "model_entailed",
"witness": "vuln_app.run(host = '0.0.0.0', port = 5000, debug = True) (line 17): permissive literal '0.0.0.0'",
"reached_from": 1
}
],
"verdict": "establishes findings"
},
"deserialization": {
"regions_offering": 25,
"questions_asked": 0,
"questions_completed": 0,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "region offered, no question asked"
},
"injection": {
"regions_offering": 25,
"questions_asked": 2,
"questions_completed": 2,
"findings": 1,
"rungs": {
"model_entailed": 1
},
"examples": [
{
"site": "models/user_model.py:73:get_user",
"rung": "model_entailed",
"witness": "username -> text(user_query) in models/user_model.py (line 73, 13 steps)",
"reached_from": 1
}
],
"verdict": "establishes findings"
},
"output_encoding": {
"regions_offering": 25,
"questions_asked": 0,
"questions_completed": 0,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "region offered, no question asked"
},
"path": {
"regions_offering": 25,
"questions_asked": 0,
"questions_completed": 0,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "region offered, no question asked"
},
"untrusted_destination": {
"regions_offering": 25,
"questions_asked": 0,
"questions_completed": 0,
"findings": 0,
"rungs": {},
"examples": [],
"verdict": "region offered, no question asked"
}
},
"summary": {
"establishes findings": 3,
"region offered, no question asked": 4
}
}
},
"verdict": {
"establish_findings": [
"injection",
"access_control",
"config_secrets",
"untrusted_destination"
],
"answered_nothing_found": {
"nodegoat": [
"access_control",
"output_encoding",
"path",
"prototype"
],
"vampi": []
},
"region_offered_no_question_asked": {
"nodegoat": [],
"vampi": [
"deserialization",
"output_encoding",
"path",
"untrusted_destination"
]
},
"never_established_anywhere": [
"output_encoding",
"path",
"prototype",
"deserialization"
]
},
"false_positive_found_and_fixed": {
"family": "prototype",
"site": "app/routes/session.js:189",
"reported_witness": "req.body -> this.handleSignup = (req, res, next) => { ...",
"measured_cause": "The matched node is <operator>.assignment whose code is the entire 1,000-character arrow function. The prototype sink 'set' matched the English word in the comment '// set these up in case we have an error case'. The handler calls no set.",
"fix": "taint.sc sinkMatches confines its text clause to the callee and excludes operator nodes",
"measured_effect_on_nodegoat_non_vendor_calls": {
"injection": {
"old": 28,
"new": 3
},
"output_encoding": {
"old": 3,
"new": 0
},
"path": {
"old": 0,
"new": 0
},
"prototype": {
"old": 13,
"new": 2
},
"untrusted_destination": {
"old": 26,
"new": 7
}
},
"true_positives_lost": 0,
"note": "Every dropped match is an operator node or an enclosing call whose body merely spells the word. req.query was an injection sink under the old rule, because 'query' is word-bounded inside it. The three eval calls and the res.redirect survive, and their witnesses now name the sink call rather than the assignment that contained it."
},
"silent_families_diagnosed": {
"untrusted_destination_on_nodegoat": "NodeGoat's documented SSRF is needle.get(req.query.url + req.query.symbol) at app/routes/research.js:16. needle.get is absent from the sink vocabulary, which holds axios/fetch/got/http.get/request. The family works; its vocabulary is thin. Recall gap.",
"output_encoding_on_nodegoat": "All six declared sinks are DOM sinks (innerHTML, document.write, dangerouslySetInnerHTML, insertAdjacentHTML, outerHTML, v-html). NodeGoat's XSS is server-side, rendered into Swig templates and written with res.write, so no question the family can ask could have found it. Structural gap: server-rendered output has no sink vocabulary in JavaScript.",
"access_control_on_nodegoat": "Measured with the real dominance query: every modelled data operation in NodeGoat lives in app/data/*-dao.js or artifacts/db-reset.js, and none in a route handler file. Operations are scoped to the region's own file, and access_control regions are the handler files, so no obligation is ever raised where the question is asked. In the DAO files every operation is equally unguarded, so the sibling-contradiction rung has nothing to contradict. The two documented defects are also outside the model's expressible claims: an IDOR that reads userId from req.params on an authenticated route (app/routes/allocations.js:17), and a commented-out isAdmin in the route table (app/routes/index.js:58). Structural gap: the model asks about one file, and this application splits route from query.",
"four_families_on_vampi": "deserialization, output_encoding, path and untrusted_destination asked nothing because VAmPI's eleven Python files contain no sink for any of them; the only match of any such token is os.path.join in config.py. Correct silence, not a gap.",
"prototype": "Never established anywhere. Its only report was the false positive above. VAmPI is Python and the family is JavaScript-only, so it has been asked on one repository."
},
"limits": [
"Two repositories, both used to develop the analyser. Nothing here qualifies a capability.",
"Findings are counted at the rung the scan reached, all model_entailed; no execution confirmation.",
"A family silent on two repositories is untested, not absent."
]
}