anamorpher: generating and comparing image scaling payloads for multi-modal prompt injection
image scaling attacks for multi-modal prompt injection
At a glance
- What is it?
- Trail of Bits' anamorpher crafts images whose hidden prompt injection text only appears after a model's image pipeline downsamples them, and pairs a Flask backend with a browser frontend so you can compare downscaling implementations side by side. It is a research and evaluation tool, and its own README lists sharp limits on what it can promise.
- Who is it for?
- Adopt anamorpher if you own a multi-modal pipeline and need to know whether your image preprocessing is exposed to scaling based prompt injection, and read the README's warning that results vary enough to require five runs per example. Do not expect a stable library API: it is at version 0.1.0 in active beta, ships a backend app and a static frontend, and has no GitHub releases.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 157 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why downscaling hides a prompt injection
The idea anamorpher is built on is narrow and mechanical. A multi-modal model receives images that have been resized, and the resizing algorithm averages neighbouring pixels. Text drawn at a size that survives the original resolution can be smeared into unreadable grey noise by that averaging step, yet a human looking at the downscaled result sees nothing. A vision model, however, may recover a legible instruction from the same smear. Anamorpher, named after anamorphosis, builds images whose payload becomes visible only under the downscale, which is what the README calls a prompt injection that reveals itself when the image is scaled down.
The attack surface this targets is production, not a lab demo. The README points to the Trail of Bits post Weaponizing image scaling against production AI systems for background on the vector, and to two USENIX papers, Adversarial Preprocessing: Understanding and Preventing Image-Scaling Attacks in Machine Learning and Seeing is Not Believing: Camouflage Attacks on Image Scaling Algorithms, which place the technique in a longer line of scaling camouflage research.
So the audience is not an end user of AI products. It is the engineer or security team who uploads images into a system that resizes them, and who needs to know whether an instruction can survive that resize and reach the model. The tool is the measurement half of that question, and the README is explicit that the results are probabilistic rather than deterministic.
What the Flask backend and static frontend actually do
The repository splits into a backend directory and a frontend directory, with backend/app.py as the entry point named in the setup instructions. The Python project metadata names the package anamorpher at version 0.1.0, built with hatchling, and the wheel target packages the backend directory. The project description is terse: Image scaling and adversarial generation tool.
The dependency list in pyproject.toml explains the mechanism. opencv-python and Pillow cover the classic imaging libraries, torch and torchvision supply the PyTorch path, tensorflow covers the TensorFlow path, and numpy handles the array maths that the payload generation depends on. Flask and Flask-CORS serve the backend and allow the browser frontend to call it, while bleach and MarkupSafe sit in the list alongside the image stack, which points to HTML sanitization being handled in the serving path rather than left to the browser.
The feature list describes three capabilities. Payloads can be generated for select implementations of the bicubic, bilinear and nearest neighbour downscaling algorithms. A frontend interface lets you compare payload effectiveness across OpenCV, PyTorch, TensorFlow and Pillow implementations, which is the practical value of the tool, since a payload is only meaningful against the exact resizer in your pipeline. Third, the Python API is described as modular, with the explicit goal of letting you plug in your own downscaling implementation.
The repository also ships a gemini-cli-PoC.gif and an image_scaling_figure.png at the top level, so the maintainers included a demonstration of the attack against a real command line assistant as well as a comparison figure.
Setting up anamorpher with uv on Python 3.11 or newer
The README lists the requirements as Python 3.11+ and uv, recommended, or pip as an alternative. The setup is three steps, and the backend has to be running before the frontend is useful, because the frontend is a static page that calls the local server.
uv syncThat first command resolves the dependency set from pyproject.toml and uv.lock into the project environment. The lock file is committed, so the resolution is meant to be repeatable rather than floating.
uv run python backend/app.pyThis starts the Flask backend. Once it is up, the README tells you to open the frontend page in a browser.
# Open this in a web browser after the backend is running
frontend/index.htmlWindows users get a specific caveat: WSL2 is required because of the TensorFlow dependencies. That is a real constraint rather than a footnote, since a native Windows install of the full dependency set is not what the maintainers support. For development, the project declares pytest, ruff, ty and pre-commit under tool.uv dev-dependencies, and the pytest configuration lives in pyproject.toml with testpaths set to tests, strict markers, and registered slow and integration markers, so you can deselect slow tests with -m "not slow".
Where the payloads stop working
The README carries a warnings section that is more informative than the feature list, and it is the first thing to read before drawing conclusions from any result.
The first limitation is about probability. Because the systems involved behave probabilistically, results may vary, and the README advises running each example 5 times to get a consistent evaluation. A single successful or failed run tells you very little in that design.
The second is interference. Additional image transformations, meaning anything applied after the resize, may break the injection entirely. A pipeline that downscales and then re-encodes, sharpens or crops is not the pipeline anamorpher was measured against.
The third is the one that most limits generalisation. Not all payloads work against every implementation and parameter set of the bicubic and bilinear algorithms. The README attributes this to the differing resistance of anti-aliasing across implementations, different default parameters in scaling libraries, and implementation specific optimizations that change interpolation behaviour. The consequence is blunt: a payload tuned for one library is not evidence of anything about another library, which is exactly why the frontend compares OpenCV, PyTorch, TensorFlow and Pillow side by side rather than reporting one number.
The README closes the section by extending the same caveat to production AI systems, since system scaling behaviour is subject to change. A defence validated against a specific resizer configuration has a shelf life.
Security research tooling, and what it is not for
It is worth being direct about where this sits. Anamorpher generates working prompt injection payloads for multi-modal systems. The README says as much, and it links a post titled Weaponizing image scaling against production AI systems. The same README also carries the caveat that not all payloads work against all implementations, which tells you it is built to test a specific pipeline rather than to defeat any model generally.
The tool is published by Trail of Bits under the Apache-2.0 licence, with Kikimora Morozova and Suha Sabi Hussain listed as maintainers, and the README states that Anamorpher is in active beta development and welcomes feedback and contributions. There is a CONTRIBUTING.md, a CODEOWNERS file, a pre-commit configuration and a.github directory, all of which point to a project that expects outside contributions rather than a one-off proof of concept.
It is the wrong tool for several adjacent jobs. It does not defend a pipeline, it measures one. It has no detection, filtering or sanitization component, no runtime guard for incoming images, and no patch to apply. It also does not address the other, much more common route to prompt injection, where the instruction arrives as text in a user message or in a document the model reads, and there is no resizing step to abuse. The payoff of anamorpher depends entirely on the assumption that your pipeline downsamples images at a point where the model then reads them.
A different approach to the same question is the Adversarial Preprocessing paper referenced in the README, whose title frames the problem from the defensive side, preventing image scaling attacks in machine learning. Anamorpher attacks a resizer from the payload side and gives you the comparison surface; the paper starts from the prevention side. Neither substitutes for reading how your own system actually handles uploads.
Version, dependency and licence considerations for adopters
The package is at version 0.1.0 and the repository has no GitHub releases, so there is no release stream to track and no upgrade path other than pulling the default branch. The last push was on 2026-05-19, and the repository is not archived. Given the beta status the README declares, expect the interface to move.
Dependency weight is the bigger practical cost. The install pulls in TensorFlow, PyTorch, torchvision, OpenCV and Pillow, and the Windows note about WSL2 exists because of the TensorFlow dependencies. Anyone evaluating this on a shared analysis host should budget for the disk and memory those two frameworks occupy, and note that the API is not packaged as a light library.
On licence, Apache-2.0 is permissive and carries the usual attribution and notice conditions, so internal security evaluation and derived tooling are generally straightforward. That is a statement about the licence terms and not legal advice, and organisations with their own review process should still read the LICENSE file in the repository.
Editorial conclusion
Adopt anamorpher if you own a multi-modal pipeline and need to know whether your image preprocessing is exposed to scaling based prompt injection, and read the README's warning that results vary enough to require five runs per example. Do not expect a stable library API: it is at version 0.1.0 in active beta, ships a backend app and a static frontend, and has no GitHub releases. Verify first that the downscaling implementation in your stack matches one of the frontend's compared implementations, since a payload that works under one interpolation library says little about another.
Frequently asked questions
What is anamorpher used for?
It crafts and visualizes image scaling attacks against multi-modal AI systems, generating images that only reveal a multi-modal prompt injection once they are downscaled. The README points to the Trail of Bits post Weaponizing image scaling against production AI systems for background.
How do I install and run anamorpher?
The README requires Python 3.11+ and uv, then instructs you to run uv sync, start the backend with uv run python backend/app.py, and open frontend/index.html in a browser. Windows users are told to use WSL2 because of the TensorFlow dependencies.
Do anamorpher payloads work against every image library?
No. The README states that not all payloads work against each implementation and parameter set of the bicubic and bilinear algorithms, because anti-aliasing, default parameters and interpolation optimizations differ, which is why the frontend compares OpenCV, PyTorch, TensorFlow and Pillow separately.
How many times should I run an anamorpher example?
The README advises running each example 5 times, since the systems involved are probabilistic and a single run gives an inconsistent evaluation. It also warns that additional image transformations can interfere with the effectiveness of the injections.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/trailofbits-anamorpher)Was this useful?