I found this issue while reviewing Penpot, the open-source design and code collaboration platform, with a very specific question in mind:
What happens when a collaborative design tool lets one user hand the backend a remote image URL to fetch?
In this case, that question led to a real bug.
Penpot's remote image import flow accepted a user-controlled URL and caused the backend to fetch it from the server network context without enforcing destination restrictions for loopback or private-network targets. The shared HTTP client also followed redirects automatically.
That turned a normal media convenience feature into an authenticated backend-origin SSRF primitive and ultimately became CVE-2026-45806.
Penpot: Penpot on GitHub
CVE: CVE-2026-45806
CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
This affected Penpot. On its official site and media kit, Penpot presents itself as having a +1M growing user base and says that tens of thousands of organizations use it, including Blender, Mozilla, Fedora, NTT Data, MIT, Société Générale, Cisco, Fujitsu, Indra, and ByteDance.
authenticated file editor -> attacker-controlled remote image URL -> create-file-media-object-from-url -> backend download-image fetch with redirects enabled -> final request lands on internal-only image endpoint -> backend-origin SSRF / internal reachability
Penpot is an open-source design and code collaboration platform.
It handles things like:
That means its media import path sits on a real trust boundary.
The important question here was not whether Penpot supports importing remote images.
The real question was:
Does Penpot restrict where the backend is allowed to connect when a user imports a remote image?
In this case, it did not.
A lot of people underestimate remote import features.
That is a mistake.
The moment an application:
it creates a real outbound trust boundary.
That was the issue here.
This bug was not in image rendering. It was not in file storage. It was not in ordinary permission checks for editing a file.
It was a classic server-side trust failure:
That is enough to create a real vulnerability.
I did not approach Penpot by blindly fuzzing random RPC methods or looking for crashes first.
The stronger approach was to identify the most promising security boundary.
For Penpot, that was remote media import.
Why?
Because this feature combines:
That was the right boundary to inspect.
And it was exactly where the bug lived.
The bug reduces to a small trust chain.
In the frontend:
the user-controlled url is sent directly into the RPC call.
Then in the backend:
and:
the backend checks that the caller can edit the target file, then passes the attacker-controlled URL into media/download-image.
The fetch implementation is here:
And the shared HTTP client is configured as:
That is the whole vulnerability:
Because the attacker only needs:
The attack chain is straightforward:
That is the whole bug.
The important distinction is where the request happens.
The question is not:
"Can Penpot import images from URLs?"
The real question is:
"Can an authenticated user make the Penpot backend connect to internal destinations that the user should not be able to reach through the application?"
In this case, the answer was yes.
That matters because there is a real difference between:
Image validation does not remove that difference.
It narrows some direct exfiltration cases, but it does not remove the SSRF condition or the network boundary break.
I validated this issue with a controlled local proof tied directly to the reviewed Penpot code path.
The goal was not to hit third-party infrastructure. The goal was to prove the exact security property:
I built a self-contained Java validator that mirrored the relevant behavior:
content-type and content-lengthI validated two cases.
The validator requested:
Observed result:
http://127.0.0.1:7790/internal.pnghttp://127.0.0.1:7790/internal.png200image/pngThat proved the import-style fetch logic accepted an internal-only image endpoint directly.
The validator then requested:
That endpoint returned an HTTP redirect to:
Observed result:
http://localhost:7791/redirect-to-internalhttp://127.0.0.1:7790/internal.png200image/pngThe internal-only listener logged the redirected request.
That proved the more important claim:
The payload here was intentionally simple:
That mattered because Penpot does not just fetch arbitrary bytes and stop. It performs media-oriented validation after the request.
So the right proof was not:
"the backend can try to connect somewhere"
The stronger proof was:
"the backend can be made to connect somewhere internal and complete the request successfully under the same image-like constraints the feature expects"
That is exactly what the validation demonstrated.
A common reaction to SSRF bugs like this is:
"the target still has to return an image"
That observation is true but incomplete.
It does not remove the vulnerability.
It just tells you which internal targets are most directly useful.
This issue still enables:
That is still a real security boundary break.
Especially in self-hosted environments, internal services often exist specifically behind that boundary.
This issue was ultimately assigned a High severity CVSS:
That classification makes sense.
The claim is not that an unauthenticated attacker can instantly compromise every Penpot deployment from nothing.
The claim is that any normal authenticated file editor can turn Penpot into a backend request primitive against internal destinations, including redirect-assisted access to loopback and private-network targets.
There was some severity discussion during disclosure, largely around:
Those are fair constraints to discuss.
But they do not remove the core issue:
That is a real and defensible SSRF vulnerability.
The important fix here is not stricter MIME handling.
The real fix is outbound destination policy.
A correct remediation for this class of bug needs to:
http and httpslocalhostThat is the right fix direction because this was not an image parsing bug. It was a network trust-boundary bug.
This issue was reported privately through GitHub's security reporting flow.
The report included:
The maintainers confirmed the issue and began working on a resolution.
The issue was later assigned:
CVE-2026-45806
The key lesson here is simple:
remote media import is an outbound trust boundary, not just a convenience feature
A lot of developers think in terms of:
Those are implementation details.
The real security question is:
where is the backend allowed to connect on behalf of a user?
If that question is not answered explicitly, features like remote import become SSRF surfaces by default.
This bug also reinforces something important about SSRF review:
That is the real takeaway.
This vulnerability was not about a flashy payload.
It was about asking the right trust-boundary question.
Penpot let an authenticated file editor provide a remote image URL, and the backend trusted that URL farther than it should have. The redirect handling did the rest.
That is why this became CVE-2026-45806.