// changelog

What shipped

Every release, newest first. Versions follow semver. Dates are when the build went out.

v3.8.0 Aug 20, 2026 released

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) or nullock.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) (plus has, keys, remove, clear), the equivalent of Burp's persistence().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 the NULLOCK_EXT_AUTORELOAD environment 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's api.collaborator()), slip it into a request, and later read back with nullock.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's api.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 name nullock.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, or deflate body and shows the readable text in its place, while keeping the response headers exactly as they came off the wire (so the Content-Encoding line 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 secure wss://, 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 (configconfig.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, or issue) — 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 /flag endpoint 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:port to 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-Length to 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: a Transfer-Encoding: chunked or duplicate-Content-Length request — 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 — a HEAD or 304 legitimately 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.com except /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 an application/x-www-form-urlencoded body. ⇄ ENCODING converts that body to multipart/form-data and back. Both recompute Content-Type/Content-Length so 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 3xx response used to leave you copying the Location into 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 form POST becomes a GET on an ordinary redirect, but a 307/308 keeps 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/403 and/or a response-body pattern like session 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-oast sink 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=ADDR now 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-Length on 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.ndjson in 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 ($0 whole match, $1$9 groups, $$ 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) and propername-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 wiener becomes peterwiener, 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: substring slices from a 0-indexed start offset (with optional length), and reverse-substring counts 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-Age and Expires — computing an absolute expiry with the correct RFC 6265 precedence (Max-Age wins) and distinguishing session from persistent cookies. It's enforced: an already-expired Set-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-chars processing 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 state parameter. 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 cookie env=staging on 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-django detector 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.x host 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.
v3.7.0 Jul 5, 2026 latest

The academy + platform-completion release: the full 50-lab Web Security Academy clone, the OWASP injection family completed, out-of-band auto-confirmation, and deployable standalone OAST + team-sync servers. Each feature shipped with an adversarial review and a regression test.

  • add 50-lab Web Security Academy clone. labs/01labs/50, each a single-file intentionally-vulnerable app mapped to a Nullock probe (XSS, SQLi, SSRF, XXE, IDOR, OAuth, GraphQL, deserialization, cache poisoning/deception, and more), verified end-to-end against its detector.
  • add OWASP injection family completed. LDAP + XPath injection (error-based with safe-value corroboration), first-class fetch-proven SSRF (cloud-metadata / file:// / internal, with encoding-bypass denylist), insecure deserialization (Java/PHP/Python/Ruby/.NET), active JWT attacks (alg:none / not-verified / weak-secret / RS256→HS256), cross-site WebSocket hijacking, host-header injection, and server-side prototype pollution.
  • add OAST out-of-band auto-confirmation. nullock oast blast sprays blind SSRF / OS-command-injection / XXE / Log4Shell payloads; a callback to the in-process HTTP or DNS sink auto-confirms the class via the correlator — a true-positive no response echo can give.
  • add Standalone deployable servers. nullock-oast (public callback sink) and nullock-workspace (team findings-sync, SQLite + bearer-key auth, identity-key merge), both Dockerized with deploy guides.
  • add Recon + discovery. Certificate transparency (crt.sh) in nullock recon, soft-404-calibrated content/directory discovery, CSRF-PoC generator, and copy-as-curl.
  • fix CVE database + enricher accuracy. Web-verified every CVE entry against NVD/vendor advisories (corrected ~11 over-broad/mis-scored entries, removed 3 bogus); every emitted finding kind now enriches to CWE/OWASP via family-prefix fallbacks.
v3.6.0 Jun 17, 2026

The platform release. The scanner grew a network layer and a full reporting + recon suite: a port-scan→findings bridge, a point-at-a-host recon→vuln pipeline, WAF/CDN and robots/sitemap recon, a live CVE-feed overlay, and engagement reporting (HTML with an A–F grade, JSON bundle, CycloneDX SBOM, OWASP/compliance coverage, asset inventory, posture grade, baseline diff). Each feature shipped with a multi-lens adversarial review and a regression test.

  • add WAF / CDN detection. nullock waf <url> identifies the protective infrastructure fronting a target — Cloudflare, Akamai, Imperva, AWS WAF/CloudFront, F5 BIG-IP, Fastly, Sucuri, NetScaler, FortiWeb, Reblaze, PerimeterX, DataDome, Vercel, Netlify, BunnyCDN, … (30+ vendors) — from response header/cookie signatures (wafw00f-class). Passive: it reads what the infra announces, sends no attack payload. Recon context Burp doesn't surface.
  • add robots.txt / sitemap recon. nullock robots <url> pulls /robots.txt and /sitemap.xml and surfaces the Disallow paths — the unlinked admin/backup/internal endpoints owners hide from crawlers — as recon findings, plus the sitemap URL set. Hidden attack surface, in one call.
  • add JSON master report. nullock report json emits one machine-readable bundle for CI / dashboards — posture grade, OWASP + compliance coverage, host inventory, and the full findings list, all from the same shared computations as the dedicated endpoints (so the numbers always agree).
  • add Report leads with the grade. The HTML engagement report now opens with the A–F security-posture badge (shared scoring with nullock posture, so they can't disagree) — the one-glance verdict above the severity breakdown and findings.
  • add More service-version CVEs. The banner→CVE matcher gained OpenSSH ssh-agent RCE (CVE-2023-38408), Apache mod_proxy request smuggling (CVE-2023-25690), and Apache mod_lua overflow (CVE-2021-44790) — version-range matched, with patched builds correctly excluded.
  • add More web-app CVE coverage. The fingerprint→CVE database gained Joomla (CVE-2023-23752 unauth config disclosure, CVE-2015-8562 object-injection RCE) and PHP (CVE-2024-4577 PHP-CGI argument-injection RCE) — the PHP entry split per maintained branch so a patched build isn't false-flagged.
  • fix Server CVEs now correlate. The curated Apache/HTTP-server CVEs (mod_proxy SSRF CVE-2024-38473, HTTP/2 Rapid Reset CVE-2023-44487) were filed under a kind nothing looked up — re-keyed to the server-apache/server-nginx the fingerprinter emits, with clean version pins, so a fingerprinted Server version actually flags them (and nginx Rapid Reset is now covered too).
  • add Live CVE feed sync. nullock cvefeed sync <url> (or load <file.json> for air-gapped) extends the service-version CVE matcher at runtime — overlay entries match by product + version range alongside the curated table, so detection coverage grows without a rebuild. The CVE feed Burp gates behind add-ons.
  • add OWASP & compliance coverage. nullock compliance rolls findings into a coverage matrix — grouped by OWASP Top-10 2021 category (all ten, with counts and which were hit) and by compliance tag (PCI-DSS, …). The audit/compliance reporting view Burp gates behind Enterprise.
  • add Security posture grade. nullock posture rolls all findings into one executive number — a letter grade (A–F) and 0–100 score, severity-weighted, with the breakdown and the top risks. The "how bad is it, in one glance" summary for the report header / dashboard.
  • add Findings baseline & diff. nullock baseline save snapshots the current findings; nullock baseline diff compares a later run against it and reports what's new (regressions), fixed (resolved), and unchanged. The repeat-engagement / re-test delta that Burp Pro lacks — persisted to the project so it survives restarts.
  • add CycloneDX SBOM export. nullock export sbom emits a CycloneDX 1.5 software bill of materials — components from detected technologies, vulnerabilities from correlated CVEs (with CVSS ratings and NVD links), each linked to its component. A supply-chain / compliance artifact (feeds Dependency-Track, etc.) that Burp doesn't produce.
  • add Asset inventory. nullock inventory rolls everything up into one record per host — open ports/services, detected technologies, and finding counts (by severity, with max CVSS and top severity) — sorted by risk. The "what do I actually know about each host" view that ties the network scan and the web findings together.
  • add HTML engagement report. nullock report html produces a self-contained, styled report — executive summary, severity breakdown (cards + stacked bar), and a per-finding table with CWE/OWASP/CVSS/remediation — that opens standalone in any browser. Every server/target-derived value is HTML-escaped, so the report can't become an XSS vector when you open it. (Markdown export via report build stays too.)
  • add Recon → vuln pipeline. nullock pipeline [host] is the point-at-a-host capstone: it bridges the port-scan results into network findings (exposed services + CVEs), then runs the safe web-identification battery — tech fingerprint (+CVE), security-header/CSP audit, HTTP-method audit, TLS inspection — against every open HTTP/HTTPS port discovered, and aggregates both layers into one severity-bucketed report. Scope-gated (out-of-scope hosts are skipped, not probed), idempotent across both layers, and web ports are classified so it won't fire HTTP probes at a confirmed non-HTTP service.
  • add Scan → findings bridge. nullock scan-findings turns the port scanner's results into first-class findings — exposed databases (MySQL/Postgres/Mongo/Redis/Elastic…), remote-admin (RDP/VNC/Telnet), management APIs (Docker/etcd/Kubernetes/Consul/Webmin), file shares (SMB/NFS), and cleartext protocols — plus banner→CVE correlation, so the network layer rides into the same findings list, report, SARIF export, and CWE/OWASP enrichment as every web finding. Pure transform: no extra packets (the scan was already scope-gated), idempotent on re-run, and severity is calibrated to each finding's CVSS.
  • fix The engagement report builder (/api/report/build) and the grouped-findings view returned zero findings due to an off-by-one in the "return all" code path — both now include the full finding set.
v3.5.0 Jun 11, 2026

The active-testing climb: a full battery of injection, access-control, and misconfiguration scanners, plus the offensive-expansion identification modules (service→CVE, ScopeGuard, TLS inspection, fingerprint, HTTP methods, subdomain takeover, exposure, cache deception) — each with adversarial review, a regression test, and built-in false-positive guards. Plus a tool-wide HTTP client correctness fix.

  • add Hidden parameter mining, IDOR/BOLA (API #1), mass-assignment (API #6), and active CORS exploitability — the API-security battery.
  • add JS recon. Mines same-origin bundles for API endpoints (real attack surface, including unlinked routes) and flags exposed source maps that leak original source.
  • add Race-condition tester. Fires N synchronized concurrent copies and flags a limited-use operation that leaked extra successes — distinguishing a real race from rate-limiting / overload.
  • add Verb-tampering auth bypass. Retries a denied request with alternate methods / override headers and flags any that flip to 2xx serving real content.
  • fix HTTP client no longer hangs on HEAD / 204 / 304 responses, correctly skips 1xx interim responses, and handles stacked Transfer-Encoding — across every active-testing feature.
  • add One-command deep audit. nullock audit <url> runs the whole battery against an endpoint; audit all sweeps every URL you give it plus every captured request — findings stream into the panel as they're confirmed.
  • add GraphQL schema analysis. nullock graphql schema <url> pulls the introspection schema and flags dangerous mutations (deleteUser, grantAdmin, …) and sensitive fields (password, apiKey, ssn) by camelCase/snake-boundary match — distinguishing a WAF/error page from genuinely-disabled introspection.
  • add Server-side template injection. nullock ssti <url> <param> injects a sentinel-bracketed arithmetic polyglot per engine family (Jinja2, Freemarker, ERB, Smarty, Razor, …) and confirms RCE-class SSTI when the server renders the product — immune to coincidental digits and locale number-grouping, and it fingerprints the engine. Burp Community has no SSTI check at all.
  • add Web cache poisoning. nullock cachepoison <url> reflects unkeyed headers (X-Forwarded-Host, X-Original-URL, …) behind a cache-buster and proves the poison end to end — a clean, header-less request served the sentinel from cache. It verifies the buster is part of the cache key first and refuses to inject otherwise, so a live run can't poison the response real users are served.
  • add Open redirect scanner. nullock openredirect <url> [param] fires a parser-confusion battery (scheme-relative, backslash, userinfo @, whitelist-prefix, missing-slash) and confirms only when the resolved Location host leaves the origin — no false positives from same-origin reflections, and it auto-detects the redirect param.
  • add The one-command deep audit now runs the full active battery — open-redirect, web-cache-poisoning, and per-parameter SSTI joined param-mining, IDOR, mass-assignment, CORS, and verb-tampering. nullock audit <url> and audit all surface every class in one pass.
  • add CSP & security-header auditor. nullock headeraudit <url> goes past "has a CSP" — it flags unsafe-inline that isn't neutralized by a nonce/hash, wildcard/scheme sources, missing object-src/base-uri, and allow-listed script-gadget hosts (Google APIs, common CDNs) an attacker can run script through — plus HSTS, nosniff, clickjacking, Referrer-Policy, and cookie-flag checks, following same-origin redirects to audit the real page.
  • add Client-side secret scanner. nullock secrets <url> fetches the page and its same-origin bundles and flags leaked credentials — AWS/Google/Stripe/GitHub/Slack/SendGrid keys, private-key blocks, and entropy-gated assigned secrets — every match masked so the finding locates the leak without re-exposing it. truffleHog-class coverage, in-line.
  • add CRLF / response-splitting detection. nullock crlf <url> [param] injects encoded-CRLF payloads carrying a uniquely-named marker header and confirms the bug only when that header actually appears in the parsed response — a real split, never a reflection false positive.
  • add Path traversal / LFI. nullock lfi <url> [param] fires a battery of traversal encodings (../, %2e%2e%2f, ....//, double-encoded, backslash) at /etc/passwd and win.ini and confirms by the file's content fingerprint — a line-anchored, multi-field signature that a prose mention can't trip — with a bounded request budget.
  • add OS command injection. nullock cmdi <url> [param] chains echo $((a*b)) through every separator (; | && $() backtick, newline) inside random sentinels and confirms RCE only when the shell returns the evaluated product — exact-match, no timing, no reflection false positives.
  • add Reflected XSS. nullock xss <url> [param] injects a random-marker tag and confirms only when the response is HTML, the angle brackets reflect unencoded, and the reflection lands in executable element content — a tiny HTML context scanner rules out JSON responses, comments, raw-text elements, and attribute values, so it doesn't cry wolf on every reflecting search box.
  • add SQL injection (error-based + blind time-based). nullock sqli <url> [param] injects syntax-breaking quotes and confirms only when a DBMS error surfaces that the baseline lacked and a balanced quote clears it — fingerprinting MySQL / PostgreSQL / MSSQL / Oracle / SQLite. Add blind for time-based detection: a SLEEP(5) that delays while the same-shape SLEEP(0) stays fast (and the delay reproduces) — the majority of real SQLi, which shows no error at all.
  • add XXE (XML external entity). nullock xxe <url> POSTs an XML body whose external entity targets a local file and confirms by that file's content signature in the response — and since the signature is remote file content (never in the request), an echo endpoint can't false-positive it.
  • add NoSQL injection. nullock nosqli <url> [param] tests the MongoDB-style operator class (param[$ne]= → auth bypass) with a literal/$ne/$eq differential gated on a two-shot stability baseline — so dynamic pages, type-confusion error paths, and non-Mongo apps don't trip it.
  • add ScopeGuard. Every active test, scan, audit, chain, intruder, repeater, and authz replay now refuses hosts the project marks out of scope — one authorization gate so a malicious local page can't pivot through Nullock to attack arbitrary hosts, and an operator can't accidentally hit a target they aren't authorized for. No change when no scope is set; it bites once in/out-of-scope rules exist.
  • add Web cache deception. nullock cachedeception <url> detects the path-confusion precondition — a dynamic/sensitive page also served at a static-extension URL (/account/x.css) a cache would store per-user — distinct from the cache-poisoning check, and higher-severity when the response is cacheable.
  • add Sensitive-file exposure scan. nullock exposure <url> probes high-value paths — .git/config, .env, phpinfo.php, server-status, Spring Actuator /env, config backups, AWS creds, .DS_Store — and confirms each by a content signature, so a server that 200s everything doesn't false-positive.
  • add One-call host assessment. nullock assess <url> runs the safe identification battery in a single pass — tech fingerprint (+CVE correlation), security-header/CSP audit, HTTP-method audit, and (for https) TLS inspection — and returns the aggregated, severity-bucketed findings. Point it at a host, get a report; the active injection battery stays opt-in via audit.
  • add Subdomain-takeover detection. nullock takeover <host> matches a curated table of dangling-service fingerprints (GitHub Pages, S3, Heroku, Azure, Fastly, Shopify, Pantheon, Ghost, Read the Docs…) to flag a subdomain whose DNS points at an unclaimed service — the classic bug-bounty takeover, identification-only.
  • add HTTP method audit. nullock methods <url> reads the OPTIONS Allow header and flags dangerous write methods (PUT/DELETE/PATCH) and WebDAV, plus a non-mutating TRACE echo probe for Cross-Site Tracing. Read-only — it never actively PUTs/DELETEs.
  • add Active tech fingerprint. nullock fingerprint <url> identifies the stack on demand — server, CMS, language, framework, JS libraries with versions from headers, cookies, and body/meta markers (WhatWeb/Wappalyzer class) — and auto-correlates versioned detections against the CVE database.
  • add TLS / certificate inspection. nullock tls <host> [port] reads the peer certificate and negotiated protocol/cipher and flags weak config — expired, not-yet-valid, self-signed, sub-2048-bit key, hostname/SAN mismatch, soon-to-expire — plus deprecated TLS 1.0/1.1 that still handshake. testssl.sh-class, read-only.
  • add Service-version CVE matching. nullock vulnscan <host> banner-grabs network services (SSH/FTP/SMTP/HTTP/…) and flags vulnerable versions against a curated CVE table — vsftpd 2.3.4 backdoor, OpenSSH regreSSHion, Apache 2.4.49/.50 path traversal, ProFTPd mod_copy, Exim RCE, IIS WebDAV, SambaCry — each with CVE id, CVSS, and fix version. The nmap-vulners capability, wired to the port scanner. Read-only: it identifies vulnerable versions, it does not exploit them.
  • add HTTP request smuggling. nullock smuggle <url> times CL.TE and TE.CL desync probes and flags the variant whose response is reproducibly delayed — Burp Pro's flagship, free. A valid-but-ambiguous control request rules out servers that merely tarpit ambiguous input, and the probes carry Connection: close so they can't smuggle into a real user's request.
v3.4.0 Jun 11, 2026

Active testing & API-security release. Five scanners that find real, exploitable bugs the free tools can't — each shipped with adversarial code review and a regression test, each with built-in false-positive guards.

  • add OAST auto-correlation + active OOB blast + DNS sink. Out-of-band callbacks become confirmed findings automatically; nullock oast blast sprays SSRF/XXE/Log4Shell, and a DNS sink catches the name-only callbacks an HTTP sink can't.
  • add Hidden parameter mining. Response-diffs a candidate wordlist to find undocumented params (reflected or status-flipping), with a control probe that suppresses targets reacting to any param.
  • add IDOR / BOLA auto-detection (OWASP API #1). Replays neighboring object ids under your session and flags distinct accessible objects — robust to per-request tokens via calibrated length comparison.
  • add Mass-assignment scanner (OWASP API #6). Injects privileged fields (role, is_admin, balance…) into write requests and reports the ones the server binds back.
  • add Active CORS exploitability. Fires an Origin battery and proves credentialed cross-origin reads — not just a passive header note.
v3.3.0 Jun 9, 2026

The "above the paid tools" release. Five capabilities that commercial scanners gate behind add-ons or don't ship at all — now in the free core, each with regression coverage.

  • add CVE correlation. Fingerprinted frameworks (WordPress, Drupal, Magento, Spring, Next.js, …) are matched against a curated CVE table; every hit becomes a finding tagged with CVE id, CVSS, and fix version.
  • add GraphQL attack probes. One call fires five probes — introspection, field-suggestion leak, alias amplification, depth bypass, batched-query bypass — with false-positive guards. nullock graphql <url>.
  • add DOM-XSS taint analysis. A proxy-side extension does one-hop dataflow on every served script, connecting sources (location, referrer, postMessage, storage) to sinks (innerHTML, eval, document.write) and attributing the true origin.
  • add Repeater chains. Define a sequence of requests, extract values (JSON path / header / cookie / regex / status) from each response, and thread them as {{var}} into later steps. nullock chain <file>.
  • add JWT attack toolkit. Decode + weakness analysis (alg:none, missing/expired exp, kid injection, privilege claims), weak-secret brute-force, and forging (alg:none + HS256 re-sign). Passive auto-analysis on captured tokens too.
  • add OAST auto-correlation. Callbacks no longer just sit in a log — a registered token arriving out-of-band auto-emits a confirmed finding linked to the originating request. The half of Collaborator worth paying for, self-hosted and free.
  • add Active OOB blast. nullock oast blast <url> sprays SSRF (a battery of param names), blind XXE, and Log4Shell payloads; each callback confirms tagged by attack class.
  • add DNS OAST sink. Catches the OOB classes the HTTP sink can't — Log4Shell JNDI resolution, blind-SQLi DNS exfil, DNS-only SSRF — feeding the same correlator. --oast-host / --dns-port for real-target deploys.
  • add Every finding now carries CWE, OWASP Top-10 2021, CVSS v3.1, and a one-line fix — across all of the above.
v3.2.0 Jun 2, 2026
  • add Repeater now diffs two responses side by side, with byte-level highlighting.
  • add nullock export --json streams scoped history without loading it all into memory.
  • fix History scroll no longer jumps when new rows arrive while a row is selected.
  • perf SQLite write batching cut capture overhead by ~40% at 200k rows.
v3.1.4 May 18, 2026
  • fix CA install on Linux now writes to /usr/local/share/ca-certificates correctly under Wayland.
  • fix Match & replace rules with empty bodies no longer drop the connection.
  • add nullock vacuum to compact history files after big sessions.
v3.1.0 Apr 29, 2026
  • add JavaScript extensions — hook the request/response pipeline, drop a .js in the ext dir.
  • change Scope syntax now accepts glob patterns, e.g. *.app.local.
  • fix Memory leak when streaming large (>50 MB) responses.
v3.0.0 Mar 11, 2026

Rewrote the capture core in C++ / Qt. The desktop app is now a thin front end over the same binary you can script.

  • add Native desktop app for macOS, Linux, Windows.
  • add SQLite-backed history — 200k+ rows on a 16 GB box.
  • change Config moved to ~/.nullock/. A migration runs on first launch.
  • remove Dropped the legacy Electron build. It was slow and we don't miss it.