mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
feat(facts): PHP semantic facts, validated against a real PHP CPG
contributor-scan 5.1, the first step toward the v0.1 WordPress target. Written against a PHP CPG rather than against PHP source, because the two do not look alike. Verified with joern-parse 4.0.623 / php2cpg on a probe: $_GET["name"] -> call `<operator>.indexAccess`, CODE $_GET["name"] mysqli_query($conn, $sql) -> call NAMED mysqli_query echo $_GET["msg"] -> call NAMED echo So sources match on code and sinks match on name, and every entry the probe did not exercise is marked unverified in the file -- `include` and `require` among them, which is PHP's most characteristic path bug and the first thing to check on a real checkout. Five families derive (injection, output_encoding, path, deserialization, untrusted_destination) with no sink that is its own sanitizer -- asserted by a test, because that bug class has now appeared three times in three matchers. `php` is added to the region model's languages, without which the facts would have reached nothing. The arbiter decides 4 of 4 on the probe: the SQL concat entails, its `mysqli_real_escape_string` twin drops to corroborated, `echo` XSS entails and `system` command injection entails. **A whole scan finds 2 of those 3, and the gap is the finding.** PHP files yield FILE-LEVEL regions because no PHP entry points are mapped, and the taint arbiter returns one verdict per region per family -- so a file-level region reports at most one injection finding however many it holds. `system` won on flow length and the SQL injection went unreported. That is the mirror image of task 2.9: that one is many regions collapsing to one site, this is many sites collapsing to one verdict, and it bites hardest exactly where PHP needs it not to, since a WordPress file is large and has no decorator for the mapper to find. Recorded as task 5.4 with WordPress's registration model (add_action, add_filter, admin-ajax, REST routes), which the mapper already handles in principle for other frameworks. A 13-line probe is not a WordPress result. What is established is that the seam works end to end for PHP; everything about scale and coverage is unmeasured, and there are still zero PHP pairs in a corpus of 263 python, 351 c_cpp, 47 javascript and 49 java. Gates byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Opus 5
parent
b5d3cd6ab6
commit
61811512a8
@@ -377,6 +377,10 @@
|
||||
measurement that could produce a true positive.
|
||||
|
||||
- [ ] 5.1 PHP/WordPress slice
|
||||
- **Fact tables landed 2026-09-09** (`benchmarks/measurements/2026-09-09-php-facts.json`). Five families
|
||||
derive, and the arbiter decides a real PHP CPG 4 of 4 on a probe: SQL concat entails, its escaped twin
|
||||
drops to corroborated, `echo` XSS and `system` command injection entail. `php` added to the region
|
||||
model's languages. What remains is below.
|
||||
- Plugin and core weaknesses. `php2cpg` needs a PHP interpreter, which the image provides. **Validate on a
|
||||
sample that the model can read the pairs before vendoring** — the OWASP harvest found 238 and vendored 40
|
||||
for exactly this reason.
|
||||
@@ -404,6 +408,23 @@
|
||||
- _Requirements: 9.2, 9.4, 9.5, 9.6_
|
||||
- _Depends: 4.1_
|
||||
|
||||
- [ ] 5.4 WordPress entry points, and the one-verdict-per-region limit
|
||||
- Two things stand between the PHP facts and a WordPress result, and the second was found by running the
|
||||
first.
|
||||
- **Entry points.** WordPress registers handlers with `add_action`, `add_filter`, admin-ajax and REST
|
||||
routes. Nothing maps them, so every PHP file becomes one file-level region. The mapper already handles
|
||||
registration-based entry points for other frameworks (predecessor task 2.6), so this is a new recogniser
|
||||
rather than a new mechanism.
|
||||
- **One verdict per region per family.** The taint arbiter returns a single verdict for a region and
|
||||
family, so a file-level region reports at most one injection finding however many the file holds: on the
|
||||
probe, `system` won on flow length and the SQL injection went unreported. This is the mirror of 2.9 --
|
||||
that is many regions collapsing to one site, this is many sites collapsing to one verdict -- and it bites
|
||||
hardest where PHP needs it not to.
|
||||
- Observable: the probe reports 3 of 3, and a WordPress checkout yields function-scoped regions rather than
|
||||
one region per file.
|
||||
- _Requirements: 2.1, 8.1, 9.1_
|
||||
- _Depends: 5.1_
|
||||
|
||||
## Group 6 — Regression baselines
|
||||
|
||||
- [ ] 6.1 Repository baseline and delta
|
||||
|
||||
Reference in New Issue
Block a user