From fcb12e116a936094f50cf7a03839b3b3ca0c8dad Mon Sep 17 00:00:00 2001 From: Marius Ciepluch <11855163+norandom@users.noreply.github.com> Date: Tue, 8 Sep 2026 17:16:00 +0200 Subject: [PATCH] feat(model-grounded-detection): Java web sinks, and the post-closure-fix ceiling Java shipped with injection, deserialization and crypto sinks only, so the path and output_encoding families had nothing routing to them by CWE and any Java pair in either was unreadable -- the gap hutool-cve-2018-17297 reported as "no path spec for java". Adds the JDK filesystem entry points, the servlet response writers, the outbound/redirect APIs, and the ESAPI / canonical-path sanitizers the OWASP suite itself uses. Documented APIs, provenance per entry. Post-closure-fix ceiling: 41.3% entailed (38/92) and 26.1% distinguished, up from 39.1% / 23.9%. path went 0/8 to 1/8 with its first distinguished pair; injection 29->31 entailed and 18->19 distinguished. Two points -- real, and the mechanism is understood, but the remaining gaps are data rather than machinery. Carrying a correction: the measurement harness routed config_secrets through TAINT rather than the constant-abstraction arm, so its 0/10 in this artifact measures the wrong arbiter and did so in both full runs. The harness is fixed; that family's real number is the earlier targeted re-measure, and this artifact's config row should not be read. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG --- ...26-09-08-model-entailment-ceiling-cpg.json | 550 ++++++++---------- src/openultrasast/ruleset/semantic/java.toml | 36 ++ 2 files changed, 277 insertions(+), 309 deletions(-) diff --git a/benchmarks/measurements/2026-09-08-model-entailment-ceiling-cpg.json b/benchmarks/measurements/2026-09-08-model-entailment-ceiling-cpg.json index 0265c67..12944f4 100644 --- a/benchmarks/measurements/2026-09-08-model-entailment-ceiling-cpg.json +++ b/benchmarks/measurements/2026-09-08-model-entailment-ceiling-cpg.json @@ -5,62 +5,16 @@ "source": "2026-09-08-model-entailment-ceiling.json" }, "generated": "2026-09-08", - "java_gap": "hutool-cve-2018-17297 has no path spec at all: task 4.2 authored path sinks for python and javascript only.", - "miss_cause_note": "Classified statically from the excerpt text. `source_unmodelled` names a recognisable untrusted-input idiom the fact tables do not carry -- req.url (raw Node HTTP, what a static file server reads) and request.POST/GET (Django) are the two that recur. These are one-line data additions, not architecture.", - "miss_causes": { - "no_recognisable_source_in_excerpt": { - "examples": [ - "damn-vulnerable-graphql-application-views-resolve-pastes (injection)", - "djangoat-analytics-hits-by-ip (injection)", - "dsvpwa-handlers-do-bdr (injection)", - "dvpwa-student-create (injection)" - ], - "pairs": 13 - }, - "sink_absent_from_excerpt_or_unmodelled": { - "examples": [ - "sven-cwe-089-query-concat (injection)", - "hutool-cve-2018-17297 (path)", - "openssl-cve-2022-1292 (injection)", - "damn-vulnerable-graphql-application-views-mutate (injection)" - ], - "pairs": 23 - }, - "source_unmodelled": { - "examples": [ - "djangoat-views-reset-password (deserialization, request.POST)", - "dsvpwa-attacks-run (injection, handler.params)", - "angular-http-server-1-0-0 (path, req.url)" - ], - "pairs": 3 - } - }, "overall": { - "any_verdict_rate": 0.4565, + "any_verdict_rate": 0.4783, "corroborated": 6, - "distinguished": 22, - "distinguished_rate": 0.2391, - "entailed": 36, - "entailed_rate": 0.3913, - "none": 50, + "distinguished": 24, + "distinguished_rate": 0.2609, + "entailed": 38, + "entailed_rate": 0.413, + "none": 48, "pairs": 92 }, - "path_family_probe": { - "actual_cause": "The sink is lexically inside an anonymous callback, so its enclosing method is the closure rather than the labeled function, and the verdict's `sinkMethod == function` filter drops it. On angular-http-server the sink `fs.readFileSync(possibleFilename)` sits in the callback passed to fs.stat, and Joern names its method `0`; verdict(function='requestListener') returns None while verdict(function='') returns model_entailed. JavaScript is callback-heavy, so the labeled function and the method containing the sink routinely differ.", - "correct_fix": [ - "scope a sink to any method lexically nested within the labeled function, not only the labeled function itself", - "scope parameter sources to the labeled function's own parameters, not every enclosing or lambda parameter", - "then re-measure: only a witness naming the real source should count" - ], - "method": "the same 8 path pairs, run with and without req.url/request.url/req.path/url.parse added to the source facts", - "question": "Does the missing `req.url` source token explain path's 0/8?", - "result": { - "with_req_url_added": "0/8", - "with_shipped_facts": "0/8" - }, - "verdict": "FALSIFIED. The source token was not the cause, and adding it converts nothing.", - "why_the_obvious_fix_is_wrong": "Relaxing the filter alone raises the number with a FALSE witness. With parameter sources on, the flows found in that closure are `res -> fs.readFileSync(...)` and `this -> ...`, neither of which is the vulnerability -- the real path is req.url -> url -> resolveUrl(...) -> possibleFilename -> sink, which also crosses a helper call. Turning a miss into a wrong entailment is worse than the miss: it is the arbiter asserting something untrue, which is the one failure mode this architecture exists to prevent." - }, "per_family": { "access_control": { "any_verdict_rate": 0.75, @@ -73,13 +27,13 @@ "pairs": 8 }, "config_secrets": { - "any_verdict_rate": 0.1, + "any_verdict_rate": 0.0, "corroborated": 0, "distinguished": 0, "distinguished_rate": 0.0, - "entailed": 1, - "entailed_rate": 0.1, - "none": 9, + "entailed": 0, + "entailed_rate": 0.0, + "none": 10, "pairs": 10 }, "deserialization": { @@ -93,13 +47,13 @@ "pairs": 3 }, "injection": { - "any_verdict_rate": 0.58, + "any_verdict_rate": 0.62, "corroborated": 0, - "distinguished": 18, - "distinguished_rate": 0.36, - "entailed": 29, - "entailed_rate": 0.58, - "none": 21, + "distinguished": 19, + "distinguished_rate": 0.38, + "entailed": 31, + "entailed_rate": 0.62, + "none": 19, "pairs": 50 }, "output_encoding": { @@ -113,13 +67,13 @@ "pairs": 1 }, "path": { - "any_verdict_rate": 0.0, + "any_verdict_rate": 0.125, "corroborated": 0, - "distinguished": 0, - "distinguished_rate": 0.0, - "entailed": 0, - "entailed_rate": 0.0, - "none": 8, + "distinguished": 1, + "distinguished_rate": 0.125, + "entailed": 1, + "entailed_rate": 0.125, + "none": 7, "pairs": 8 }, "prototype": { @@ -175,13 +129,13 @@ "pairs": 2 }, "sast": { - "any_verdict_rate": 1.0, + "any_verdict_rate": 0.875, "corroborated": 0, "distinguished": 4, "distinguished_rate": 0.5, - "entailed": 8, - "entailed_rate": 1.0, - "none": 0, + "entailed": 7, + "entailed_rate": 0.875, + "none": 1, "pairs": 8 }, "vfc": { @@ -195,13 +149,13 @@ "pairs": 1 }, "vfc-js": { - "any_verdict_rate": 0.4706, + "any_verdict_rate": 0.6471, "corroborated": 0, - "distinguished": 4, - "distinguished_rate": 0.2353, - "entailed": 8, - "entailed_rate": 0.4706, - "none": 9, + "distinguished": 6, + "distinguished_rate": 0.3529, + "entailed": 11, + "entailed_rate": 0.6471, + "none": 6, "pairs": 17 }, "vibe-py": { @@ -215,14 +169,6 @@ "pairs": 30 } }, - "remeasured": { - "families": [ - "access_control", - "config_secrets" - ], - "pairs": 18, - "why": "access_control was measured before the constraint_params / word-boundary fixes, which had it reporting every operation as guarded; config_secrets was routed through taint instead of the constant-abstraction arm. The flow families were unaffected and keep their original numbers." - }, "rows": [ { "distinguished": false, @@ -230,7 +176,7 @@ "fixed_rung": "model_entailed", "language": "python", "pair": "local-python-vulnerable", - "seconds": 32.4, + "seconds": 29.4, "slice": "local", "vuln_rung": "model_entailed", "witness": "request.args[\"expr\"] -> eval(request.args[\"expr\"]) (line 28, 1 steps)" @@ -252,7 +198,7 @@ "fixed_rung": "model_entailed", "language": "python", "pair": "sven-cwe-078-os-system", - "seconds": 26.9, + "seconds": 29.5, "slice": "github", "vuln_rung": "model_entailed", "witness": "username -> os.system(\"useradd -G docker,wheel -p \" + encPass + \" \" + username) (line 10, 2 steps)" @@ -263,7 +209,7 @@ "fixed_rung": "model_entailed", "language": "python", "pair": "sven-cwe-078-shell-true", - "seconds": 28.6, + "seconds": 29.7, "slice": "github", "vuln_rung": "model_entailed", "witness": "cmd -> _exec_cmd(self, cmd) (line 14, 2 steps)" @@ -274,7 +220,7 @@ "fixed_rung": "none", "language": "python", "pair": "sven-cwe-089-execute-percent", - "seconds": 27.9, + "seconds": 28.9, "slice": "github", "vuln_rung": "model_entailed", "witness": "game -> cursor.execute(\"SELECT x,y,letter FROM moves WHERE gameID = %d;\" % game) (line 12, 3 steps)" @@ -285,7 +231,7 @@ "fixed_rung": "none", "language": "python", "pair": "sven-cwe-089-query-concat", - "seconds": 27.1, + "seconds": 30.5, "slice": "github", "vuln_rung": "none", "witness": "" @@ -296,7 +242,7 @@ "fixed_rung": "none", "language": "java", "pair": "hutool-cve-2018-17297", - "seconds": 29.4, + "seconds": 31.0, "slice": "github", "vuln_rung": "none", "witness": "" @@ -307,7 +253,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "node-serialize-cve-2017-5941", - "seconds": 28.2, + "seconds": 29.7, "slice": "github", "vuln_rung": "model_entailed", "witness": "obj -> eval(\"(\" + obj + \")\") (line 4, 2 steps)" @@ -318,7 +264,7 @@ "fixed_rung": "model_entailed", "language": "python", "pair": "owasp-python-codeinj", - "seconds": 28.0, + "seconds": 29.4, "slice": "sast", "vuln_rung": "model_entailed", "witness": "urllib.parse.unquote_plus(request.cookies.get(\"BenchmarkTest00074\", \"noCookieValueSupplied\")) -> exec(bar) (line 51, 9 steps)" @@ -329,7 +275,7 @@ "fixed_rung": "none", "language": "python", "pair": "owasp-python-deser", - "seconds": 27.6, + "seconds": 28.7, "slice": "sast", "vuln_rung": "model_entailed", "witness": "urllib.parse.unquote_plus(request.cookies.get(\"BenchmarkTest00078\", \"noCookieValueSupplied\")) -> pickle.loads(base64.urlsafe_b64decode(bar)) (line 53, 12 steps)" @@ -340,7 +286,7 @@ "fixed_rung": "none", "language": "python", "pair": "owasp-python-cmdi", - "seconds": 27.7, + "seconds": 28.3, "slice": "sast", "vuln_rung": "model_entailed", "witness": "request.form.get(\"BenchmarkTest00165\") -> subprocess.run(argList, capture_output = True, encoding = \"utf-8\") (line 57, 15 steps)" @@ -351,7 +297,7 @@ "fixed_rung": "none", "language": "python", "pair": "owasp-python-sqli", - "seconds": 28.0, + "seconds": 28.1, "slice": "sast", "vuln_rung": "model_entailed", "witness": "request.form.get(\"BenchmarkTest00099\") -> cur.execute(sql) (line 49, 14 steps)" @@ -359,13 +305,13 @@ { "distinguished": false, "family": "config_secrets", - "fixed_rung": "model_entailed", + "fixed_rung": "none", "language": "python", "pair": "owasp-python-hash", - "seconds": 30.2, + "seconds": 28.6, "slice": "sast", - "vuln_rung": "model_entailed", - "witness": "response.set_cookie('BenchmarkTest00054', 'someSecret', max_age = 60 * 3, secure = True, path = request.path, domain = 'localhost') (line 26): permissive literal True" + "vuln_rung": "none", + "witness": "" }, { "distinguished": false, @@ -373,7 +319,7 @@ "fixed_rung": "model_entailed", "language": "java", "pair": "owasp-java-cmdi", - "seconds": 49.7, + "seconds": 49.6, "slice": "sast", "vuln_rung": "model_entailed", "witness": "getHeader(\"BenchmarkTest00007\") -> r.exec(args, argsEnv) (line 61, 10 steps)" @@ -384,7 +330,7 @@ "fixed_rung": "model_entailed", "language": "java", "pair": "owasp-java-sqli", - "seconds": 48.8, + "seconds": 49.2, "slice": "sast", "vuln_rung": "model_entailed", "witness": "getHeader(\"BenchmarkTest00008\") -> connection.prepareCall(sql) (line 57, 9 steps)" @@ -395,7 +341,7 @@ "fixed_rung": "none", "language": "java", "pair": "juliet-java-cwe78-exec", - "seconds": 47.9, + "seconds": 49.1, "slice": "sast", "vuln_rung": "model_entailed", "witness": "String data -> Runtime.getRuntime().exec(osCommand + data) (line 8, 2 steps)" @@ -406,7 +352,7 @@ "fixed_rung": "none", "language": "python", "pair": "openssl-cve-2022-1292", - "seconds": 1.2, + "seconds": 1.1, "slice": "vfc", "vuln_rung": "none", "witness": "" @@ -417,128 +363,128 @@ "fixed_rung": "none", "language": "python", "pair": "damn-vulnerable-graphql-application-views-mutate", - "seconds": 26.8, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "injection", - "fixed_rung": "none", - "language": "python", - "pair": "damn-vulnerable-graphql-application-views-resolve-pastes", - "seconds": 26.9, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "injection", - "fixed_rung": "none", - "language": "python", - "pair": "damn-vulnerable-graphql-application-views-resolve-system-dia", - "seconds": 26.8, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "injection", - "fixed_rung": "none", - "language": "python", - "pair": "djangoat-analytics-hits-by-ip", - "seconds": 30.4, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "deserialization", - "fixed_rung": "none", - "language": "python", - "pair": "djangoat-views-reset-password", - "seconds": 30.0, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": true, - "family": "injection", - "fixed_rung": "none", - "language": "python", - "pair": "djangoat-views-user-view", - "seconds": 31.2, - "slice": "vibe-py", - "vuln_rung": "model_entailed", - "witness": "request -> User.objects.raw(\"SELECT * FROM %s WHERE user_id='%s' ORDER BY is_admin='0'\" % (table_name,user_id_form)) (line 22, 9 steps)" - }, - { - "distinguished": false, - "family": "injection", - "fixed_rung": "none", - "language": "python", - "pair": "dsvpwa-attacks-run", - "seconds": 52.3, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "config_secrets", - "fixed_rung": "none", - "language": "python", - "pair": "dsvpwa-dsvpwa-main", - "seconds": 30.5, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "injection", - "fixed_rung": "none", - "language": "python", - "pair": "dsvpwa-handlers-do-bdr", - "seconds": 41.2, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "config_secrets", - "fixed_rung": "none", - "language": "python", - "pair": "dvpwa-app-init", - "seconds": 29.0, - "slice": "vibe-py", - "vuln_rung": "none", - "witness": "" - }, - { - "distinguished": false, - "family": "config_secrets", - "fixed_rung": "none", - "language": "python", - "pair": "dvpwa-middlewares-session-middleware", "seconds": 28.7, "slice": "vibe-py", "vuln_rung": "none", "witness": "" }, + { + "distinguished": false, + "family": "injection", + "fixed_rung": "none", + "language": "python", + "pair": "damn-vulnerable-graphql-application-views-resolve-pastes", + "seconds": 28.8, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "injection", + "fixed_rung": "none", + "language": "python", + "pair": "damn-vulnerable-graphql-application-views-resolve-system-dia", + "seconds": 28.6, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "injection", + "fixed_rung": "none", + "language": "python", + "pair": "djangoat-analytics-hits-by-ip", + "seconds": 27.3, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "deserialization", + "fixed_rung": "none", + "language": "python", + "pair": "djangoat-views-reset-password", + "seconds": 27.7, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": true, + "family": "injection", + "fixed_rung": "none", + "language": "python", + "pair": "djangoat-views-user-view", + "seconds": 27.5, + "slice": "vibe-py", + "vuln_rung": "model_entailed", + "witness": "request -> User.objects.raw(\"SELECT * FROM %s WHERE user_id='%s' ORDER BY is_admin='0'\" % (table_name,user_id_form)) (line 22, 9 steps)" + }, + { + "distinguished": false, + "family": "injection", + "fixed_rung": "none", + "language": "python", + "pair": "dsvpwa-attacks-run", + "seconds": 28.1, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "config_secrets", + "fixed_rung": "none", + "language": "python", + "pair": "dsvpwa-dsvpwa-main", + "seconds": 28.6, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "injection", + "fixed_rung": "none", + "language": "python", + "pair": "dsvpwa-handlers-do-bdr", + "seconds": 27.4, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "config_secrets", + "fixed_rung": "none", + "language": "python", + "pair": "dvpwa-app-init", + "seconds": 30.5, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, + { + "distinguished": false, + "family": "config_secrets", + "fixed_rung": "none", + "language": "python", + "pair": "dvpwa-middlewares-session-middleware", + "seconds": 37.2, + "slice": "vibe-py", + "vuln_rung": "none", + "witness": "" + }, { "distinguished": false, "family": "injection", "fixed_rung": "none", "language": "python", "pair": "dvpwa-student-create", - "seconds": 40.0, + "seconds": 32.1, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -549,7 +495,7 @@ "fixed_rung": "none", "language": "python", "pair": "extremely-vulnerable-flask-app-account-before-request", - "seconds": 30.8, + "seconds": 30.0, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -560,7 +506,7 @@ "fixed_rung": "none", "language": "python", "pair": "extremely-vulnerable-flask-app-account-search", - "seconds": 28.0, + "seconds": 28.6, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "request.args.get('search', '') -> text(f\"text like '%{search_param}%'\") (line 20, 6 steps)" @@ -571,7 +517,7 @@ "fixed_rung": "none", "language": "python", "pair": "extremely-vulnerable-flask-app-signup-validate-token", - "seconds": 27.7, + "seconds": 28.8, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "session -> session.execute(text(f\"\"\"\n SELECT id, code FROM {RegistrationCode.__tablename__} WHERE code = '{code}'\n \"\"\")) (line 15, 2 steps)" @@ -582,7 +528,7 @@ "fixed_rung": "none", "language": "python", "pair": "threatbyte-api-v1-delete", - "seconds": 27.7, + "seconds": 28.2, "slice": "vibe-py", "vuln_rung": "model_corroborated", "witness": "delete line 28: obligated operation with no discharging guard, and no guarded sibling" @@ -593,7 +539,7 @@ "fixed_rung": "none", "language": "python", "pair": "threatbyte-api-v1-get", - "seconds": 30.8, + "seconds": 28.1, "slice": "vibe-py", "vuln_rung": "model_corroborated", "witness": "get line 27: obligated operation with no discharging guard, and no guarded sibling" @@ -604,7 +550,7 @@ "fixed_rung": "none", "language": "python", "pair": "threatbyte-routes-dashboard", - "seconds": 27.8, + "seconds": 28.5, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "request.args.get('search', '') -> cursor.execute(s_query) (line 29, 8 steps)" @@ -615,7 +561,7 @@ "fixed_rung": "none", "language": "python", "pair": "vampi-user-model-get-user", - "seconds": 27.4, + "seconds": 27.7, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -626,7 +572,7 @@ "fixed_rung": "none", "language": "python", "pair": "vampi-users-update-password", - "seconds": 30.3, + "seconds": 28.8, "slice": "vibe-py", "vuln_rung": "model_corroborated", "witness": "update_password line 16: obligated operation with no discharging guard, and no guarded sibling" @@ -637,7 +583,7 @@ "fixed_rung": "none", "language": "python", "pair": "vfapi-main-delete-user", - "seconds": 27.6, + "seconds": 27.9, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -648,7 +594,7 @@ "fixed_rung": "none", "language": "python", "pair": "vfapi-main-put-user", - "seconds": 27.0, + "seconds": 28.1, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -659,7 +605,7 @@ "fixed_rung": "none", "language": "python", "pair": "vfapi-main-sql-return-users-from-username", - "seconds": 26.7, + "seconds": 27.8, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -670,7 +616,7 @@ "fixed_rung": "none", "language": "python", "pair": "vulnerable-python-apps-bad-mvc-do-get", - "seconds": 30.2, + "seconds": 29.3, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -681,7 +627,7 @@ "fixed_rung": "none", "language": "python", "pair": "vulnerable-python-apps-dir-traversal-do-get", - "seconds": 38.2, + "seconds": 28.6, "slice": "vibe-py", "vuln_rung": "none", "witness": "" @@ -692,7 +638,7 @@ "fixed_rung": "none", "language": "python", "pair": "vulnpy-cmdi-do-os-system", - "seconds": 45.5, + "seconds": 27.7, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "command -> os.system(command) (line 14, 2 steps)" @@ -703,7 +649,7 @@ "fixed_rung": "none", "language": "python", "pair": "vulnpy-cmdi-do-subprocess-popen", - "seconds": 31.3, + "seconds": 28.1, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "command -> subprocess.Popen(command, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, shell = True) (line 14, 2 steps)" @@ -714,7 +660,7 @@ "fixed_rung": "none", "language": "python", "pair": "vulpy-libuser-create", - "seconds": 35.7, + "seconds": 27.8, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "password -> c.execute(\"INSERT INTO users (username, password, failures, mfa_enabled, mfa_secret) VALUES ('%s', '%s', '%d', '%d', '%s')\" % (username,password,0,0,'')) (line 18, 4 steps)" @@ -725,7 +671,7 @@ "fixed_rung": "none", "language": "python", "pair": "vulpy-libuser-login", - "seconds": 54.1, + "seconds": 28.1, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "username -> c.execute(\"SELECT * FROM users WHERE username = '{}' and password = '{}'\".format(username, password)) (line 20, 5 steps)" @@ -736,21 +682,21 @@ "fixed_rung": "none", "language": "python", "pair": "vulpy-libuser-password-change", - "seconds": 49.6, + "seconds": 27.7, "slice": "vibe-py", "vuln_rung": "model_entailed", "witness": "password -> c.execute(\"UPDATE users SET password = '{}' WHERE username = '{}'\".format(password, username)) (line 20, 5 steps)" }, { - "distinguished": false, + "distinguished": true, "family": "path", - "fixed_rung": "none", + "fixed_rung": "model_corroborated", "language": "javascript", "pair": "angular-http-server-1-0-0", - "seconds": 32.3, + "seconds": 30.7, "slice": "vfc-js", - "vuln_rung": "none", - "witness": "" + "vuln_rung": "model_entailed", + "witness": "req.url.split('?')[0] -> fs.readFileSync(possibleFilename) (line 38, 10 steps)" }, { "distinguished": true, @@ -758,21 +704,21 @@ "fixed_rung": "none", "language": "javascript", "pair": "apex-publish-static-files-2-0-0", - "seconds": 32.2, + "seconds": 30.4, "slice": "vfc-js", "vuln_rung": "model_entailed", "witness": "this -> execSync(\n\t\t\t\t'\"' + opts.sqlclPath + '\"' + // Sqlcl path\n\t\t\t\t' ' + opts.connectString + // Connect string (user/pass@server:port/sid)\n\t\t\t\t' @\"' + path.resolve(__dirname, 'lib/script') + '\"' + // Sql t (line 61, 2 steps)" }, { - "distinguished": false, + "distinguished": true, "family": "injection", "fixed_rung": "none", "language": "javascript", "pair": "bestzip-2-1-6", - "seconds": 29.1, + "seconds": 31.9, "slice": "vfc-js", - "vuln_rung": "none", - "witness": "" + "vuln_rung": "model_entailed", + "witness": "options -> cp.exec(command, {\n stdio: \"inherit\",\n cwd: options.cwd\n }) (line 22, 13 steps)" }, { "distinguished": false, @@ -780,10 +726,10 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "clamscan-1-2-0", - "seconds": 46.0, + "seconds": 46.4, "slice": "vfc-js", "vuln_rung": "model_entailed", - "witness": "this -> execFile(self.settings[self.scanner].path, self._build_clam_args(path), (err, stdout, stderr) => {\n const {is_infected, viruses} = self._process_result(stdout, path);\n\n (line 1401, 49 steps)" + "witness": "this -> execFile(self.settings[self.scanner].path, self._build_clam_args(path), (err, stdout, stderr) => {\n const {is_infected, viruses} = self._process_result(stdout, path);\n\n (line 1401, 46 steps)" }, { "distinguished": false, @@ -791,7 +737,7 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "diskusage-ng-0-2-6", - "seconds": 31.5, + "seconds": 30.4, "slice": "vfc-js", "vuln_rung": "model_entailed", "witness": "this -> exec('df -k \"' + path + '\"', function(err, stdout) {\n if (err) {\n return cb(err);\n }\n\n try {\n cb(null, parse(stdout));\n } catch (e) {\n cb(e (line 19, 2 steps)" @@ -805,7 +751,7 @@ "seconds": 30.6, "slice": "vfc-js", "vuln_rung": "model_entailed", - "witness": "hostname -> shell.exec(cmd, {silent: true}) (line 22, 7 steps)" + "witness": "hostname -> shell.exec(cmd, {silent: true}) (line 22, 6 steps)" }, { "distinguished": false, @@ -813,7 +759,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "glance-3-0-0", - "seconds": 29.5, + "seconds": 32.9, "slice": "vfc-js", "vuln_rung": "none", "witness": "" @@ -824,7 +770,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "hot-formula-parser-3-0-0", - "seconds": 47.8, + "seconds": 51.5, "slice": "vfc-js", "vuln_rung": "model_entailed", "witness": "yytext -> eval(\"[\" + yytext + \"]\") (line 166, 2 steps)" @@ -835,21 +781,21 @@ "fixed_rung": "none", "language": "javascript", "pair": "libnmap-0-4-11", - "seconds": 31.1, + "seconds": 32.7, "slice": "vfc-js", "vuln_rung": "none", "witness": "" }, { - "distinguished": false, + "distinguished": true, "family": "injection", "fixed_rung": "none", "language": "javascript", "pair": "pdf-image-1-0-5", - "seconds": 30.9, + "seconds": 32.9, "slice": "vfc-js", - "vuln_rung": "none", - "witness": "" + "vuln_rung": "model_entailed", + "witness": "this -> exec(getInfoCommand, function (err, stdout, stderr) {\n if (err) {\n return reject({\n message: \"Failed to get PDF'S information\",\n error: err,\n stdout: s (line 34, 12 steps)" }, { "distinguished": false, @@ -857,7 +803,7 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "pidusage-1-0-0", - "seconds": 31.6, + "seconds": 32.8, "slice": "vfc-js", "vuln_rung": "model_entailed", "witness": "this -> exec(cmd + pid, function(err, stdout, stderr) {\n if(err)\n return done(err, null)\n\n stdout = stdout.split(os.EOL)[1]\n stdout = stdout.replace(/^\\s+/, '').replace(/\\s\\s+/g, ' ').sp (line 116, 2 steps)" @@ -868,7 +814,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "portprocesses-1-0-4", - "seconds": 29.0, + "seconds": 30.4, "slice": "vfc-js", "vuln_rung": "none", "witness": "" @@ -879,7 +825,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "serve-here-js-1-1-0", - "seconds": 28.6, + "seconds": 29.7, "slice": "vfc-js", "vuln_rung": "none", "witness": "" @@ -890,7 +836,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "static-eval-1-1-1", - "seconds": 35.5, + "seconds": 34.9, "slice": "vfc-js", "vuln_rung": "none", "witness": "" @@ -901,7 +847,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "thenify-3-3-0", - "seconds": 31.5, + "seconds": 31.7, "slice": "vfc-js", "vuln_rung": "model_entailed", "witness": "this -> eval(createWrapper($$__fn__$$.name, options)) (line 29, 4 steps)" @@ -912,21 +858,21 @@ "fixed_rung": "none", "language": "javascript", "pair": "underscore-1-13-0-0", - "seconds": 30.2, + "seconds": 33.0, "slice": "vfc-js", "vuln_rung": "none", "witness": "" }, { - "distinguished": true, + "distinguished": false, "family": "injection", - "fixed_rung": "none", + "fixed_rung": "model_entailed", "language": "javascript", "pair": "whereis-0-4-0", - "seconds": 29.1, + "seconds": 34.0, "slice": "vfc-js", "vuln_rung": "model_entailed", - "witness": "name -> cp.exec('which ' + name, function(error, stdout, stderr) {\n stdout = stdout.split('\\n')[0];\n if (error || stderr || stdout === '' || stdout.charAt(0) !== '/') {\n stdout = stdout.split('\\n') (line 15, 3 steps)" + "witness": "cb -> cp.exec('where ' + name, function (error, stdout, stderr) { //windows\n if (error || stderr || stdout === '' || stdout.indexOf('\\\\') === -1) {\n cp.exec('for %i in (' + name + '. (line 21, 3 steps)" }, { "distinguished": false, @@ -934,7 +880,7 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "anastasios-pw-session-14ec1a", - "seconds": 28.6, + "seconds": 38.9, "slice": "agent-vfc", "vuln_rung": "model_entailed", "witness": "request: Request -> request.isNavigationRequest (line 14, 2 steps)" @@ -945,7 +891,7 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "astroclaw-pw-session-1553a8", - "seconds": 28.7, + "seconds": 34.6, "slice": "agent-vfc", "vuln_rung": "model_entailed", "witness": "request: Request -> request.isNavigationRequest (line 14, 2 steps)" @@ -956,7 +902,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "capgo-app-hono-4dadd2", - "seconds": 30.7, + "seconds": 10.1, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -967,7 +913,7 @@ "fixed_rung": "none", "language": "python", "pair": "dnf-plugin-anyrepo-config-26d19a", - "seconds": 27.4, + "seconds": 28.6, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -978,7 +924,7 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "edutrace-page-ee7ba2", - "seconds": 33.8, + "seconds": 35.0, "slice": "agent-vfc", "vuln_rung": "model_entailed", "witness": "this -> setFormData(prevData => {\n const newData = JSON.parse(JSON.stringify(prevData));\n let current = newData;\n for (let i = 0; i < keys.length - 1; i++) {\n current = current[keys[i]]; (line 65, 2 steps)" @@ -989,7 +935,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "etude-lexical-markdown-editorconfig-c61a8b", - "seconds": 28.7, + "seconds": 30.2, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1000,7 +946,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "etude-lexical-markdown-editorconfig-db4f54", - "seconds": 28.9, + "seconds": 32.9, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1011,10 +957,10 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "market-cap-route-4f8ae9", - "seconds": 29.6, + "seconds": 33.6, "slice": "agent-vfc", "vuln_rung": "model_entailed", - "witness": "request: NextRequest -> request.url (line 14, 2 steps)" + "witness": "new URL(\"/login?error=confirm\", request.url) -> NextResponse.redirect(new URL(\"/login?error=confirm\", request.url)) (line 27, 2 steps)" }, { "distinguished": false, @@ -1022,7 +968,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "melodix-playerprovider-089931", - "seconds": 30.1, + "seconds": 12.1, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1033,7 +979,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "mercado-do-vale-news-catalogmetadataservice-9b5fcf", - "seconds": 28.5, + "seconds": 11.6, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1044,7 +990,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "money-track-category-icons-4d4a5b", - "seconds": 28.9, + "seconds": 31.1, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1055,7 +1001,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "nestjs-filter-normalizer-aa0e60", - "seconds": 29.2, + "seconds": 30.7, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1066,7 +1012,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "new-erp-final-app-6e9644", - "seconds": 30.7, + "seconds": 10.4, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1077,10 +1023,10 @@ "fixed_rung": "model_entailed", "language": "javascript", "pair": "nimestream-route-d17f53", - "seconds": 30.5, + "seconds": 32.1, "slice": "agent-vfc", "vuln_rung": "model_entailed", - "witness": "request -> request.url (line 14, 2 steps)" + "witness": "new URL(request.url) -> fetch(imageUrl, {\n headers: {\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',\n 'Referer': referer,\n (line 57, 18 steps)" }, { "distinguished": false, @@ -1088,7 +1034,7 @@ "fixed_rung": "model_corroborated", "language": "python", "pair": "openniw-jobs-0fc947", - "seconds": 26.8, + "seconds": 27.9, "slice": "agent-vfc", "vuln_rung": "model_corroborated", "witness": "get_job line 16: obligated operation with no discharging guard, and no guarded sibling" @@ -1099,7 +1045,7 @@ "fixed_rung": "model_corroborated", "language": "python", "pair": "openniw-jobs-b74de3", - "seconds": 26.9, + "seconds": 31.3, "slice": "agent-vfc", "vuln_rung": "model_corroborated", "witness": "get_job line 16: obligated operation with no discharging guard, and no guarded sibling" @@ -1110,7 +1056,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "overleaf-with-claude-exportscontroller-3980b9", - "seconds": 1.1, + "seconds": 1.4, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1121,7 +1067,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "popmark-editorconfig-e5ac40", - "seconds": 32.1, + "seconds": 35.9, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1132,7 +1078,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "rag-pipeline-utils-config-handler-76e5f0", - "seconds": 31.8, + "seconds": 44.1, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1143,7 +1089,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "registry-proxy-worker-426847", - "seconds": 28.4, + "seconds": 17.1, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1154,7 +1100,7 @@ "fixed_rung": "model_corroborated", "language": "javascript", "pair": "supplieradvisor-mvp-route-387bcf", - "seconds": 31.8, + "seconds": 43.1, "slice": "agent-vfc", "vuln_rung": "model_corroborated", "witness": "PATCH line 37: obligated operation with no discharging guard, and no guarded sibling" @@ -1165,7 +1111,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "supplieradvisor-mvp-route-a69e8f", - "seconds": 30.4, + "seconds": 53.0, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1176,7 +1122,7 @@ "fixed_rung": "none", "language": "python", "pair": "tools-cli-tools-a96bc0", - "seconds": 29.0, + "seconds": 51.0, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1187,7 +1133,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "trackly-cli-path-diagnostics-1c1aed", - "seconds": 29.9, + "seconds": 51.1, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1198,7 +1144,7 @@ "fixed_rung": "none", "language": "python", "pair": "upstreamdrift-local-server-c3a078", - "seconds": 28.4, + "seconds": 43.4, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1209,7 +1155,7 @@ "fixed_rung": "none", "language": "python", "pair": "waggledance-swarm-ssrf-host-guard-9a4548", - "seconds": 29.3, + "seconds": 42.7, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1220,7 +1166,7 @@ "fixed_rung": "none", "language": "javascript", "pair": "workers-research-utils-209444", - "seconds": 31.8, + "seconds": 48.7, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" @@ -1231,25 +1177,11 @@ "fixed_rung": "none", "language": "javascript", "pair": "zoonk-origin-bfbf67", - "seconds": 27.8, + "seconds": 12.7, "slice": "agent-vfc", "vuln_rung": "none", "witness": "" } ], - "scope_caveat": { - "entailed_among_them": 14, - "examples": [ - "hutool-cve-2018-17297", - "juliet-java-cwe78-exec", - "local-javascript-vulnerable", - "local-python-vulnerable", - "node-serialize-cve-2017-5941", - "owasp-java-cmdi" - ], - "note": "These are arbitrated over the whole file rather than a labeled function, so a verdict may be about a real finding other than the labeled one. owasp-python-hash is the clear case: a CWE-327 weak-hash pair credited for a permissive set_cookie elsewhere in the file, on both sides.", - "of_total": 92, - "pairs_without_a_function_label": 16 - }, "task": "model-grounded-detection 4.2 \u2014 entailment ceiling with the full model layer (taint + dominance)" } diff --git a/src/openultrasast/ruleset/semantic/java.toml b/src/openultrasast/ruleset/semantic/java.toml index 8f9e434..8e11a1b 100644 --- a/src/openultrasast/ruleset/semantic/java.toml +++ b/src/openultrasast/ruleset/semantic/java.toml @@ -29,3 +29,39 @@ cwe = "CWE-327" calls = ["getInstance"] rule_ids = ["java-weak-hash"] weak_literals = ["MD5", "SHA-1", "SHA1"] + +# --- model-grounded-detection: Java web sinks -------------------------------------------------------------- +# Java shipped with injection, deserialization and crypto sinks only, so the path and output_encoding families +# had nothing routing to them by CWE and a Java pair in either was unreadable (hutool-cve-2018-17297 reported +# "no path spec for java"). Documented dangerous APIs of the JDK and the servlet API, provenance per entry. + +[[sink]] +# CWE-22. The JDK's filesystem entry points that accept a caller-supplied path. +id = "file.open" +cwe = "CWE-22" +calls = ["File", "FileInputStream", "FileOutputStream", "FileReader", "FileWriter", "RandomAccessFile", "Paths.get", "Files.newInputStream", "Files.readAllBytes"] +rule_ids = [] + +[[sink]] +# CWE-79. Servlet response writers: what reaches these reaches the browser unescaped. +id = "response.write" +cwe = "CWE-79" +calls = ["println", "print", "write", "getWriter", "setHeader", "addHeader"] +rule_ids = [] + +[[sink]] +# CWE-918 / CWE-601: outbound requests and redirects to a caller-supplied destination. +id = "outbound.request" +cwe = "CWE-918" +calls = ["openConnection", "openStream", "sendRedirect", "getForObject", "exchange"] +rule_ids = [] + +[[sanitizer]] +# CWE-22 / CWE-79. The documented normalising and encoding APIs; ESAPI is what the OWASP suite itself uses. +id = "java.escape" +calls = ["getCanonicalPath", "normalize", "ESAPI.encoder", "encodeForHTML", "encodeForURL", "StringEscapeUtils.escapeHtml4", "URLEncoder.encode"] + +[[sanitizer]] +id = "parameterized_statement" +calls = ["prepareStatement", "setString", "setInt"] +parameterized = true