Every CVE Search/ Get API key

CVE-2026-33693

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

6.5 MediumPublic exploitFix available

Lemmy is a link aggregator and forum for the fediverse. Prior to version 0.7.0-beta.9, 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. Version 0.7.0-beta.9 patches the issue.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Exploit likelihood

0.37%Up 0.3 points since Mar 27, 2026
90%50%10%1%

What each source reports

CVE List Score used 6.5

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

Lemmy is a link aggregator and forum for the fediverse. Prior to version 0.7.0-beta.9, 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. Version 0.7.0-beta.9 patches the issue.

Record
CVE-2026-33693
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
EUVDEUVD-2026-16494 6.5

Lemmy is a link aggregator and forum for the fediverse. Prior to version 0.7.0-beta.9, 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. Version 0.7.0-beta.9 patches the issue.

Record
EUVD-2026-16494
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-q537-8fr5-cw35 6.5

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

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

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
    1. Attacker sends ActivityPub activity referencing https://evil.com/actor
    1. Library calls verify_url_valid() → is_invalid_ip() → resolves to 0.0.0.0
    1. v4_is_invalid(0.0.0.0) returns false (BYPASS)
    1. 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

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:

let resolved_ip = lookup_host((domain, 80)).await?;
// validate resolved_ip...
let client = reqwest::Client::builder()
    .resolve(domain, resolved_ip)  // pin resolution
    .build()?;
Record
GHSA-q537-8fr5-cw35
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
NVD 6.5

Lemmy is a link aggregator and forum for the fediverse. Prior to version 0.7.0-beta.9, 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. Version 0.7.0-beta.9 patches the issue.

Record
CVE-2026-33693
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSV 6.5

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

Lemmy is a link aggregator and forum for the fediverse. Prior to version 0.7.0-beta.9, 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. Version 0.7.0-beta.9 patches the issue.

Record
CVE-2026-33693
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02
OSVGHSA-q537-8fr5-cw35 6.5

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

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

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
    1. Attacker sends ActivityPub activity referencing https://evil.com/actor
    1. Library calls verify_url_valid() → is_invalid_ip() → resolves to 0.0.0.0
    1. v4_is_invalid(0.0.0.0) returns false (BYPASS)
    1. 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

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:

let resolved_ip = lookup_host((domain, 80)).await?;
// validate resolved_ip...
let client = reqwest::Client::builder()
    .resolve(domain, resolved_ip)  // pin resolution
    .build()?;
Record
GHSA-q537-8fr5-cw35
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-918
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
activitypub_federation
crates.io
before 0.7.0-beta.9
0.7.0-beta.9

Public exploits

Links only. Every CVE stores no exploit code.

Public exploits
SourceLinkDate
PoC in GitHubSnailSploit/CVE-2026-336932026-03-23

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV, PoC in GitHub

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-33693 is a medium vulnerability (CVSS 6.5) in Lemmynet Lemmy, published March 25, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 0.37%, the 31st percentile. Fixed in activitypub_federation 0.7.0-beta.9.

References

MoveEnter Open