Loading...
Skip to main content

CVE-2026-33693 — Vulnerability in activitypub_federation — CVE Details

MEDIUM

Activitypub-Federation has SSRF via 0.0.0.0 bypass in activitypub-federation-rust v4_is_invalid()

Published March 25, 2026Updated April 2, 2026Source: osv

Summary

### Summary The `v4_is_invalid()` function in `activitypub-federation-rust` (`src/utils.rs`) does not check for `Ipv4Addr::UNSPECIFIED` (0.0.0.0). An unauthenticated attacker controlling a remote domain can point it to 0.0.0.0, bypass the SSRF protection introduced by the fix for CVE-2025-25194 (GHSA-7723-35v7-qcxw), and reach localhost services on the target server. ### Details **File:** `src/utils.rs` in `activitypub-federation-rust` **Function:** `v4_is_invalid(v4: Ipv4Addr) -> bool` The function checks `is_private()`, `is_loopback()`, `is_link_local()`, `is_multicast()`, and `is_documentation()` — but omits `is_unspecified()`. On Linux, macOS, and Windows, TCP connections to 0.0.0.0 are routed to localhost (127.0.0.1). Additionally, `::ffff:0.0.0.0` (IPv4-mapped IPv6) also bypasses because `v6_is_invalid()` calls `to_ipv4_mapped().is_some_and(v4_is_invalid)`, inheriting the same gap. Notably, `v6_is_invalid()` already includes `is_unspecified()` for native IPv6, making this an asymmetric oversight. **Independent secondary finding — DNS Rebinding TOCTOU:** `is_invalid_ip()` resolves DNS via `lookup_host()` for validation, but `reqwest` resolves DNS again for the actual connection. With TTL=0 DNS responses, an attacker can return a legitimate IP for the first resolution (passes check) and 127.0.0.1 for the second (reqwest connects to localhost). CVSS for rebinding alone: 4.8 (AC:H). ### PoC **1. Logic Proof (reproduced from source):** ```rust fn v4_is_invalid(v4: Ipv4Addr) -> bool { v4.is_private() || v4.is_loopback() || v4.is_link_local() || v4.is_multicast() || v4.is_documentation() // BUG: Missing || v4.is_unspecified() } assert_eq!(v4_is_invalid(Ipv4Addr::UNSPECIFIED), false); // 0.0.0.0 PASSES validation assert_eq!(v4_is_invalid(Ipv4Addr::LOCALHOST), true); // 127.0.0.1 correctly blocked ``` **2. OS Routing Verification:** ``` $ connect(0.0.0.0:80) → ConnectionRefused ``` ConnectionRefused proves the OS routed to localhost (port 80 not listening). Any service on 0.0.0.0:PORT is reachable. **3. Attack Chain:** 1. Attacker configures DNS: `evil.com A → 0.0.0.0` 2. 2. Attacker sends ActivityPub activity referencing `https://evil.com/actor` 3. 3. Library calls `verify_url_valid()` → `is_invalid_ip()` → resolves to 0.0.0.0 4. 4. `v4_is_invalid(0.0.0.0)` returns `false` (BYPASS) 5. 5. `reqwest` connects to 0.0.0.0 → reaches localhost services ### Impact - **Direct:** Bypasses the SSRF protection layer for all ActivityPub federation traffic - - **Downstream:** 6+ dependent projects affected including Lemmy (13.7k stars), hatsu, gill, ties, fediscus, fediverse-axum - - **Attacker can:** Access cloud instance metadata (169.254.169.254 via rebinding), reach internal services on localhost, port scan internal infrastructure ### Suggested Fix ```rust fn v4_is_invalid(v4: Ipv4Addr) -> bool { v4.is_private() || v4.is_loopback() || v4.is_link_local() || v4.is_multicast() || v4.is_documentation() || v4.is_unspecified() // ADD: blocks 0.0.0.0 || v4.is_broadcast() // ADD: blocks 255.255.255.255 } ``` For DNS rebinding TOCTOU, pin the resolved IP: ```rust let resolved_ip = lookup_host((domain, 80)).await?; // validate resolved_ip... let client = reqwest::Client::builder() .resolve(domain, resolved_ip) // pin resolution .build()?; ```

Advisory Timeline

  • First published March 25, 2026 (201 days ago).
  • Last revised April 2, 2026 — 8 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Cargo
Update activitypub_federation to 0.7.0-beta.9 or later
cargo update -p activitypub_federation --precise 0.7.0-beta.9

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: crates.io (1).

PackageEcosystemAffectedFixed In
activitypub_federation
crates.io
All versions0.7.0-beta.9

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-918
    Server-Side Request Forgery (SSRF)MITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 6.5 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
Low
Availability
None

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N

Frequently Asked Questions

What is CVE-2026-33693?
Activitypub-Federation has SSRF via 0.0.0.0 bypass in activitypub-federation-rust v4_is_invalid() This vulnerability has been assigned a severity rating of MEDIUM (CVSS score: 6.5/10).
How do I check if my project is affected by CVE-2026-33693?
CVE-2026-33693 affects activitypub_federation. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-33693 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
6.5

Exploitation requires specific conditions or has limited impact. Remediate within weeks.

Also Known As

GHSA-q537-8fr5-cw35

Related CVEs

  • CVE-2026-102821
    MEDIUM

    Russh: Unbounded memory exhaustion via CHANNEL_OPEN flood during a client-stalled rekey

  • CVE-2026-102820
    MEDIUM

    pageant: Out-of-bounds read / oversized allocation in `pageant` MemoryMap::read via a malicious Pageant agent (Windows)

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies