{"id":"CVE-2026-73087","revision":null,"records":[{"revision":"0b5b4bf580c346b8bde0019219487595","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-73087","aliases":[],"title":"Dozzle: SSRF guard bypass via IPv6 transition addresses (6to4/NAT64/Teredo) in webhook notification dispatcher","description":"Dozzle is a realtime log viewer for docker containers. From 10.5.2 until 10.6.15, the isBlockedIP SSRF guard in internal/notification/dispatcher/webhook.go, used by safeDialContext for webhook notification URLs, does not inspect IPv4 addresses embedded in 6to4, NAT64, Teredo, or IPv4-compatible IPv6 addresses, allowing an authenticated user to reach loopback or link-local targets that the guard intends to block. This issue is fixed in version 10.6.15.","state":0,"publishedAt":"2026-08-11T16:52:13.728+00:00","modifiedAt":"2026-08-11T19:57:12.584+00:00","affected":[{"ecosystem":"Vendor product","name":"dozzle","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"amir20\",\n                    \"product\": \"dozzle\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 10.6.15\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 4.0","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N","score":2.3,"severity":"LOW"}],"references":["https://github.com/amir20/dozzle/security/advisories/GHSA-p2w3-6x73-2f6x","https://github.com/amir20/dozzle/pull/4887","https://github.com/amir20/dozzle/commit/8cf7ccd5ee041ecaea92b49951793d4d2393761f","https://github.com/amir20/dozzle/releases/tag/v10.6.15"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-73087","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-73087","identifiers":["CVE-2026-73087"]},"retained":false,"historicalAffected":[]},{"revision":"48a9386df4944fd6bd94b006e43699de","observedAt":"2026-10-25T15:19:03.401+00:00","statement":{"source":"nvd","id":"CVE-2026-73087","aliases":[],"title":"Dozzle is a realtime log viewer for docker containers. From 10.5.2 until 10.6.15, the isBlockedIP SSRF guard in internal/notification/dispatcher/webhook.go, used by safeDialContext for webhook notification URLs, does not inspect IPv4 addres…","description":"Dozzle is a realtime log viewer for docker containers. From 10.5.2 until 10.6.15, the isBlockedIP SSRF guard in internal/notification/dispatcher/webhook.go, used by safeDialContext for webhook notification URLs, does not inspect IPv4 addresses embedded in 6to4, NAT64, Teredo, or IPv4-compatible IPv6 addresses, allowing an authenticated user to reach loopback or link-local targets that the guard intends to block. This issue is fixed in version 10.6.15.","state":0,"publishedAt":"2026-08-11T17:19:16.83+00:00","modifiedAt":"2026-10-24T15:10:00.19+00:00","affected":[],"metrics":[{"system":"CVSS 4.0 · security-advisories@github.com · Secondary","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","score":2.3,"severity":"LOW"}],"references":["https://github.com/amir20/dozzle/commit/8cf7ccd5ee041ecaea92b49951793d4d2393761f","https://github.com/amir20/dozzle/pull/4887","https://github.com/amir20/dozzle/releases/tag/v10.6.15","https://github.com/amir20/dozzle/security/advisories/GHSA-p2w3-6x73-2f6x"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-73087","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-918"],"productCriteria":[],"sourceDates":{"published":"2026-08-11T17:19:16.830","lastModified":"2026-10-24T15:10:00.190"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-73087","identifiers":["CVE-2026-73087"]},"retained":false,"historicalAffected":[]},{"revision":"214021a83d6b431e825d0c7433b33f5b","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-p2w3-6x73-2f6x","aliases":["CVE-2026-73087","GO-2026-6440"],"title":"Dozzle: SSRF guard bypass via IPv6 transition addresses (6to4/NAT64/Teredo) in webhook notification dispatcher","description":"## Summary\n\nThe `isBlockedIP` SSRF guard in Dozzle's webhook notification dispatcher blocks loopback, link-local, multicast, and unspecified addresses but does not recognize IPv6 transition mechanism addresses (RFC 3056 6to4, RFC 6052 NAT64, RFC 4380 Teredo) that embed arbitrary IPv4 addresses. An authenticated user can bypass the guard to reach loopback services, cloud metadata endpoints (169.254.169.254), and other blocked ranges via webhook notification URLs.\n\n## Affected component / versions\n\n- Package: `github.com/amir20/dozzle`\n- Affected versions: all versions with SSRF guard (current HEAD [`b9df313`](https://github.com/amir20/dozzle/commit/b9df31356fc024e6768a1aac605844dc041d95ee))\n- Vulnerable code: `internal/notification/dispatcher/webhook.go`\n\n## Details\n\n### Root cause (CWE-918)\n\n[`internal/notification/dispatcher/webhook.go:32-51`](https://github.com/amir20/dozzle/blob/b9df31356fc024e6768a1aac605844dc041d95ee/internal/notification/dispatcher/webhook.go#L32-L51):\n\n```go\nfunc isBlockedIP(ip net.IP) bool {\n\tif ip.IsLoopback() ||\n\t\tip.IsLinkLocalUnicast() ||\n\t\tip.IsLinkLocalMulticast() ||\n\t\tip.IsMulticast() ||\n\t\tip.IsInterfaceLocalMulticast() ||\n\t\tip.IsUnspecified() {\n\t\treturn true\n\t}\n\tif v4 := ip.To4(); v4 != nil && zeroNetV4.Contains(v4) {\n\t\treturn true\n\t}\n\tif ip.Equal(net.IPv4bcast) {\n\t\treturn true\n\t}\n\treturn false\n}\n```\n\nThe guard intentionally allows RFC 1918 private ranges for self-hosted webhook targets, but blocks loopback (127.0.0.0/8, ::1), link-local (169.254.0.0/16, fe80::/10), and other non-routable addresses. IPv6 transition mechanism addresses bypass all these checks:\n\n| Mechanism | Prefix | Embeds | `isBlockedIP` result |\n|-----------|--------|--------|---------------------|\n| 6to4 | `2002::/16` | any IPv4 in bits 16-47 | `false` |\n| NAT64 WKP | `64:ff9b::/96` | any IPv4 in bits 96-127 | `false` |\n| Teredo | `2001:0000::/32` | any IPv4 in bits 96-127 | `false` |\n\n### Reachability / trust boundary\n\nThe `safeDialContext` function (line 53) resolves hostnames and checks each IP against `isBlockedIP` before establishing a TCP connection. This is used as the `DialContext` for the webhook HTTP client (line 115).\n\nWebhook URLs are configured by authenticated Dozzle users through the notification settings UI. The guard exists to prevent authenticated users from using webhook delivery as a proxy to reach the host machine's loopback services or cloud metadata endpoint.\n\n### Attack chain\n\n1. Authenticated user creates a webhook notification with URL `http://[2002:7f00:0001::1]:8080/` (6to4 embedding 127.0.0.1)\n2. When a notification triggers, Dozzle's webhook dispatcher calls `safeDialContext`\n3. The IPv6 address `2002:7f00:0001::1` is checked against `isBlockedIP` -- all predicates return false\n4. Connection proceeds to the 6to4 relay which routes to 127.0.0.1\n5. The webhook POST reaches the host's loopback services\n\n## Impact\n\nAn authenticated user can bypass the SSRF guard to:\n\n- Reach cloud metadata service at 169.254.169.254 via `2002:a9fe:a9fe::1` (6to4) to steal instance credentials\n- Reach localhost services via `64:ff9b::7f00:1` (NAT64) or `2002:7f00:0001::1` (6to4)\n- The webhook response body is logged at debug level but not returned to the user, making this a semi-blind SSRF (status code is returned)\n\nNote: RFC 1918 private ranges are intentionally allowed by the guard. This bypass specifically targets the blocked ranges (loopback and link-local/metadata) that the guard explicitly intends to prevent.\n\n## Proof of concept\n\nBypass vectors:\n\n```\n# 6to4 embedding 127.0.0.1 (bypasses IsLoopback)\nhttp://[2002:7f00:0001::1]:8080/\n\n# NAT64 embedding 169.254.169.254 (bypasses IsLinkLocalUnicast)\nhttp://[64:ff9b::a9fe:a9fe]/latest/meta-data/\n\n# 6to4 embedding 169.254.169.254 (bypasses IsLinkLocalUnicast)\nhttp://[2002:a9fe:a9fe::1]/latest/meta-data/\n\n# Teredo embedding 127.0.0.1\nhttp://[2001:0000:dead:beef:0000:0000:7f00:0001]:8080/\n```\n\nVerification that `isBlockedIP` returns false for all vectors:\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"net\"\n)\n\nfunc isBlockedIP(ip net.IP) bool {\n    return ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() ||\n        ip.IsMulticast() || ip.IsInterfaceLocalMulticast() || ip.IsUnspecified()\n}\n\nfunc main() {\n    for _, v := range []string{\n        \"2002:7f00:0001::1\",    // 6to4 -> 127.0.0.1\n        \"64:ff9b::a9fe:a9fe\",   // NAT64 -> 169.254.169.254\n        \"2002:a9fe:a9fe::1\",    // 6to4 -> 169.254.169.254\n    } {\n        ip := net.ParseIP(v)\n        fmt.Printf(\"%-35s blocked=%v\\n\", v, isBlockedIP(ip))\n    }\n}\n// Output: all false\n```\n\n## Remediation\n\nAdd IPv6 transition mechanism prefix checks to `isBlockedIP`:\n\n```go\nfunc isBlockedIP(ip net.IP) bool {\n\t// ... existing checks ...\n\n\t// IPv6 transition mechanisms embedding arbitrary IPv4\n\tif len(ip) == net.IPv6len {\n\t\tif ip[0] == 0x20 && ip[1] == 0x02 { return true } // 6to4\n\t\tif ip[0] == 0x00 && ip[1] == 0x64 && ip[2] == 0xff && ip[3] == 0x9b { return true } // NAT64\n\t\tif ip[0] == 0x20 && ip[1] == 0x01 && ip[2] == 0x00 && ip[3] == 0x00 { return true } // Teredo\n\t}\n\treturn false\n}\n```\n\n## Credit\n\nReported by tonghuaroot (tonghuaroot@gmail.com).","state":0,"publishedAt":"2026-09-08T18:11:56+00:00","modifiedAt":"2026-09-10T15:25:38.1741002+00:00","affected":[{"ecosystem":"Go","name":"github.com/amir20/dozzle","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.29.1-0.20260804193351-8cf7ccd5ee04"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"LOW"}],"references":["https://github.com/amir20/dozzle/security/advisories/GHSA-p2w3-6x73-2f6x","https://nvd.nist.gov/vuln/detail/CVE-2026-73087","https://github.com/amir20/dozzle/pull/4887","https://github.com/amir20/dozzle/commit/8cf7ccd5ee041ecaea92b49951793d4d2393761f","https://github.com/amir20/dozzle","https://github.com/amir20/dozzle/releases/tag/v10.6.15"],"sourceUrl":"https://github.com/advisories/GHSA-p2w3-6x73-2f6x","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-p2w3-6x73-2f6x","identifiers":["GHSA-p2w3-6x73-2f6x","CVE-2026-73087","GO-2026-6440"]},"retained":false,"historicalAffected":[]},{"revision":"efae8ac5543d4ee984b4e540d00a6fc7","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GO-2026-6440","aliases":["CVE-2026-73087","GHSA-p2w3-6x73-2f6x"],"title":"Dozzle: SSRF guard bypass via IPv6 transition addresses (6to4/NAT64/Teredo) in webhook notification dispatcher in github.com/amir20/dozzle","description":"Dozzle: SSRF guard bypass via IPv6 transition addresses (6to4/NAT64/Teredo) in webhook notification dispatcher in github.com/amir20/dozzle","state":0,"publishedAt":"2026-09-10T14:48:42+00:00","modifiedAt":"2026-09-10T15:15:15.7536386+00:00","affected":[{"ecosystem":"Go","name":"github.com/amir20/dozzle","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.29.1-0.20260804193351-8cf7ccd5ee04"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[],"references":["https://github.com/amir20/dozzle/security/advisories/GHSA-p2w3-6x73-2f6x","https://nvd.nist.gov/vuln/detail/CVE-2026-73087","https://github.com/amir20/dozzle/commit/8cf7ccd5ee041ecaea92b49951793d4d2393761f","https://github.com/amir20/dozzle/pull/4887","https://github.com/amir20/dozzle/releases/tag/v10.6.15"],"sourceUrl":"https://osv.dev/vulnerability/GO-2026-6440","license":"OSV · upstream source license applies","key":"osv:GO-2026-6440","identifiers":["GO-2026-6440","CVE-2026-73087","GHSA-p2w3-6x73-2f6x"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-10-25T22:04:08.5875992+00:00","complete":true,"records":1756,"lastAttemptAt":"2026-10-25T22:04:08.5875992+00:00","lastSuccessAt":"2026-10-25T22:04:08.8596165+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:04:08.8596241+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-1a687ad2a0b90150aa7d97c9f39e63de695ae2db23e31ebc28df1492c461b23c-1c072e7db56f0d3179c99f5b33ed9988c328ad75783993f151d8522bc700aaba","complete":true,"records":414046,"lastAttemptAt":"2026-10-25T22:02:18.7733512+00:00","lastSuccessAt":"2026-10-25T22:02:18.6654575+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:02:18.7733512+00:00","snapshotPublishedAt":"2026-10-25T21:21:07+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-43321610382942b8ad8c85917eab1546","complete":false,"records":4735,"lastAttemptAt":"2026-10-25T22:04:11.413428+00:00","lastSuccessAt":"2026-10-24T23:18:49.862+00:00","error":"InvalidDataException","lastVerifiedAt":"2026-10-24T23:18:49.862+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":4764,"expectedIdentifiers":13474},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-10-25T22:04:08.5875992+00:00","complete":true,"records":1093,"lastAttemptAt":"2026-10-25T22:04:08.5875992+00:00","lastSuccessAt":"2026-10-25T22:04:08.8610999+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:04:08.8611051+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-204a3fb93a00487e8f7f36db01dc851d","complete":true,"records":13413,"lastAttemptAt":"2026-10-25T22:04:09.4303098+00:00","lastSuccessAt":"2026-10-25T16:19:28.681+00:00","error":null,"lastVerifiedAt":"2026-10-25T16:19:28.681+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13474,"expectedIdentifiers":13474},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-2375a4e597279abf92e8747e140fe8da9d421877cd49cae3ac69a2cb78469b2c","complete":true,"records":9779,"lastAttemptAt":"2026-10-25T22:04:08.4463409+00:00","lastSuccessAt":"2026-10-24T13:19:53.1346702+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:04:08.4463409+00:00","snapshotPublishedAt":"2026-10-24T03:03:12+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-16ad89dfea13ab9e9b0108e63a759d63bd4559cc68b58491107d62ee35bbbaf2","complete":true,"records":1965,"lastAttemptAt":"2026-10-25T22:02:18.9302775+00:00","lastSuccessAt":"2026-10-23T16:01:26.4487605+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:02:18.9302775+00:00","snapshotPublishedAt":"2026-10-21T12:18:07+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-7da67a15aa6e56a0e3081a7646dc74d537e6ef974afc593c2b1794ed01970648","complete":true,"records":2969,"lastAttemptAt":"2026-10-25T22:04:08.554556+00:00","lastSuccessAt":"2026-10-24T13:19:59.1145547+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:04:08.554556+00:00","snapshotPublishedAt":"2026-10-24T08:47:51+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-11236ada05a0588e51df37636716526867f73fb127392c49680b6f8561496a99","complete":true,"records":230781,"lastAttemptAt":"2026-10-25T22:04:08.3201814+00:00","lastSuccessAt":"2026-10-25T22:04:07.173333+00:00","error":null,"lastVerifiedAt":"2026-10-25T22:04:08.3201814+00:00","snapshotPublishedAt":"2026-10-25T21:33:06+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null}]}