ptai 1.1.0 — verification coverage + resilience (Juice Shop 0→12 verified)#20
Merged
Conversation
Scope safety: the web scan scraped external links from a target's content and fed them to sqlmap/dalfox, actively testing third parties outside the engagement. Active-tool targets are now host-locked to the engagement host. This also stops the scan from overloading and crashing the target before the verify phase, which is what produced 0 verified findings on otherwise-vulnerable apps. Path-traversal oracle: a traversal finding is now oracle-verified (re-fetch the payload, confirm the file content reproduces, benign control twin). ptai demo is now 4 findings, all 4 oracle-VERIFIED.
A trusted-proxy header bypass is now oracle-verified: re-send the request with the bypass header and confirm privileged 2xx access, re-send without it and confirm denial (401/403). The with/without differential is the proof; a path that returns 200 to both is not gated and abstains. Takes the external-honeypot scan from 5 verified to 10 (the 5 critical X-Forwarded-User=admin bypasses).
… (recall cycle 2) Three new verification oracles, each proving via an attack-vs-control differential and reusing an existing OracleKind (no schema bump): - jwt_alg_none: an unsigned (alg:none) token is accepted while a bogus-signature token is rejected. - stored_xss: a unique canary planted via POST survives unescaped on read-back. - host_header_poison: a poisoned Host reflects in the response while the legit host does not. External-honeypot scan: verified 10 -> 14 (JWT alg:none x3 + host-header). The stored-XSS oracle is sound and unit-green but does not yet fire on the live stored-XSS findings end-to-end; the probe->oracle wiring is the next fix.
Comment/feedback sinks usually require auth, so the oracle now acquires a test session once (setting the session cookie and a bearer header) before the POST + read-back. Unit tests stub the acquisition to stay offline. (End-to-end verification on the honeypot still needs the probe to emit the actually-winning store param; tracked separately.)
- xxe: re-POST the XXE payload and confirm the disclosed file marker (root:x:0:0:) reproduces, with a benign no-entity control that must not. - type_confusion: confirm a type-confused value (negative quantity, zero price) is accepted while an obviously-invalid control is rejected. External-honeypot scan: verified 14 -> 17 (XXE + 2 type-confusion). Also hardens the stored-XSS probe to emit the actually-winning store field; that class still does not verify live end-to-end and stays tracked.
… status The oracle tried JSON first and broke on its 200, but a server that reads form fields returns 200 to a JSON POST while storing nothing, so the canary was never planted and stored XSS never verified. Now it reads back after each body shape (form first) and passes only when the raw canary survives unescaped. Stored XSS verifies end-to-end: external-honeypot scan 17 -> 20 verified.
…l cycle 4) Three oracles, each reusing an existing OracleKind (no schema bump): - ssrf: a non-blind fetch endpoint echoes an attacker-chosen URL's content (marker present for the probe URL, absent for a control). - mass_assignment: a privileged field persists on re-read after the write. - sequential_idor: one session reads >=2 distinct user records by walking ids. Wires the privilege_escalation_patch + idor_sequential probes to emit recipes. External-honeypot scan: verified 20 -> 21 (sequential IDOR). SSRF and mass-assignment verify in unit tests but not yet live end-to-end; tracked.
The prior with/without-field differential collapsed on a persistent state mutation: once role=admin is written it stays admin, so N/N replay on a shared record poisoned itself. The oracle now acquires its OWN fresh account each attempt (non-privileged baseline), locates its own record (signup user_id, else matching the signup email in the collection), writes the privileged value to itself, and re-reads, passing iff the field flips. Meaningful (a regular user escalated itself) and idempotent (each attempt is its own throwaway record). External-honeypot scan: verified 21 -> 22.
Server-side fetchers that echo the fetched body let an attacker make the server retrieve an arbitrary URL. The probe points the fetch parameter at the target's own root (reachable internal content) and confirms the content echoes back while an unreachable control does not, then emits the ssrf recipe the oracle re-proves. Turns the prior discovery-only SSRF finding into a VERIFIED one. External-honeypot scan: verified 22 -> 23 (14 distinct oracle-verified classes).
An aggressive sweep can knock a fragile single-container target over (Juice Shop under load). The verify phase ran once, after the whole sweep, against whatever was left, so a target that fell over mid-scan failed every oracle and the scan reported 0 verified despite valid, replayable recipes. The verify phase now health-checks the engagement target and waits for it to answer again before the oracle loop; a healthy target sees no delay. Juice Shop scan: 0 -> 12 verified (8 critical JWT alg:none, BOLA, 2 IDOR, type confusion), container survives.
Juice Shop's iconic SQLi (' OR 1=1-- in the login email field returns a valid
JWT) was detected but never verified: the probe omitted /rest/user/login from its
path list, and its recipe pointed at the boolean oracle, which only handles
GET-param SQLi. Adds /rest/user/login, a dedicated sqli_login_bypass oracle
(injection returns an auth token its false twin does not, N/N differential), and
points the recipe at it. Verifies 3/3 live against Juice Shop.
The probe can emit a (shape,payload) combo that tripped a non-token detection signal but returns no token on replay (a form POST to Juice Shop's JSON-only login). The oracle now tries the recipe's combo, then canonical JSON ' OR 1=1 --/' OR '1'='1 combos, passing on the first real token-vs-false-twin differential. Juice Shop's login bypass now verifies via the fallback.
CI caught a test still asserting the probe emits the boolean oracle; the probe now emits sqli_login_bypass. While fixing it, corrected the oracle's control: it used the SQL false-twin, but a comment-based bypass (... --) logs in regardless of the OR's truth, so the twin bypassed too and erased the differential (Juice Shop returns a token for both). The control is now a benign non-injection login, which fails normally. Juice Shop login bypass verifies 3/3.
Bumps to 1.1.0 (this is a minor release, not a 1.0.1 patch: it adds 10 new oracle classes, the verify-resilience fix, and the scope-safety fix). Rewrites the changelog into an honest 1.1.0 entry covering the new coverage, the fix that took Juice Shop from 0 to 12 verified, and the validation numbers.
0xSteph
added a commit
that referenced
this pull request
Jul 5, 2026
ptai 1.1.0 — verification coverage + resilience (Juice Shop 0→12 verified)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ptai 1.1.0 — verification coverage + resilience
Roughly doubles the vulnerability classes ptai can oracle-verify, and fixes the bug that made a scan of a live, otherwise-vulnerable app report 0 verified.
Added
alg:none, host-header poisoning, XXE, type confusion, stored XSS, sequential IDOR, mass-assignment, non-blind SSRF, SQLi login-bypass. ptai now verifies 14 distinct classes.ptai demo→ 4 findings, all 4 oracle-VERIFIED).Fixed
Validation
Known gaps (honest)