
Brainstorms for AI Poisoning Techniques
Exploring extensions to AI poisoning programs such as Nepenthes, Iocaine, and Quixiotic, including generating other kinds of media and mixing in genuine content in order to make the mazes appealing both to human users as well as to the bots that follow them.
By: TheHans255
10/5/2025
I've been reading a lot about various defenses against AI scraper bots. I trust that if you're the kind of person who reads my website, the problem needs no introduction - essentially, thousands of startups and established companies around the world are trying to invest in AI and LLMs, all of them want their own dataset (since that's the only thing remotely of value), and hence each of those companies run thousands of bots every day in an attempt to scrape the entirety of the publicly available Internet, which all too often brings down smallweb and Indie web sites that were never designed to handle a load of visitors who are only there to desperately recoup their venture capital funds.
I still think that the most promising defense, while admittedly one of the most expensive for the server operator, is the technique of AI poisoning. Other methods, such as the proof-of-work solution provided by Anubis or the simpler technique of blocking problematic IP blocks, mainly work by preventing bot operators from finding your content and visiting your site, but AI poisoning instead works by giving the AI bots something to keep themselves busy - content generated via a Markov chain that statistically looks like training data they want for their models, but is actually meaningless and will result in worsening of the model if it is integrated (or simply wasted time and venture capital money that will lower their chances of getting more of it in the future). These tools also produce mazes of links that continue generating this content endlessly - each link has a procedurally generated name that the generator uses as a seed to generate more garbage, thus ensuring that no page needs be stored by the generator, but the same link will produce the same result every time (thus tricking bots into thinking the resource is permanent).
A few examples of these tools include Nepenthes, Iocaine, and Quixotic, each of which use slightly different techniques and have different design goals.
I've thought about what I might do if I were to program my own such tool, and here are some ideas I've come up with. Maybe they might inspire me to actually write something, or perhaps they could inspire you to write your own.
Generating Images via Markov Chain
Text is obviously not the only thing that AI companies want for training their models - many also want to be able to generate and analyze images. It at least seems to me that a good counter to that would be to provide images that appear statistically like the sorts of images they want.
So, how might one generate these images, especially considering as they're two-dimensional and can't just be generated using a Markov chain like text can? The solution here is to come up with some order in which to traverse the pixels, such as row-by-row, following rows and doing switchbacks, making a spiral, etc. The fancy mathematical name for this sort of line that you might trace through your pixels is the plane-filling function or space-filling curve. Using one of those naive options above - row-by-row, switchbacks, or a spiral - does have a drawback in that they all have poor spatial locality - in other words, two pixels that are next to each other in the image will end up in wildly different parts of the traversal order, making the final result less likely to be convincing.
A space-filling curve with much better spatial locality is the
Hilbert curve,
which is a fractal that, given a number of iterations n
, will fill up a square
that is 2^n
pixels to a side by drawing a series of straight lines at 90 degree
turns. A Hilbert curve can be generated via the following two procedures and your
starting n
:
A: +BF-AFA-FB+
B: -AF+BFB+FA-
where +
means "turn left", -
means "turn right", F
means "move forward",
A
means "run subprocedure A with n
set to n - 1
", and B
means "run subprocedure B with
n
set to n - 1
" (and in both A
and B
, do nothing if n
is 0). The Hilbert
curve is used with pretty decent success in the
Riemersma dithering algorithm, where the value of
a given pixel is given by the error values of the previous pixels in the curve (with pixels
in the 2^n
square that are left empty by the image drawn with a neutral color instead).
In a similar way, we could apply Hilbert curves to images in a small training set to generate Markov chains out of them, then use those Markov chains to generate new images that get placed on your AI poisoning output.
One problem with the space-filling curve Markov approach is the sheer enormity of the resulting chain - a Markov
chain with n
states needs to store up to n^2
probabilities in order to calculate the matrix -
if we use 24-bit color, like most image formats use, and then use a 4-byte float
to store each
probability, we can expect a storage burden of 2^50
bytes, or 1 petabyte - obviously way too
much for a project like this. There are, however, several things we can do to reduce the storage burden
and make the model more efficient:
- Reduce the resolution of the Markov probabilities - if you represent them as a single byte
from
0x00
to0xff
, then you reduce your storage needs four-fold. - Round low probabilities to zero and only store non-zero probabilities in a sparse graph. If you
can reduce the number of next states for each color to
2^8
, then you only need to store2^32
probabilities, which is a much more doable 16 gigabytes if using floats. - Reduce the color depth. If you only use 16-bit color, for instance, while still storing a full
array of states per color, you still only need to store
2^32
probabilities for the same 16 gigabytes if using floats. You can also play with the color space in order to get better results - for instance, one of the design principles behind JPEG is that humans have much less color resolution that light/darkness resolution, so you could use a perceptual color space like HSV and grant more bytes to the luminance/value while granting fewer bytes to the hue and saturation.
Generating Audio via Markov Chain
AI companies are also interested in generating and analyzing audio, so having audio that looks like something they would want but turns out to just be noise would also be interesting. However, while PCM audio is indeed one-dimensional, and thus doesn't require using Hilbert curves or related to create a Markov chain, it is very unlikely that the resulting sound would be mistaken as meaningful, since meaningful sounds almost always include sustained periodic waves that a Markov chain would not capture if it was asked to generate samples.
It's possible that you might get improved results from working in frequency space, which captures these waveforms as fundamental units. Indeed, since it is possible to approximate an arbitrary sound (at least one that is sufficiently short) with a series of increasingly more frequent sine waves at different amplitudes, it may well be more fruitful to use a Markov chain or other statistical method to generate those amplitudes instead.
Seeding an AI Poisoning Maze With Actual Content
That's enough about additional poison content, though. The idea I really think about a lot is more creative ways to actually use AI poison generators. The way they're currently deployed is as an obscure trap for AI bots to fall into, while being something that a human will quickly recognize as garbage and want to avoid. And, of course, a human visiting your site and clicking a link that leads to your AI poison generator might not know what's going on and get confused, and bounce off of your site entirely, or someone might become more wary of clicking links in the middle of your text because one of them led to your generator. You are thereby encouraged as a developer to insert links to your trap in places that would not normally be encountered by a human - and, of course, the more obvious this subversion, the more likely a bot will be to also recognize the link as low value and avoid it.
However, what if you made an AI poison link something that a user, even if only a particular subset of user, would want to click on, because mixed into the garbage designed for poisoning AI bots, the site also contained genuine, interesting, valuable content for visitors to find? Something that users will willingly explore, discuss, and post links to - and something that the likes of Google, with access to anonymized browsing history and PageRank, will also be believe is good content for their bots to explore when it really is not? (And also just to create something nice in the world, you know?)
The kind of content you could share this way could be anything, really. On the one end, maybe you simply have a list of missives and ruminations you want to write, but feel might be a little too boring to publish as a list or whatever and want to encourage more random exploration. By mixing your messages with the output of a text generator (perhaps the whole thing somewhere in one chunk, or split into chunks of two or three sentences), you can do just that.
Perhaps you have music or other audio to share. Personally, I do an impression of Spamton G. Spamton from DELTARUNE (mostly modeled after jerma985's voice for him) and I think it would be fun to record all of his lines from the game and post them into a generator like this - if nothing else, having him hide in the anti-AI garbage would be fitting. A more modest project might simply be to release the dozen or so tracks for your next music album, or make an archive of your podcast. This is where I would likely want to have tools for generating audio with the garbage, however, since a bot that was specifically looking for audio would simply snatch all the audio files they found without paying attention to the text.
With a network of such infinite anti-AI mazes, one could consider using them to construct an alternate reality game, where each maze includes several pages that resolve into further elements of the story and clues for where to look next (the reason I specifically mention a network of mazes is so that they can be the targets of multiple intentional links). This particular approach has the advantage where players will be likely to link directly to these pages in an effort to help other players know where to look, in prominent locations such as social networks and wikis where bots will also find those links.
Heck, you could even just post your blog in such a maze. Use a helper script that can introspect the poison generation and look for which page includes the post, and share that link in a feed or social media post (deleting the feed entry or post after the word has gotten out sufficiently).
You would probably need to establish some rules and fine-tune some things in order to make the experience pleasant for visitors and not waste their time with too much endless meandering - since, after all, any linked clicked in the AI poison maze will give no clues as to how far you are to the next geunine piece. On top of adjusting the probabilities that genuine content will be found on a page to a good sweet spot, a good rule to establish might be some sort of distance counter, where traversing 3 or more links away from a page that has genuine content will guarantee that there will never be any more geunine content past that point, hence giving your users the freedom to backtrack.
I think making something like that could be a lot of fun. I still have to get around to recording all those voice lines, of course.