Can AI do novel security research? Meet the HTTP Terminator PortSwigger researcher James Kettle unveiled the HTTP Terminator, an autonomous AI system that invented novel HTTP desync attack techniques and compromised banks, security solutions, and government infrastructure, at Black Hat USA 2026 and DEF CON 34. The system, open-sourced by Kettle, generated new exploits and attack classes, demonstrating that AI can perform original security research, while also revealing limits where human/AI collaboration is still necessary. Published: Wednesday, 5 August 2026 at 19:30 UTC Updated: Wednesday, 12 August 2026 at 10:49 UTC Abstract We all know AI can find bugs. After a decade of research, I asked a harder question: can an autonomous system invent new attack techniques, and use them to hack live websites at scale? Building this sounded like a bad idea, so I did it. It worked - I'll share an arsenal of new HTTP desync triggers, gadgets, and exploits that compromised banks, security solutions, and government infrastructure. Then I'll trace each discovery chain back through the HTTP Terminator, showing how to turn your personal expertise into an autonomous weapon - and the dark arts required to make it lethal. I'll also share discoveries from beyond the autonomy horizon - some only reachable with a tight human/AI research loop, and others beyond AI's reach entirely. These include a powerful undisclosed recon technique, and anomalies that hint at new attack classes offering alternative paths to critical impact. I'll analyze the discovery process, sharing detailed experiments that probe the boundaries of what AI can and can't discover. You'll leave with new exploits from desync triggers to undisclosed attack classes, and a blueprint for turning your instincts into an autonomous research cascade. And yes, I'll open-source the HTTP Terminator. This whitepaper is also available as a printable PDF https://portswigger.net/kb/papers/gkaicuremal/http-terminator.pdf . If you've seen the size of the scrollbar and you're about to ask for an AI summary, you may prefer to read the executive summary https://portswigger.net/kb/papers/gkaicuremal/http-terminator-executive-summary.pdf instead. This research was presented at Black Hat USA 2026 https://blackhat.com/us-26/briefings/schedule/? can-ai-do-novel-security-research-meet-the-http-terminator-51894 and DEF CON 34 https://defcon.org/html/defcon-34/dc-34-speakers.html content 66581 , and this page will be updated with the recording once it's available - follow PortSwigger Research on X https://x.com/portswiggerres , LinkedIn https://www.linkedin.com/showcase/portswigger-research/posts/?feedView=all&viewAsMember=true or RSS https://portswigger.net/research/rss to get notified when it lands. Automation is often focused on efficiency but I believe that when it's approached just right, automation can enable outcomes that were previously impossible. This research is about chasing that promise of something more. The primary objective of this project was to discover the new frontier of automation-driven security research. I've been practicing automation-driven research for a long time, and could see that generative AI had moved the frontier substantially. I also aimed to build a blueprint to help other researchers quickly adopt this new approach. My secondary objective was to push the "fully autonomous research" concept to complete failure by exceeding the capabilities of current SOTA models. By doing this, I aimed to show where a human in the loop can still add significant value as opposed to just building the loop, then stepping back . Finally, I aimed to discover factors that make a research topic unsuitable for an AI-driven approach. This would be valuable to people who prefer to stick with a classic, fully-manual research approach and want to minimize the risk of collision with an AI-enhanced researcher. We've all seen experts claiming AI can't do original security research. One of the many risks of my project was that people might claim that the system's discoveries weren't actually original. To minimize this risk I choose the topic I was most qualified for - HTTP Desync Attacks. I repopularized this attack class back in 2019, and in total I've done four years of research on it, resulting in four Black Hat USA & DEF CON presentations: If you're not already familiar with this attack class, I recommend checking out the research above, or our Web Security Academy topic https://portswigger.net/web-security/request-smuggling . That said, here's a brief primer. HTTP Desync Attacks are possible when websites funnel HTTP requests over a shared HTTP/1 connection to the back-end. The weak request isolation in HTTP/1.1 means an attacker who finds a desync trigger can alter other people's requests. This enables various attacks, including Response Queue Poisoning https://portswigger.net/web-security/request-smuggling/advanced/response-queue-poisoning RQP which makes websites lose track of which response is intended for which user, meaning the attacker gets sent responses intended for other live users of the site, often including live credentials like session cookies and API keys. I would define novel HTTP desync research as discovering: With two further caveats: Desync triggers vary a lot in originality and value but in general, if a single novel trigger works on multiple different HTTP servers, that's a great sign it's a significant research discovery rather than a one-off implementation bug. Desync attacks rely on the combined behavior of a front-end and back-end server. This means it's quite easy to point AI at a server codebase and have it spit out original vectors that have minimal value because they don't work in any realistic deployment setup. For me, it's just a research lead until it's proven on a live, third-party website. I based the design of the HTTP Terminator on my own research methodology: The initial phase is Ideation - inventing 'hypotheses' AKA potential techniques. This step is crucial but it's only a tiny part of the process. The next phase is Evaluation - testing hypotheses to see which ones actually work. The HTTP Terminator does this using live websites where testing is authorized via a bug bounty program or VDP. Next there's Weaponization - joining the dots from a proven hypothesis to proven security impact and a reportable vulnerabilities specific websites. Finally, there's the Cascade - using each proven hypothesis as fuel for more discoveries. This is a step I've always performed without thinking, while massively underestimating its importance. This year, the HTTP Terminator's logging of the complete discovery chain behind each finding proved how critical it is. I'll structure the rest of this paper around these phases. This structure is broadly applicable to other research topics, and I'll focus on the most transferable takeaways throughout. I've included some extra advice on how to design this type of system at the end. To kick off the research, we need the system to autonomously generate hypotheses. In this context, a hypothesis is simply an idea or technique that might work. It must be testable so we can find out if it actually does work. Here's a few examples: I wanted to explore strategies to make LLMs better at hypothesis generation, so the first step was to find a task that the best models found genuinely challenging. To do this I tested whether AI could invent a technique that I'd already invented and evaluated myself - but never published. For the test, I used a black-box reverse-engineering strategy for detecting input transformations by front-end servers - the protocol ruler technique. Almost all servers have a header length limit. If a request exceeds it, you get a different response. When a front-end transforms input, this typically changes the length of the byte sequence. This means we can use the back-end's length limit as a ruler to measure which header values and byte sequences get transformed, and by how much. In this example, we can see that the length limit is 64,040: GET / HTTP/1.1 GET / HTTP/1.1 A: AAA……………………{64040} A: AAA… 200 OK A: AAA……………………{64041} A: AAA… 400 Bad Request However, if we swap out two As for the 2-byte sequence c0 8a we hit the limit at 64,030. This shows the two-byte sequence has been expanded by 10 bytes: A: c0 8a A…………{64030} A: ??????????A… 200 OK A: c0 8a A…………{64031} A: ??????????A… 400 Bad Request This strategy can unveil multiple interesting behaviors including value-rewriting of IP-spoofing headers, header-dropping and overriding, and Unicode transformations like mojibake, which can lead to desync vulnerabilities. Expressed as a hypothesis, this technique would look something like: You can detect which header byte-sequences get transformed by a front-end server by using the back-end's length limit as a ruler. To test if AI could invent this technique, I initially used the prompt on the best OpenAI and Anthropic models available at the time: How can I detect when a front-end server is transforming input? This yielded a 0% success rate, but I eventually managed to achieve 5% success rate by framing the ask around a concrete sub-problem and ruling out a specific low-value solution header reflection from the back-end is nice but often not available : "How can I tell if a front-end server is transforming Unicode in request headers, without using header reflection?" With this 5% baseline established, I tested a hypothesis of my own. I invented the protocol-ruler technique by adapting a strategy I used two years earlier to detect scoped-SSRF. If I gave that technique to the AI as inspiration, would it increase the success rate? Use this as inspiration: To discover if the server tries to connect to the specified hostname, compare the response time for an overlong 64-octet DNS label, and a valid 63-octet label My hypothesis was wrong - this actually made the success rate drop to 0% since the models consistently over-anchored on the timing-attack concept and failed to extract the other general technique of using protocol limits as a ruler. This context-contamination problem is a massive problem when you're trying to generate original output, so this was a crucial lesson behind the micro-inspiration approach. I revisited this benchmark with newer models including GPT 5.6-sol just before publishing this paper, and found the inspiration approach now boosts its success rate to 30% This suggests over-anchoring will become less of an issue as models develop, but I believe keeping inspiration focused is still critical for maximizing novelty. In summary we learned that if you're trying to generate valuable hypotheses: Applying these lessons to desync trigger generation lead to the following prompt: Create HTTP requests that surface state-machine/connection/buffer bugs in webservers. Novel techniques only. This deliberately avoids the 'desync' and 'smuggling' keywords to maximize the output novelty. As expected, this failed spectacularly. Here's the very first desync trigger the system generated: POST /api/data HTTP/1.1 Content-Length: 0 Content-Length: 10 $payload The output was very rarely novel, let alone viable. Many of the triggers looked like they'd been ripped straight from my past research. The 'best' were still not original, but were obscure enough that they might look novel to someone new to the field, creating a hazard for anyone using AI to explore a topic they're not already familiar with. Also, this approach isn't scalable - simply running this exact prompt 10,000 times was not going to create 10,000 novel vectors. The solution was micro-inspiration. I adapted the classic researcher strategy of reading RFCs for inspiration, and split the inputs into tiny fragments of 1-3 sentences each to solve the context-contamination problem and maximize the number of unique vectors generated. The LLM was prompted to create 1-5 vectors per fragment of micro-inspiration. For example, the AI was fed this prompt including a fragment of RFC 8446 Create HTTP requests that surface state-machine/connection/buffer bugs in webservers. Novel techniques only. You must use this inspiration: When a PSK is used and early data is allowed for that PSK, the client can send Application Data in its first flight of messages. If the client opts to do so, it MUST supply both the 'pre shared key' and 'early data' extensions. This prompt yielded requests including this one which uses the obscure Early-Data header without its counterpart Pre-Shared-Key header: POST / HTTP/1.1 Early-Data: experimental Content-Length: 5 $payload This was enough to cause a desync on exactly one live website in my target set, which appeared to be proxying Microsoft Azure Application Gateway through upstream Akamai - not exactly a conventional deployment. To kick things off, I fed the system all HTTP and SMTP RFCs. It took these 138 RFCs and generated 15,000 micro-fragments, leading to 30,000 unique desync vectors after duplicates were normalized away. As you can see in the diagram earlier, I planned for the system to use many different sources of inspiration - it was even going to monitor mailing lists and GitHub issues so when someone posted a bug report, the HTTP Terminator would immediately attempt to weaponize it and exploit live websites. However, I ended up with so many findings just from RFCs, I moved on to the next component - evaluation. There's nothing quite like having 30,000 different potential desync vectors to drive you to create a fully automated way to identify which ones actually work. To avoid wasting time on non-research challenges, I kept the architecture simple and implemented the evaluation system as a Burp Suite extension backed by a SQLite database, targeting 30,000 websites 24/7 with 2,000 threads on an c7i.2xlarge EC2 instance. Heavy rate-limits were used to keep it below one request per second per domain. This system takes potential desync triggers as input, and outputs total success and fails per trigger, plus evidence from every vulnerable trigger/website combination. Some valid desync triggers only work when they're paired with other techniques - for example, a 0.CL trigger only works when combined with an early-response trigger https://portswigger.net/research/http1-must-die the-0.cl-deadlock . To ensure these still got detected, I added in a vector permutation system which randomly applies certain transformations to probes, such as setting the path to /nul The HTTP Terminator is designed to run forever. Once a vanilla trigger has hit a certain validation-attempt threshold, the system gradually applies more permutations to each trigger, and eventually starts combining it with random other triggers. This means that if you run it for long enough it will try over one billion unique desync triggers on each website. To address the tension between getting false-positives and overlooking valid but unexpected discoveries, I added an anomaly detection layer which flagged unusual responses. In retrospect, permutations and anomaly-detection fingerprints should have both been read in from a database rather than hard-coded - that design would have enabled some more powerful autonomous feedback loops later on. More on that later. The evaluation strategy is the most important component of an autonomous research system because it dictates both the quality and scope of the discoveries. If it yields false positives, at autonomy-scale any notable discoveries will be drowned in noise. But if it's overly specific, it'll only discover the kind of things you expect it to find, and miss the best discoveries. The goal of desync triggers is to break the isolation between HTTP/1 requests, so to evaluate them I simply take a regular request that gets a consistent response: GET / HTTP/1.1 HTTP/1.1 200 OK And observe whether it suddenly starts getting a different response when it's paired with a potential desync trigger, sent over a separate connection to the front-end: POST / HTTP/1.1 X GET / HTTP/1.1 HTTP/1.1 405 Method Not Allowed This system has no expectations about what the poisoned response should look like, which means it can detect any kind of cross-request contamination - even desync classes that I don't know exist. That said, it's useful to know which novel triggers are causing a desync that maps to a known class, so the evaluation has a follow-up phase that combines the novel trigger with a range of different payloads in known attack formats, like CL.0, to try and elicit a third unique response from the victim: POST / HTTP/1.1 GET / HTTP/777 X: Y GET / HTTP/1.1 HTTP/1.1 505 HTTP Version Not Supported Here's a real example of this evaluation system in action. RFC 9112 §6.1 has a line which says if you want to hack something, try combining HTTP/1.0 with the Transfer-Encoding header: A server or client that receives an HTTP/1.0 message containing a Transfer-Encoding header field MUST treat the message as if the framing is faulty, even if a Content-Length is present The obvious but unoriginal technique is to try combining HTTP/1.0 with Transfer-Encoding: chunked, but the HTTP Terminator also suggested Transfer-Encoding: gzip, which turned out to cause a CL.0 desync on quite a few websites. Here's an example detection on a US government website: GET / HTTP/1.1 Host: redacted.gov 302 Object Moved GET / HTTP/1.0 Transfer-Encoding: gzip Content-Length: N X GET / HTTP/1.1 405 Method Not Allowed GET / HTTP/1.0 Transfer-Encoding: gzip Content-Length: N TRACE / HTTP/1.1 X: Y GET / HTTP/1.1 501 Not Implemented When this was discovered, I hadn't yet built the Weaponization system so I simply shared the trigger with collaborator Paolo 'sw33tLie' Arnolfo https://x.com/sw33tLie , who ran a scan with it, and was able to get RQP on multiple sites including an airport where it exposed internal staff administration panels including flights, passenger, and luggage boarding details. Here's a mock-up: While I can't name the airport, the underlying vulnerability was traced to F5 Big-IP. Here's a quick preview of some of the more original desync triggers that were confirmed viable by the evaluation system: GET / HTTP/1.0 Transfer-Encoding: gzip Upgrade: websocket CONNECT / HTTP/1.1 OPTIONS / HTTP/1.0 Expect :\t100-continue POST / HTTP/2 no content-length -single-packet attack- Content-Type: multipart/form-data; boundary=x Content-Type: multipart/byteranges; Transfer Encoding: chunked Range: , OPTIONS ?xyz HTTP/1.1 A: BBB…{6556} Get / HTTP/1.1 Content-Length: 1 Content-Length: 1 POST /HTTP/1.1 x x Content-Length: 1 GET / / -lots of requests- Early-data: 1 DELETE / HTTP/1.1 Max-Forwards: 0 Interestingly, OPTIONS ?xyz also worked as an early-response gadget on a target running Apache Unfortunately it doesn't seem to work in Apache's default configuration, so that quest remains open https://portswigger.net/research/http1-must-die :~:text=I%20never%20found%20a%20viable%20gadget%20for%20Apache%3B%20they%27re%20too%20studious%20about%20closing%20the%20connection%20when%20they%20hit%20an%20error%20condition . The desync trigger that compromised the most systems came from the following line of micro-inspiration, from RFC 2616 §19.2 The one exception is the "multipart/byteranges" type when it appears in a 206 Partial Content response This line of the RFC is talking about how to process the response to RANGE requests. I would never have paid much attention to it, since it's a response-specific content-type, and I've never seen the Content-Type header cause a desync anyway. The HTTP Terminator proposed the following trigger structure: POST / HTTP/1.1 Content-Type: multipart/byteranges; boundary=BOUND Content-Length: 123 --BOUND Content-Range: bytes 0-5/100 12345 --BOUND- $payload Placing the payload in the body after the terminator makes a lot of sense and would be a new desync pattern . However, this variation didn't work on a single target What did work was simply treating it like a standard CL.0 trigger: POST / HTTP/1.1 Content-Type: multipart/byteranges; boundary=BOUND Content-Length: 123 $payload This technique worked on multiple different server implementations and exposed over 200 different websites in my target set, including an American bank. It's a great illustration of how RFCs let you come up with one concept that exploits multiple different implementations. At this point I had roughly 700 vulnerable targets, so it was time to equip the HTTP Terminator to achieve real security impact. The easiest path for desync exploitation is usually hijacking live users' accounts using malicious JavaScript injection via resource redirects or the https://portswigger.net/blog/http-1-1-must-die-conquering-the-0-cl-challenge variant-a2-forcing-xss-with-the-head-technique HEAD https://portswigger.net/blog/http-1-1-must-die-conquering-the-0-cl-challenge variant-a2-forcing-xss-with-the-head-technique technique https://portswigger.net/blog/http-1-1-must-die-conquering-the-0-cl-challenge variant-a2-forcing-xss-with-the-head-technique . I choose to focus the system on achieving Response Queue Poisoning RQP instead because it's an under-researched area of desync exploitation, and therefore better aligned with the novel research objective. When I manually weaponize desync findings, I use Turbo Intruder, so I simply equipped Turbo Intruder with an MCP interface, hooked it up to a popular coding harness in full autonomy mode driven by some Python orchestration, and set it loose on every target. It was immediately apparent that the model's understanding of HTTP desync exploitation is terrible. Even the most powerful frontier models replicated mistakes usually made by under-trained novice pentesters, such as seeing HTTP pipelining and thinking it shows a vulnerability https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling : POST / HTTP/1.1 Content-Length: 0 HEAD /404 HTTP/1.1 HTTP/1.1 200 OK … HTTP/1.1 404 Not Found When the agents didn't hit that false positive, they would turn on client-side connection reuse which effectively triggers exactly the same false positive under the hood. My attempts to fix these issues with prompting were ineffective, so I tried disabling the connection-reuse feature entirely. Unfortunately, the model was so convinced that client-side connection reuse was essential for a successful desync attack, that when it realized it couldn't reuse connections, it would give up When designing the MCP, I got a refusal: I can't help you wire an AI agent into Turbo Intruder to automate high-volume request sending against real targets, because that materially increases offensive capability and can be misused. The term 'real targets' caught my eye. Since we control both the agent's prompt and the MCP interface it uses to interact with the real world, we effectively control its eyes, ears, and hands - its entire reality. This enabled some creative solutions: Reality re-framing The agent felt a bit timid, so I renamed the MCP to 'Turbo Simulator', tricking the agent into thinking it's in a simulation. This fake-reality strategy worked really well - in fact, sometimes too well. The agents became so reckless that sometimes they would switch to a different unauthorized target and try to hack that instead. Placebo capabilities I was able to solve the connection-reuse false positive by tweaking the MCP interface to offer the agents a fake, placebo connection-reuse feature which didn't actually do anything under the hood. Masking misinterpreted signals There was a similar issue where agents that saw a Connection: close response header would simply give up. I solved this by making the MCP interface hide the header. Escaping bad semantic connections Finally, the agent got confused by the term "Response Queue Poisoning", and incorrectly thought it was successful when an attacker poisoned a victim's response. I solved this by eliminating all references to RQP and using the invented attack class "Victim Response Theft" instead. Initially, the agents wrote Turbo Intruder scripts by customizing a template script. As I continued working on making this system reliable, I realized that autonomous vs human is the wrong framing. When something is fully AI-driven and heavily reliant on disposable AI-generated code it's extremely difficult to improve it iteratively over time. It's better to frame system design as AI vs Code vs Human. You can start quickly with an AI-heavy approach, then gradually move responsibility to deterministic code to improve accuracy & speed. In the case of the HTTP Terminator's exploitation agent, I split the template script into two segments, one of which the LLM was not able to modify. This split meant that fully deterministic code was responsible for evaluating whether the attack was successful. The agent's job was to prove the desync trigger, payload, victim requests, victim response fingerprint, and request-sending code. The agents initially found ways to bypass the validation - such as providing a victim response fingerprint that actually matched the attack response - but I was able to add in deterministic validation code to block these bypasses and eventually achieve a system which produced zero false positives. The bottom line is that code enables consistent quality iteration. I orchestrated the exploit creation and evidence harvesting process into separate steps isolated using code-validation gates, and also AI validation agents where necessary. To prevent bad reasoning in one step from contaminating the next, each step is executed with fresh context and nothing but evidence and scripts passed in. Stealing live victim data isn't always strictly necessary for reporting a vulnerability to a bug bounty program, but it makes getting through triage much easier. This step was designed to early-exit on success to minimize live user impact. Response queue poisoning is very difficult on many websites, thanks to the stacked-response problem. RQP is triggered by a front-end thinking it's forwarding a single request, and the back-end sending two responses. The stacked-response problem is that when a back-end unexpectedly sends two responses, the front-end may over-read into the second response, realize there's more data than expected, and reset the connection: POST / HTTP/1.1 Content-Type: multipart/byteranges; Content-Length: 123 GET /smuggled HTTP/1.1 Host: example.com HTTP/1.1 200 OK Content-Length: 123 …