The pre-launch blocker push — five of the first-hour blockers fixed: scan findings and Repeater tabs now survive app close and project reopen, Repeater auto-updates Content-Length, the proxy can bind off-loopback for device testing, and interception is now rule-driven — alongside a detector-hardening pass over the passive scanner (mutation-proven regression coverage around every finding kind), the false-negative bugs those tests surfaced, and new Burp-parity features on the roadmap.
- add Intruder's payload processing gets an “Add raw payload” rule. A processing chain like hash → prefix only ever sees the value the step before it produced — so a sign-then-send payload (a hash or signature that needs the original value tacked back on next to it, like
<sha256><rawvalue>) had no way to reach back to the untouched original once an earlier rule had already overwritten it. A new rule re-inserts that original payload at any point in the chain, no matter how many steps ran before it. It shows up in the same rule dropdown as prefix/suffix/case/match-replace and needs no configuration. - add Match & replace can match plain text, not just patterns. Each proxy match/replace rule now has a “literal” option. Switch it on and whatever you type in the find box is matched exactly — a dot is a dot, a
?is a?— instead of being read as a regular expression, so you don't have to hand-escape a URL, a JSON fragment, or a version number. Regular expressions are still the default, and the choice is saved with the rule. (Match/replace sections for individual request-parameter names and values are still on the way.) - add Catch the response to just one intercepted request. When you're holding a request in the intercept editor, you can now forward it and grab only its response — without switching on response interception for every in-scope response (Burp's "Do intercept > Response to this request"). Hold a login POST, forward it, inspect the response it comes back with, and let all the other traffic keep flowing untouched. The one response is held even with the global response toggle off, and only for the request you flagged. (Wired through the API for now; the right-click option in the intercept view is next.)
- add Extensions can hand a request to Repeater or Intruder. An extension can now call
nullock.sendToRepeater(host, port, tls, request)ornullock.sendToIntruder(...)to drop a request it built or spotted straight into a new Repeater tab or Intruder's base request — the same "send to tool" flow you get from the history table. It's what lets an extension flag something and tee it up for hands-on testing without any copy-paste. (Sending to Comparer or Decoder from an extension is still to come.) - add Extensions can save their own settings and state. An extension can now remember data between runs with a simple key/value store —
nullock.storage.set(key, value)/get(key, default)(plushas,keys,remove,clear), the equivalent of Burp'spersistence().extensionData(). It holds text, numbers, and nested objects, saves to disk (outside the extensions folder, so saving doesn't set off auto-reload), and is still there after a restart — so an extension can stop hardcoding things like credentials in its source. The store is shared between extensions, so prefix your keys. - add Extensions can reload themselves as you edit them. Switch on auto-reload (launch with
--ext-autoreload, set theNULLOCK_EXT_AUTORELOADenvironment variable, or flip it via the API) and editing, adding, or removing an extension file reloads your extensions on its own — no more clicking Reload after every change while you're writing one. It's off by default so a running extension isn't torn down on an unrelated save, and saves are debounced so one edit means one reload. - add Extensions can run their own out-of-band (OOB) checks. A JavaScript extension can now mint a Collaborator-style payload with
nullock.collaborator.generate()(the equivalent of Burp'sapi.collaborator()), slip it into a request, and later read back withnullock.collaborator.interactions()any DNS or HTTP callbacks a target made to that payload — each with its token, source IP, and timing. That's the piece you need to write your own SSRF, blind-injection, XXE, or log4shell checks as an extension, and each extension only sees the interactions for the payloads it generated. (SMTP callbacks and the full raw callback body are still to come.) - add You can turn a single extension off without deleting it. Disabling one extension used to mean dragging its file out of the folder and reloading. Now each extension can simply be switched off — it stays installed and in the list but stops running, and switching it back on loads it again, the way Burp's per-extension "Loaded" checkbox works. The on/off choice is remembered across restarts and takes effect right away. (Driven through the API for now; the checkbox in the Extensions view is next.)
- add Extensions get a built-in toolbox of encoders and hashes. A JavaScript extension used to hand-write base64, hex, and hashing from scratch in old-style JS. It can now reach for ready-made helpers under
nullock.utils— base64, URL, hex, and HTML encode/decode, plus SHA-256, SHA-1, and MD5 (the equivalent of Burp'sapi.utilities()). They're plain text-in/text-out calls that need no permission, and they're backed by a small tested core so every extension gets the same correct result. (A byte-array type and gzip helpers are still to come.) - add Extensions can read recent proxy history. A JavaScript extension only ever got to see the one request or response it was handed the instant it fired — to know anything about the wider traffic it had to keep its own running tally. It can now ask for the recent history directly with
nullock.history(), getting back the last however-many proxy exchanges — method, host, URL, status code, response size, timing — so a recon or scanning extension can look back over what's been captured instead of rebuilding it by hand. It needs no special permission (it's the same traffic the extension already sees go by), and the list survives reloading the extension. - add Out-of-band DNS callbacks are recorded now, not just counted. Some of the most valuable findings only ever cause a DNS lookup — a Log4Shell where the outbound LDAP is firewalled but the DNS still escapes, or a blind SSRF/SQL-injection/XXE where name resolution is the only thing that gets out. Those callbacks were being used to auto-confirm findings, but the interaction itself was thrown away, so you couldn't go back and see what name was looked up, from where, or when. The DNS listener now keeps a list of every interaction you can page through, each showing the full queried name, the source IP, the timing, and the record type that was asked for. It also answers the right record type now — an IPv6 (AAAA) lookup gets an IPv6 answer, an IPv4 (A) lookup gets an A answer, and anything else gets a proper empty answer instead of a wrong one — while still logging the callback either way. (A dedicated interactions table in the Collaborator tab is the next step; read them from the API for now.)
- add Extensions can run cleanup code when they're unloaded. A JavaScript extension can now register a teardown callback —
nullock.onUnload(fn), or the Burp-compatible namenullock.registerUnloadingHandler(fn)— that runs just before the extension is torn down, whether you reload it, uninstall it, or quit the app. Until now a script was simply cut off with no warning, leaving no chance to flush its own state, close something it opened, or note that it stopped. The callback runs while the engine is still alive, needs no permission (it only touches the script's own state, never the traffic), and one misbehaving handler can't stop the others from running. - add Repeater unpacks gzip / deflate responses so you can read them. A compressed response used to show up in the Repeater response pane as a wall of binary garbage — you could see it arrived, but not what it said. Repeater now decompresses a
gzip,x-gzip, ordeflatebody and shows the readable text in its place, while keeping the response headers exactly as they came off the wire (so theContent-Encodingline still tells you it was compressed). The raw bytes are left untouched underneath, and the same decoding now also feeds body-matching in the template engine, so a rule looking for text in a response no longer misses it just because the server gzipped it. (Brotli and zstd aren't decoded yet.) - add Plaintext WebSocket (
ws://) connections are proxied properly now. An unencrypted WebSocket used to get its handshake answered and then the connection was simply dropped — the messages never actually flowed, weren't recorded, and couldn't be resent. They're now carried through frame by frame using the same path as securewss://, so plaintext WebSocket traffic turns up in the WebSocket history and can be inspected and replayed like anything else. - add Add a host to the “don't intercept” list up front. Nullock keeps a list of hosts whose encrypted traffic it passes straight through without intercepting. That list used to fill in only after a host refused interception — so a certificate-pinned app (common on mobile and desktop) had to fail once before Nullock left it alone. You can now add a host to the list ahead of time, so it's passed through cleanly from the very first connection. Together with the per-host removal added earlier, the list is now fully yours to manage. (Wildcards and IP ranges are next.)
- add Content discovery can sweep file extensions. Give it a wordlist and a set of extensions (
.php,.bak,.old,.zip…) and every word is tried both on its own and with each extension tacked on — the classic hunt for leftover backup files (config→config.php,config.bak…). Previously you had to spell out every combination in the wordlist yourself, which quickly hit the request limit; now the combinations are built for you and the limit counts the real total. (An extensions box in the discovery view is the next step; use the API for now.) - add You can keep out-of-scope traffic instead of losing it. Nullock filters traffic to hosts outside your scope out of history — good for privacy, but it means anything you browsed before narrowing your scope was gone for good. A new proxy switch lets you keep it: turn on “log out-of-scope traffic” and those requests stay in history and are searchable, so you can browse widely, decide scope afterwards, and still review what you already saw (the way Burp logs everything). It's off by default — the private option — and covers plain HTTP; an out-of-scope HTTPS host is still tunnelled straight through with nothing to record. (The “stop logging out-of-scope?” prompt and an in/out-of-scope tag on each row are still to come.)
- add Search can be case-sensitive, and can find what's missing. Two options join the search box. Case-sensitive matching (it still defaults to case-insensitive) for when the exact casing matters. And a negative match — ask for everything that does not contain the pattern, which is the quick way to answer “which of these requests is missing the auth header?” across everything you've captured. Both respect the same safety limits, and the negative match works across proxy history, Repeater and issues alike. (Narrowing a search to one branch of the site map is still to come.)
- add Search covers Repeater and issues now, not just proxy history. The search box only ever looked through captured proxy traffic, so a value you were poking at in a Repeater tab, or one buried in a finding the scanner raised, simply wouldn't turn up. It now searches those too, and every result is labelled with where it came from (
proxy,repeater, orissue) — Repeater request and response bodies follow the same request/response filter as history, and issues match on their summary, evidence, URL, host and kind. The same safety limits and one shared time budget cover every source, so it stays fast and can't be made to hang. (Intruder results and the site-map are the next sources to add.) - add All 50 teaching labs now have a real submit-flag success-check. The last ten labs (OAuth redirect_uri theft, credentials leaking via the URL/Referer, XXE, CRLF/response-splitting, dangerous HTTP methods, verb tampering, cache poisoning, sensitive file exposure, robots/sitemap disclosure, predictable session tokens) each gain a
/flagendpoint that only hands back the flag once the bug was actually exploited — not just visited. An OAuth lab needs a code genuinely delivered to an off-origin redirect_uri; the CRLF lab needs the injected header to land as a real second response header; the session-token lab needs an id you predicted, not one you logged in for yourself. Completes flag coverage for all 50 labs; XP/tracks and in-app wiring are still to come. - add Comparer handles bigger and lopsided inputs. The diff between two blobs was capped at 2000 tokens per side, so lining up a short value against a full-page response chopped the long side off right away — even though the short side left plenty of room. The cap is now based on the total work instead: a side that fits is kept in full and only an oversized side is trimmed, so comparing something short (a single injected value) against a 30 KB response now diffs the whole response, and two mid-sized responses compare at roughly double the old size. (Two genuinely huge responses still get trimmed — pushing that ceiling higher means running the diff off the request thread, which is the next step.)
- add You can now intercept HTTPS to a bare IP address. Proxying an internal box by its IP —
https://192.168.1.10/,https://10.0.0.5/— used to fail outright: the on-the-fly certificate Nullock generated always named the host as a DNS name, which browsers and clients reject for an IP, and the failed handshake then blocklisted the target for the rest of the session. The generated certificate for an IPv4 address now carries a proper IP-address entry, so the client accepts it and interception works like it does for any hostname. (And the per-host unblock added with the invalid-certificate work makes a host that got stuck this way easy to recover.) IPv6 addresses are still to come. - add Intruder can walk a token across requests (“recursive grep”). Some forms hand you a fresh anti-CSRF token or one-time nonce with every response and reject any request that reuses the old one — which normally makes them impossible to brute-force. Intruder's new recursive-grep payload type solves it: instead of a fixed list, each request's payload is the value pulled out of the previous response, chained forward. You give it a starting value and a number of requests; it runs one at a time (each needs the one before) and stops on its own if a response has nothing left to extract. It's the standard way to attack a token-protected form or walk a server-side state machine. (Driven through the API for now, reusing the grep-extract rule as the source; the payload-type picker in the Intruder UI is still to come.)
- add Intercept a box with a broken TLS certificate — on purpose, per host. A staging server with a self-signed or expired cert couldn't be intercepted before: the connection failed, and one attempt quietly blocklisted the host for good. Now you can add a specific
host:portto an accept-invalid-cert list and Nullock will go through, the way Burp does — but only for hosts you name, never a blanket “trust any bad cert” switch that could let an attacker's certificate slip through on some other host. It keeps the guardrails that matter: only ordinary validation problems (self-signed, expired, wrong name, unknown issuer) are waved through; a certificate flagged blacklisted or revoked still fails; the list starts empty and is saved per project, so a relaxed setting never follows you into the next engagement; and each accepted cert is logged with its SHA-256 fingerprint so an unexpected one stands out. Along the way the old “one failure blocklists the host forever” bug is fixed, with a new per-host unblock for hosts blocked for other reasons. (Per-request cert badges and certificate pinning are still to come.) - add Repeater shows how long a request took and how big the response was. Every send now records the round-trip time in milliseconds and the response size in bytes — the signal that matters for blind SQL injection, blind command injection and timing/race work, where how long did it take is the whole answer. The clock is measured around the real network round-trip (before the response is decoded or formatted), follows a redirect chain if that's on, and the numbers are kept per tab and saved with each prior send in the tab's history. (Wired through the backend and live snapshot now; drawing them in the Repeater pane is the last UI step.)
- add Editing an intercepted request fixes its Content-Length for you. Change the body of a request you've caught in the intercept editor and Nullock now recomputes its
Content-Lengthto match before sending it on — no more truncated requests or hung origins from a stale length (Burp's on-by-default behaviour, with an Update Content-Length checkbox right in the Intercept tab to turn it off, remembered per project). It's careful in the way a security tool has to be: aTransfer-Encoding: chunkedor duplicate-Content-Lengthrequest — the shape of a request-smuggling probe — is passed through untouched even with the switch on, so a desync you're deliberately sending still goes out as you typed it; only a single, unambiguous length is corrected, and your header names and line endings are left exactly as they were. (Editing a response's length is still to come — aHEADor304legitimately carries a length with no body, so that case needs more care.) - add The captured cookie jar survives a restart too. With the session rules already persisting, the cookie jar now saves with the project as well — the per-host cookies the proxy captured are written out when you close or switch projects and restored when you reopen, so an authenticated session survives a restart instead of making you log in again. The one thing it deliberately won't do is bring a dead session back to life: a cookie that has already expired (a logged-out or timed-out token) is dropped on load rather than replayed. Completes “cookie jar + session rules persist across restarts.”
- add Session rules survive a restart. Your session-handling rules — the ones that grab a value from a response (a CSRF token, a bearer token) and inject it into later requests — used to vanish every time you restarted. They now save with the project and come back when you reopen it, kept per project so one engagement's rules never leak into another's.
- add Triage findings: change severity, delete an issue. On top of marking false positives, you can now talk a finding's severity down (or up) when you've judged it, and delete an issue you don't want cluttering the list. Nothing is actually destroyed — both stick with the project and are reversible, so clearing a severity change or un-deleting brings the finding back exactly as the scanner found it. Completes the issue-triage workflow (false-positive, severity, delete). (The buttons in the Issues view are still to come.)
- add Advanced scope control. Scope used to be a simple list of host patterns to include or exclude. You can now write precise rules — by protocol, host, port (single or range), and path — so “everything under
app.example.comexcept/admin” or “only port 8443” is finally expressible. It layers on top of the existing host scope rather than replacing it, so turning it on never changes what was in scope before, and it's careful in the ways that matter for a security tool: a path/port exclusion actually filters in the proxy, anything a rule excludes stays excluded, and a bad regex can't hang the proxy. Rules save with the project. (The rule editor in the UI is still to come; set it through the API for now.) - add Content discovery runs in parallel now. The wordlist brute-force used to send one request at a time, so a real wordlist took forever. It now probes many paths at once (a concurrency setting, 1–64, with an optional throttle to stay polite), which is dramatically faster — roughly 4× on a small test and far more on a big list. It finds exactly the same paths as before: only the probing is parallel, the detection is unchanged. (Set through the API for now; the sliders in the discovery UI are still to come.)
- add Triage findings: mark false positives, hide noisy issue kinds. Cleaning up the issue list used to be all-or-nothing. Now you can mark a single finding as a false positive, or suppress an entire issue kind so it stops showing up — and both stick across restarts. Nothing is destroyed: because it's applied when the list is drawn, un-marking a finding or un-suppressing a kind brings it right back with no re-scan. (Driven through the API for now; the mark/suppress buttons in the Issues view are still to come.)
- add Repeater: Change request method / Change body encoding. Two new buttons on the Repeater request pane. ⇄ METHOD toggles
GET/POST, moving params between the query string and anapplication/x-www-form-urlencodedbody. ⇄ ENCODING converts that body tomultipart/form-dataand back. Both recomputeContent-Type/Content-Lengthso the edited request stays well-formed — a first-move test for HPP, CSRF, and upload-parser/WAF-bypass bugs that used to mean hand-editing raw bytes. - add Intruder can follow redirects too. The same redirect-following now runs during an attack: turn it on (never / on-site / in-scope / always, with the option to carry cookies) and each payload's request follows its redirect chain, so the result row — status, length, and every Grep column — grades against the final page instead of a wall of 302s. Handy for bruteforcing anything behind a login or redirect. Set via
/api/intruder/set. - add Repeater can follow redirects. A
3xxresponse used to leave you copying theLocationinto a new tab and rebuilding the cookie jar by hand — which bites on every login and OAuth flow. Repeater now follows redirects for you after a send, with the usual choices (never, on-site only, in-scope only, or always) and the option to carry cookies through the chain. It works out the right method (a formPOSTbecomes aGETon an ordinary redirect, but a307/308keeps the method and body), threads your original cookies plus anything the server sets along the way, and shows you the final page with a note of how many hops it took. - add Redirect-following gets a GUI control. Both Repeater and Intruder now have a FOLLOW dropdown (never / on-site / in-scope / always) and a COOKIES checkbox right next to their other send settings — no more driving the follow-redirect engine through raw API calls.
- add Intruder's Resend follows redirects too. Re-firing a single completed attack row used to skip the redirect-follow engine entirely, so a resend could grade against a different page than the original attack pass did. Resend now follows the same redirect chain, under the same FOLLOW/COOKIES setting, so it grades against the same final page.
- add Sequencer live capture — harvest a token corpus automatically. Sequencer could only score a corpus you'd assembled yourself (paste, or Send-to-Sequencer). It can now build the corpus for you: point it at a request, say where the token lives (a cookie, header, JSON field, or regex), and how many samples you want, and it fires that request over and over, pulling one token out of each response, then runs the randomness analysis on what it collected. Because it's actively generating traffic it's kept on a short leash — it only runs against a host you've put in scope, caps how many requests it will send, paces itself (backing off if the server says
429), and stops early if the target starts failing. And if the “token” turns out to be the same value every time, it tells you that plainly instead of reporting a scary-looking “predictable” verdict. (Driven through the API for now; the Live Capture panel in the Sequencer tab is still to come.) - add Send to Sequencer. Select a token in Proxy history's detail pane or in Repeater's request/response view — a session cookie, a CSRF token, a reset-URL token — and a new SEQUENCER/SEQ button sends it straight into Sequencer's manual-load corpus, switching tabs for you. Click it again on the next capture to build up a real sample set instead of copy-pasting each token by hand.
- add Session login macros with automatic re-authentication. A long Intruder run or audit scan that logs out midway used to silently churn out a page of meaningless redirects. You can now save a recorded login sequence as a named macro, run it on demand, and — the key part — attach a logged-out condition (a status code such as
401/403and/or a response-body pattern likesession expired). When a response shows the session has gone invalid, the macro re-runs on its own and re-acquires the session, so the tokens the following requests carry stay fresh. The re-login runs in the background (it never stalls the proxy) and is rate-limited per host, so a permanently-failing login can't hammer the target. (A visual macro editor is still to come.) - add Session login macros survive a restart. A saved login macro — its recorded steps and the logged-out condition that auto-re-runs it — now persists in the project file and is restored when the project reopens, instead of having to be re-entered every session. (The cookie jar and the session rules themselves still don't persist yet.)
- add Session rules can be scoped to tools. A session-handling rule (auto-inject a captured token or cookie into matching requests) can now be limited to — or kept out of — specific tools (proxy, repeater, intruder, scanner), rather than always applying in the proxy. Existing rules are unchanged. (Wiring the rule engine into Repeater/Intruder sends, and the per-tool editor checkboxes, are still to come.)
- add Point out-of-band detection at a hosted sink. Blind-vulnerability checks (SSRF, RCE, XXE, log4shell) rely on an out-of-band interaction server, and the built-in one was in-process — only reachable from your own machine. You can now run a
nullock-oastsink on a public box and point the app at it with--oast-remote, so those checks fire against real internet targets. Falls back to the local sink if the remote is down. - add Repeater keeps a per-tab send history. Every send used to overwrite the previous request and response in that tab — mutate a working request, break it, and there was no way back. Each tab now keeps a history of what you sent, so you can look back through prior sends, compare them, and re-load one. (The back/forward navigation UI is still to come.)
- add Record a Repeater chain from proxy history. Chains (multi-step request sequences with token passing) could only be hand-written as JSON. You can now select rows from the proxy history and turn them into a replayable chain in one call — each captured request becomes a step, ready to run or to edit in the
{{var}}extractions that carry a token from one response into the next request. (A visual macro editor is still to come.) - add Proxy interception is now rule-driven. Turning intercept on used to hold every in-scope message — every image, stylesheet, and beacon — one at a time. You can now define match rules (by method, URL, host, file extension, content-type, status code, or header, combined with And/Or) so only the requests and responses you care about are held. Rules persist per project. (A rules-editor UI is still to come; they're set via the API for now.)
- add Proxy can listen off-loopback for device testing. The proxy was hardwired to
127.0.0.1, so you couldn't point a phone, VM, or container at it.--proxy-bind=ADDRnow binds it to any interface — but because that exposes a cert-forging MITM to your whole network, a non-loopback bind is refused unless you also pass--proxy-bind-insecure, with a loud warning. Toggling the proxy keeps the bind instead of snapping back to loopback. - add Repeater tabs survive app close and project switch. Staged Repeater requests were wiped on every project switch and lost on close. They now save into the project file and restore when the project reopens — per project, so one engagement's requests (and their auth headers) never appear in another's. The tabs of the project you're leaving are saved before the switch; the incoming project's are loaded after.
- add Repeater auto-updates Content-Length on send. Editing a request body in Repeater used to leave a stale
Content-Lengthon the wire — the server would truncate the body or hang waiting for bytes that never arrive. Repeater now recomputes it from the actual body before each send (Burp's default), and it stays a toggle you can switch off to hand-craft a deliberately-desynced request for CL/TE smuggling tests. - add Scan findings survive app close and project reopen. Passive-scan findings were held in memory only, so an engagement's issue list evaporated on restart and was wiped on every project switch. Findings now persist to
findings.ndjsonin the project at discovery time and stream back into the panel on reopen — preserving each finding's original discovery time, enrichment (CWE / OWASP / CVSS), and the history row it points at, so click-to-jump still lands on the right request. The first pre-launch usability blocker, closed. - add Intruder "ECB block shuffler" payload type. Splits a hex ciphertext into blocks of a chosen size and emits the block-shuffled variants — the classic ECB token-forgery attack, where reordering ciphertext blocks reorders the decrypted plaintext. Deduped and capped; non-hex or misaligned input is rejected.
- add Intruder regex match/replace processing rule. Payload processing now offers
regex-replace— match a regular expression and replace every occurrence, with Burp-style back-references in the replacement ($0whole match,$1–$9groups,$$a literal$) — alongside the existing literal match/replace. - add Intruder "Modify case" processing rule — propername variants. Payload processing now offers
propername(Titlecase: upper-case the first character, lower the rest) andpropername-keep(upper-case the first, keep the rest) alongside upper/lower-case, matching Burp's Case-modification rule. - add Intruder "Illegal Unicode" payload type. Generates overlong UTF-8 encodings of a character (2–6 bytes) for WAF / path-normalization bypass —
/becomes%C0%AF,%E0%80%AF, and so on. Output is hex, optionally%-prefixed. - add Intruder "Username generator" payload type. Derives candidate usernames from a full name or email address using common schemes —
peter wienerbecomespeterwiener,peter.wiener,wienerpeter,peterw,pwiener, and more. Handy for auth/brute testing. - add Intruder "Substring" / "Reverse substring" payload-processing. Two new processing rules matching Burp:
substringslices from a 0-indexed start offset (with optional length), andreverse-substringcounts the offset and length from the end of the payload. Both are code-point-safe and leave the payload untouched on an out-of-range spec. - add Cookie jar respects cookie lifetime (Max-Age / Expires). The session cookie jar now understands
Max-AgeandExpires— computing an absolute expiry with the correct RFC 6265 precedence (Max-Age wins) and distinguishing session from persistent cookies. It's enforced: an already-expiredSet-Cookie(a logout) deletes the stored cookie, and an expired cookie is never re-injected — so a stale or logged-out session token is no longer replayed forever. - add Intruder "Grep - Payloads" reflected-payload flagging. Automatically flags a result row when one of its submitted payloads is reflected in the response — no hand-built per-payload match needle. The check is a literal substring test (a payload is data, not a pattern), the flag persists across save/resume, and it's off by default.
- add Intruder "URL-encode these characters" global safety net. Matches Burp's always-on payload encoder: a configured set of characters is percent-encoded in every Intruder payload (a new code-point-safe
url-encode-charsprocessing op, appended as the final step of every payload's chain). Off by default, so existing attacks are byte-for-byte unchanged. - fix Starting a project from a template now applies the template's match & replace rules. A project template can bundle proxy match/replace rules ready to go — the OAuth-review template, for one, ships a rule that flags an authorization request sent without its
stateparameter. Creating a project from a template set up the scope and notes but quietly dropped those rules, so a template that advertised them handed you none. They're applied to the new project now. (A template can also name extensions it wants enabled; that part isn't wired up yet — extensions currently load globally rather than per project — so for now the template just reports which ones it asked for.) - fix A session rule that sets a fixed value now actually fires. A session-handling rule with a hard-coded value — “always add
X-Debug: 1”, or set cookieenv=stagingon this host — never took effect: it has no captured{{variable}}, and the engine bailed out entirely whenever the host's variable bag was empty, so nothing was injected until some other rule happened to capture a value first. Static rules now apply regardless of what's been captured. And as a matched safeguard, a rule whose own{{variable}}was never captured is now skipped on its own instead of putting the literal text{{token}}on the wire — so one unresolved rule can't corrupt the request while the static rules beside it still work. - fix Django DEBUG page exposure is detected again. The
stack-djangodetector keyed on Django's URLconf error page but was gated to 5xx responses only — and that page renders on a 404, so it never fired in the wild. The gate now admits a 404 for the Django needle only (other framework stack needles stay 5xx-only, so an ordinary not-found page can't false-positive). - fix Outbound-PII check no longer skips public 172.x hosts. The data-exfiltration gate treated any
172.xhost as private, but RFC 1918 reserves only 172.16–31.x. SSN / card / phone / IBAN leaving to a public 172.x host (e.g.172.200.1.1) is now flagged; the genuine 172.16–31.x range stays private. - fix Verbose-error detection catches the two most common leaks. The SQL/framework error detector only scanned 4xx responses, missing a SQL error echoed in a 200 and a framework DEBUG page on a 500. It now uses a per-needle status policy: specific SQL signatures flag on any status, debug-page markers on 4xx and 5xx, while the generic php
Warning:/Notice:needles stay 4xx-only (so ordinary copy like "Warning: low battery" can't false-positive). - hardening Regression coverage locked across the passive scanner + JWT analysis. Every emitted finding kind — leaked-secret patterns, subdomain-takeover fingerprints, framework stack traces, cloud-storage endpoints, DOM-XSS sinks, outbound-PII, and verbose-error leaks — now has a mutation-proven test, so a future regex/gate regression can't silently disable a detector.