How it decides
Every verdict has a basis you can check.
RiftX reaches the verdict itself. Before it makes a single attempt, it characterizes what the fix actually does and writes that down. Everything the retest tries is derived from that record.
query parameter, reflected into a quoted HTML attribute
- Input filteringabsent
- Stored and returned as submitted, nothing stripped on the way in.
- Framework auto-escapingrobust
- Escapes by default, and nothing on this route marks the value safe.
- Output encodingrobust
- Brackets, quotes and ampersand map to entities after templating.
- Content-Security-Policyabsent
- No policy served, so nothing would stop execution if injection landed.
Target details are stand-ins. The characterization is real. This is the record every attempt is derived from, in the words the observer settles them in.
Three outcomes, and it will not talk itself into one
Fixed and Not Fixed clear the same confidence bar. Neither direction ships on a weaker standard than the other, because the one that quietly leaves a live vulnerability in production is “Fixed.”
Not Fixed
The finding still reproduces, or an attempt derived from the fix got past it.
Fixed
The finding did not reproduce, and the attempts the fix earned did not land.
the confidence bar
Needs Review
Neither call cleared the bar, or the run hit a boundary. It comes back to you rather than resolving itself.
The bar is a floor rather than a preference, and it cuts both ways: a call that lands under it is demoted to Needs Review whichever direction it was leaning. That costs us a cleaner looking report and it costs you a job you have to finish by hand. It is still the right trade, because the alternative is a green badge you cannot defend.
The attempts come from the fix, not from a list
A catalog of techniques is the easy half, and every scanner has one. Which of them this fix earns, and on what grounds, is the half a list cannot produce. It is why the same finding against two different fixes produces two different runs.
Observed
- HTML encoding on the reflection path, applied after templating.
- The reflection lands inside a double-quoted attribute.
- No Content-Security-Policy on the route.
Therefore
The attempts worth making are the ones that never need an angle bracket, and the ones that reach the parser through a layer the encoder never sees.
With no policy on the route, anything that lands will execute, so nothing here is unreachable. Attempts that assume an unencoded HTML body are not worth a request.
Result
Six attempts against the encoder and the attribute sink, all blocked.
One left unattempted. No reachable client-side sink to drive, recorded as a gap rather than counted as a pass.
Your steps to reproduce are the only input
There is no payload field, no injection parameter field, and no vulnerability type to pick. Any attack strings you want tried live in the notes as prose. RiftX works out the class itself once the retest starts, so nothing about the run was configured in advance at either end.
Why it works this way: it starts from what your tester actually wrote in the ticket, not from a clean proof of concept that may never have been captured. It retests the finding you reported and goes looking for nothing else.
Replay a reported finding against the live target.
Navigate to /search. Enter a script payload in the q parameter. The value reflects unescaped into the results heading and the alert box fires.
Whatever went into your report goes here as free text: steps to reproduce, impact, requests and responses, and any attack strings you want tried. There is no separate payload field.
The loop that attacks the fix is not the loop that decides
Three loops over one retest, and the one that ships the verdict never ran the attack. It is handed the capture rather than the run’s account of the capture, which is what makes the call something you can check: open the same evidence and reach your own.
A run that spends twenty minutes on a fix has a story about how that went. That story is exactly what the deciding loop is not given, because a story cannot be argued with afterwards and a capture can.
The run
produces the capture
Drives a real browser, works the fix, and captures every request, frame and step it takes. It reaches no verdict. What it came to believe about its own progress goes no further than the capture it produced.
- the capture crosses here
The judge
reads the capture
ships the verdict
A separate loop on its own budget. It reaches the call from the capture itself, which is a different document from the account the run kept of its own progress. Only one of the two can be checked afterwards.
The auditor
re-derives the verdict
Runs on every job without being asked and re-derives the verdict again, independently. It can return one for review, and that is the only thing it can do.
What the attack captures constrains the call rather than making it. A captured bypass gives the judge grounds to overturn a fix that appeared to hold, and an attack that captured nothing leaves that fix where it stands. Neither route reaches “Fixed” without the judge.
You keep both ends, and the middle is the part that repeats
Accountability does not delegate. Your name goes on the finding, which is the whole reason the evidence travels with the verdict. A retest is the same run of work every time, and only its two ends need you.
You start it
RiftX, unattended
You finish it
Send the finding you already wrote.
Scope, access, and the steps to reproduce. It retests what you reported, nothing else.
Review the evidence and deliver to the client.
Ask the examiner why a call landed where it did, answered from that retest’s own files. Override it when you disagree. Own what ships.
- Follows your steps
- Works out the fix
- Derives the attempts
- Reaches a verdict
- Writes the report
It follows the reported steps against the live target, works out what the fix does before touching it, derives the attempts from what it found and runs them, then reaches Fixed, Not Fixed or Needs Review from the captured evidence. The report is written by the time you open the job. That stretch is the same on the first finding you send and on every one after it.
You start it
Send the finding you already wrote.
Scope, access, and the steps to reproduce. It retests what you reported, nothing else.
RiftX, unattended
- Follows your steps
- Works out the fix
- Derives the attempts
- Reaches a verdict
- Writes the report
It follows the reported steps against the live target, works out what the fix does before touching it, derives the attempts from what it found and runs them, then reaches Fixed, Not Fixed or Needs Review from the captured evidence. The report is written by the time you open the job. That stretch is the same on the first finding you send and on every one after it.
You finish it
Review the evidence and deliver to the client.
Ask the examiner why a call landed where it did, answered from that retest’s own files. Override it when you disagree. Own what ships.
See it run
Watch it retest a finding you already know the answer to.
You have just read how the call gets made. The fastest way to judge whether it holds up is to watch one get produced for a finding your team already retested by hand, where you know the ground truth before we do.
