{ "caveat": "Every PHP number here comes from probe files of a dozen lines. The recogniser is validated on a WordPress-shaped sample, not on WordPress.", "generated": "2026-09-09", "native_run": { "build_seconds": 4.06, "entailed": 7, "environment": "eclipse-temurin:21-jre-noble + php-cli 8.3.6 + the same joern 4.0.623, no shim", "findings": [ "plugin.php:8:mp_fetch_report injection $_GET['id'] -> concat -> mysqli_query", "plugin.php:9:mp_fetch_report output_encoding echo of the query result", "plugin.php:14:mp_save_report injection $_POST['title'] -> concat -> mysqli_query", "plugin.php:18:mp_render_box output_encoding echo $_GET['banner']", "vuln.php:5:get_user injection $_GET['name'] -> concat -> mysqli_query", "vuln.php:12:show output_encoding echo $_GET['msg']", "vuln.php:13:run injection system($_POST['cmd'])" ], "query_seconds": 10.94, "reading": "Every intended vulnerability in both files is found, at the right function and line, with the WordPress-registered handlers ranked above the plain helper. safe_user is correctly absent -- its mysqli_real_escape_string drops it to corroborated, which the free pass does not report.", "regions": 10 }, "one_verdict_per_region_fixed": { "libpng": "1 -> 2 entailed; the second (contrib/libtests/makepng.c:1580:strstash) was hidden by the collapse. Neither is validated and both are in contrib/.", "php_probe": "2 of 3 -> 3 of 3; the SQL injection at vuln.php:5 had been losing to `system` on flow length", "vampi": "6 entailed, unchanged -- and now with line numbers on access-control findings from task 2.7", "what": "taint.verdicts() returns one verdict per distinct SINK SITE, strongest first, and its first element is exactly what verdict() returns -- so the pair path and every committed measurement resting on it are unchanged, and the gates are byte-identical." }, "reading": "Both halves of 5.4 work, and the frontend blocker recorded against them was the local shim rather than php2cpg. With a native php-cli a two-file PHP tree yields 10 function-scoped regions and 7 entailed findings at the right locations, in 15 seconds.", "spec": "contributor-scan 5.4 (Req 2.1, 8.1, 9.1)", "the_blocker": { "cause": "The shim ran each `php` invocation in its own container, which this machine needed because it has no PHP interpreter. php2cpg drives PHP-Parser per file and something in that per-invocation isolation kept only one file's JSON. The `====> File X:` banner that looked like the thread to pull was a symptom of the same thing, and it does not occur natively.", "detail": "A CPG over two PHP files contained only the last one alphabetically, reproduced twice. That was recorded as a php2cpg blocker for the WordPress target. It was wrong: rerun with a NATIVE php-cli (php 8.3.6, no shim) over the same two files, the CPG contains both, all eight methods, and no PHP-Parser banner warning appears at all.", "id": "php2cpg-emits-one-file", "lesson": "The workaround was the defect. Two independent reproductions agreed and both were measured through the same broken instrument, which is exactly how a measurement lies: it was consistent and wrong.", "status": "NOT A DEFECT -- it was the container shim, resolved 2026-09-09" }, "wordpress_recogniser": { "access_is_declared_not_guessed": "The hook name IS the declaration: wp_ajax_nopriv_* is WordPress saying logged-out callers reach this, so it is public; wp_ajax_* fires only for logged-in ones. permission_callback => __return_true declares a REST route open. That is the declared-provenance signal task 2.8 needs, arriving from a second framework.", "measured": "1 file-level region -> 10 function-scoped; mp_fetch_report public (rank 1.0), mp_save_report authenticated (0.8), mp_render_box public, mp_helper review-required", "what": "add_action / add_filter / add_shortcode with a string callback, and register_rest_route's callback with its permission_callback. Plus every top-level PHP function as its own region, without which a file is one region however many functions it holds." } }