Xssmaze::Beacon
Execution oracle.
Every scoring path in this lab measures reflection: a scanner asks whether
its string came back in the HTML and calls that a finding. That is a proxy,
and a poor one — it scores a harmlessly-escaped echo as a hit, and it is
blind to the ~160 dom endpoints where the payload never reaches the server
response at all. The beacon replaces the proxy with proof: a payload has to
actually run to reach /beacon/<token>, so a hit in the log is a true
positive that no amount of string matching can fake.
/basic/level1/?query=<img src=/beacon/run1 onerror=fetch('/beacon/run1')> then: GET /beacon/log?token=run1
The recorded Referer is the payoff — it names the maze page that executed,
so a headless harness can fire one token for a whole sweep and still
attribute every hit to the endpoint that produced it.
Routes: ANY /beacon/<token> record a fire, answer with a 1x1 GIF GET /beacon/log the whole log GET /beacon/log?token=t one token DELETE /beacon/log clear it, so consecutive runs are isolated POST /beacon/log/clear the same reset for clients that cannot DELETE
This is instrumentation, not a maze, and it is deliberately boring: it never
calls Xssmaze.push (the catalog is a benchmark denominator and must not
grow a non-maze entry), it answers only image/gif and application/json,
and nothing it records is ever echoed into an HTML response.
Constants
The canonical 43-byte transparent 1x1 GIF: the smallest thing an
<img src=...> can load without drawing anything on the page under test.
A fuzzer pointing at /beacon/<random> must not be able to exhaust memory,
so the log is bounded on all three axes it can grow along: distinct tokens,
stored hits per token, and the length kept from each attacker-set header.
/beacon/log is the log API for every verb, so a token by that name could
never be read back. Refusing it up front beats letting a benchmark discover
the collision from a permanently empty result.
Class methods
no-store because a cached beacon is a silently lost signal, and the
wildcard CORS header because the payload firing it may well be running on
another origin. nosniff keeps a browser from ever second-guessing the
JSON content type and parsing a recorded Referer as markup.
Returns false only when the token cap refused a brand new token. Tokens already in the log keep recording, so a benchmark run in flight is never cut off by someone else fuzzing the beacon.