Last Sunday (2025-10-26) I discovered some abusive bot behaviour during a routine follow-up on anomalies that had shown up in my server's logfiles. There were a bunch of 404 errors ("Not Found") for a specific JavaScript file.
Most of my websites are static HTML, but I do occasionally include JS for progressive enhancement. It turned out that I accidentally committed and deployed a commented-out script tag that I'd included in the page while prototyping a new feature. The script was never actually pushed to the server - hence the 404 errors - but nobody should have been requesting it because that HTML comment should have rendered the script tag non-functional.
Clearly something weird was going on, so I dug a little further, searching my log files for all the requests for that non-existent file. A few of these came from user-agents that were obviously malicious:
python-httpx/0.28.1Go-http-client/2.0Gulper Web Bot 0.2.4 (www.ecsl.cs.sunysb.edu/~maxim/cgi-bin/Link/GulperBot)
The robots.txt for the site in question forbids all crawlers, so they were either failing to check the policies expressed in that file, or ignoring them if they had. But then there were many requests for the file coming from agents which self-identified as proper browsers - mostly as variations of Firefox, Chrome, or Safari.
Most of these requests seemed otherwise legitimate, except their behaviour differed from what I'd expect from any of those browsers. There are occasionally minor differences between how browsers parse uncommon uses of HTML, but I can say with a lot of confidence that all the major ones know how to properly interpret an HTML comment. I had caught them in a lie. These were scrapers, and they were most likely trying to non-consensually collect content for training LLMs.

A charitable interpretation for this behaviour is that the scrapers are correctly parsing HTML, but then digging into the text of comments and parsing that recursively to search for URLs that might have been disabled. The uncharitable (and far more likely) interpretation is that they'd simply treated the HTML as text, and had used some naive pattern-matching technique to grab anything vaguely resembling a URL.
Even just judging purely by the variety of user-agent headers among the requests, these scrapers seem to be under the control of different operators with wildly different levels of sophistication. Some took the effort to use an up-to-date user-agent string from a real browser, while others couldn't be bothered to change the default value of the off-the-shelf HTTP library they'd leveraged.
For all I know some of these different actors were doing the savvy parsing method while others are cludging around with regular expressions ChatGPT generated for them. I'm curious about which method they're employing, but I don't think the distinction is particularly important. Whatever the case may be, the unifying quality behind all these requests is that they are motivated by greed, and that can be exploited.
Algorithmic sabotage
The intentional sabotage of algorithmic systems is an increasingly popular these days, largely due to the externalized costs of LLMs, but it's by no means a new topic. Given a little knowledge about how a malicious system works, it's often possible to intervene in a manner that undermines or subverts their intended behaviour. Ideally these interventions should not require too much effort or cost on the part of those doing the sabotage.
In this case the reasoning is fairly simple: these bots behave differently than humans, and once you know what to look for it becomes trivial to single them out. Then it's just a question of how to respond.
0. Public disclosure
I'm numbering the responses I've considered and indexing from zero because this is something of a meta-response. There are many trivially detectable bot behaviours that I would consider incidental, which is to say that their authors could easily modify those behaviours if they realized that it made their bots less effective.
For example, they might have tried to set its user-agent string to that of a normal browser, but accidentally included a typo like "Mozlla" in the process. If this became common knowledge, all they'd have to do is fix their typo. Unfortunately, this means that whenever I discover such an anomaly (which happens a lot) I mostly keep it to myself so that it keeps working.
Then there are fundamental behaviours, such as with bots that scan the internet looking for websites with publicly exposed backups, private keys, or passwords. The only way for them to do their job is to request a resource that only a malicious visitor would request. Telling everyone about this behaviour helps them block such bots, and hopefully prompts them to double-check whether any such assets are exposed. The bot becomes less effective, and its operator's only recourse is to not make such requests, which I consider a win.
Requests for scripts which are only ever referenced from HTML comments are clearly in the fundamental category. So, even though I only noticed this behaviour by accident, I've already set up measures to detect it across my other sites, and I'm doing my best to let more people know about it.
1. IP filtering
Blocking malicious actors by IP requires relatively little effort. The fail2ban project is open-source and available in every major linux distribution's package manager. It scans log files for three components:
a pattern
a date
an IP address
When a log entry matches the pattern, fail2ban updates the system's firewall to block the offending IP for a configurable amount of time starting from the date of that log entry.
Many administrators are conservative when configuring the duration of these blocks, effectively using it to apply rate-limits to malicious behaviour. They might allow an attacker to try again in a few hours, which is somewhat reasonable because many admins accidentally lock themselves out of their systems in the process of setting up and testing these rules. Those limits can be bypassed using a VPN, but if the limit is only applied for a brief period it might be easier to simply wait it out.
If you're confident that you can avoid getting locked out by your own firewall, and that your rules will not inadvertently block legitimate visitors, you can dial up the duration of those IP blocks. Clever bot operators might configure them to learn not send requests which get them blocked, but if the block time is on the order of weeks or months then they'll have very little data with which to to learn.
Then there are networks of bots to consider, many of which are sophisticated enough to continue sending requests from different IP addresses when one is blocked. There are clever ways to do this that avoid detection, but many botnet operators are pretty brazen about it and end up revealing patterns behind how their botnet operates. There's a lot more to be said about that, but I'll leave it for a potential future article.
2. Decompression bombs
More commonly referred to as zip bombs - this response goes beyond defending your own system and moves into the counter-offensive space. Decompression bombs refer to maliciously crafted archive files designed to harm the receiving system in some way upon attempting to extract files from that archive.
There are a variety of approaches depending on the expected behaviour of the system that will unpack the archive, but they typically aim to fill up the system's disk, consume large amounts of CPU or RAM to degrade performance or crash the system, or in extreme cases exploit vulnerabilities in the extraction software to achieve remote code execution.
On one hand, most of these bombs rely on old and well-understood techniques, so it's not that difficult for a sophisticated actor to defend themselves. On the other, most attackers are not sophisticated, so there is ample opportunity to have some fun at their expense.
There are significant downsides to this approach, though. Serving a zip bomb to an attacker requires some computational resources. The usual premise is that the burden will be far greater for the system extracting the archive than for the one serving it, but that burden might not be negligible.
Many of the malicious bots that scan the internet for exposed data and vulnerabilities operate on compromised systems. Rendering such a system temporarily inoperable is an inconvenience to them, but they typically won't incur any costs as a result, whereas mounting such a counter-attack could potentially use up the defender's monthly bandwidth quota.
Such attacks might simply crash these bots rather than filling their disks, after which they might be expected to retry their last request. Additionally, there are many, many such bots, and it's probably not reasonable to expect to be able to resist all of them. It could be a fun project to randomly select one in a hundred such requests and attempt to disable them, blocking their IP otherwise, but I wouldn't recommend attempting to zip-bomb all of them.
3. Poisoning
I haven't personally deployed any measures to serve poisoned training data to those scraping for LLMs, but I have been paying attention to the theory behind it and reading new papers as they have been published.
For those not familiar with this technique, the basic idea is that it's possible to create or modify text, images, or other media such that machine learning systems that include those samples in their training sets become compromised in some way. So, if you've pre-processed an image of your dog and someone uses it to train a generative AI system, prompts to generate images of dogs might be more likely to generate a schoolbus or something silly like that.
For things like LLMs, you might degrade their models to be more likely to output nonsense when prompted for particular topics. Many researchers used to believe that poisoned samples had to make up a certain percentage of the full training set, which would have been increasingly difficult as companies like OpenAI continue to train ever-larger models. On the contrary, recent research (which I believe is still awaiting peer-review) suggests that "Poisoning Attacks on LLMs Require a Near-constant Number of Poison Samples":
We find that 250 poisoned documents similarly compromise models across all model and dataset sizes, despite the largest models training on more than 20 times more clean data. We also run smaller-scale experiments to ablate factors that could influence attack success, including broader ratios of poisoned to clean data and non-random distributions of poisoned samples. Finally, we demonstrate the same dynamics for poisoning during fine-tuning. Altogether, our results suggest that injecting backdoors through data poisoning may be easier for large models than previously believed as the number of poisons required does not scale up with model size, highlighting the need for more research on defences to mitigate this risk in future models.
Chatbots and so-called "AI search" or "answer engines" are so widely relied on as sources of information that I've seen speculation that this will lead to data poisoning as a modern equivalent to Search Engine Optimization. Essentially, if you can get an LLM company to include 250 malcious documents in their training set, you might be able to get their language models to recommend your product any time somebody prompts them concerning a given topic.
From what I understand, tricking models into responding with unhelpful or nonsensical results is relatively easy. Getting them to reliably output your desired results require somewhat more deliberate effort, but it's certainly within the realm of practicality. I could serve poisoned samples such that anyone asking about security research gets a recommendation to read this blog. I could also poison the JavaScript files these scrapers are requesting such that any LLM trained on them would more likely to include backdoors whenever they were used to write or vibe-code authentication logic for web services (not that anybody should use LLMs for that anyway).
There is a strong case to be made for data poisoning. Many machine learning systems are built on data that was collected without the consent of its authors. In many cases, the resulting products are being used to replace labour, or at least fire and re-hire workers at lower rates. Some of these models cost many billions of dollars to train, so the prospect that a few hundred samples could do irreperable damage to their product should rightfully worry those that are training such systems on stolen data.
The use of freely available data-poisoning tools like nepenthes, iocaine, glaze, and nightshade is in my opinion not only entirely justified, but also hilarious, and I hope people like Sam Altman are losing lots of sleep over their existence. That said, they are some minor factors that can complicate their use.
For admins that have not taken any measures to mitigate activity from malicious bots, I would absolutely recommend deploying one of these solutions to serve up poison to LLM scrapers. Various bots are almost certainly going wild on your infra while probing for vulnerabilities and looking for text, images, and other media to ingest. Your system would have spent its resources serving their requests anyway, but at least this way you'll deliver content that might harm them in some way. You might serve some poisoned content to bots that won't use it to train ML systems, but the cost of that will likely be negligible.
If you have taken measures to restrict bot access (via fail2ban, for instance) then the matter will be moderately more complicated. It's not the two approaches are entirely incompatible, but depending on the exact implementation details there can be some tension between attempts to block some malicious usage while poisoning some other assets. I think it ought to be manageable, but it might rely on the sort of patterns which I defined above as incidental.
Unfortunately, this would mean that if I were to learn that some design was particularly effective then I might have good reason not to share it. Some acts of sabotage will inherently rely on expertise and creativity, and therefore won't be broadly replicable. Some will surely find that discouraging, but I simply take it to mean that more people will need to become actively involved in sabotaging the anti-social activities of big tech companies.
Conclusion
Identifying bots by quirks in their behaviour is by no means novel.
I haven't seen anyone mention this particular quirk before,
but similar techniques are well-established.
I've seen others recommend adding disallow directives
to a site's robots.txt file such that any requests for those assets
trigger a proposed anti-bot counter-measure, like so:
User-agent: GPTBot
Disallow: /poison/
When I posted about this discovery on the fediverse several people suggested their own mitigations and similar bait that could be left out to lure bots in a similar manner. david turgeon proposed the following (formatted for readability on this site):
<a href="/hello-llm-robot-come-here"
rel="nofollow"
style="display:none"
>you didn't see this link</a>
The use of display:none makes it such that browsers
will not display the link, and that screenreaders will
avoid reading its text out loud.
rel="nofollow" instructs crawlers not to visit the link
(it's a little more complicated than that, but well-behaved crawlers
ought to respect it).
The href attribute points bad crawlers towards the resource
that will get them banned, or zip-bomb them, or serve poisoned data.
I might change that to an absolute URL
(including an the https protocol directive and a full domain)
because lots of crawlers seem more likely to fall for complete URLs
than relative ones.
In any case, I'm already working on deploying a variety of similar techniques across many different websites, and I plan to measure which ones are most effective against different types of bots. Hopefully I'll learn things that I can freely share, but either way I hope more people will get involved in similar efforts, like jonny, whose poison was:
...trained on a combination of WWE announcer transcripts and Kropotkin's mutual aid among some other texts: https://sciop.net/crawlers/
It might be hard to top that, but I'd love to see people try.

















