CVE-2026-55177: CloudTAK Authenticated Full-Read SSRF in /api/esri Routes
Any logged-in CloudTAK user can make the server fetch an arbitrary internal URL (cloud metadata, loopback ports, VPC services) through the ESRI helper routes, and read the full response back, because
The problem
Every route in the `/api/esri*` family accepts a fully user-controlled URL from the request body or query string and passes it to `EsriBase` / `EsriProxy*` classes, which call the bare `fetch` from `@tak-ps/etl`. No IP or hostname classification runs before the request is issued.
The only inspection the URL receives is `EsriBase.sniff()`, which pattern-matches only the URL pathname for `/rest`, `/arcgis/rest`, or `/sharing/rest`. An attacker adds that suffix to any internal address and `sniff()` approves it. The response body is returned verbatim to the caller via `res.json()`, or reflected in the error string, making this a full-read (not blind) SSRF.
All six affected routes require only a valid user token (`anyResources: true`), not an admin role. This means any account can exploit the flaw.
Proof of concept
A working proof-of-concept for CVE-2026-55177 in @tak-ps/cloudtak, with the exact payload below.
# Variant 1: read AWS IMDSv1 credentials (full-read)
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"}
# Variant 2: read an internal-only loopback service (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>
# Both return the upstream JSON body directly in the response.
# /arcgis/rest or /rest suffix satisfies sniff() path check; host is never validated.The root cause is an incomplete SSRF-hardening migration. The repository already ships `isSafeUrl` from `@tak-ps/node-safeurl` and uses it in `basemap.ts`, `task.ts`, and `video-service.ts`, but the guard was never wired into `api/lib/esri.ts` or any of the six `/api/esri*` route handlers.
`sniff()` validates only the URL pathname, not the host, so appending `/rest` or `/arcgis/rest` to any private address bypasses the only pre-fetch check. The patch (commit `ff6dd1d9` on the advisory fork) centralizes a `safeFetch` wrapper and an `EsriBase.assertSafe` method inside `api/lib/esri.ts`, so every `EsriProxy*` call and every `fetchVersion()` / `generateToken()` call now runs `isSafeUrl` before the first outbound request.
The fix
Upgrade `@tak-ps/cloudtak` to **v13.10.0**. The fix adds a `safeFetch` wrapper and `EsriBase.assertSafe` in `api/lib/esri.ts` that call `isSafeUrl(...)` before every outbound fetch, blocking loopback, link-local, and private-range destinations. The same `process.env.StackName !== 'test'` skip used by other guarded paths is preserved.
Operators who cannot upgrade immediately should restrict access to the `/api/esri*` routes at the network layer and enforce IMDSv2 (token-required mode) on any cloud host running CloudTAK.
Reported by tonghuaroot.
Related research
- high · 8.6CVE-2026-50131CVE-2026-50131: @fedify/fedify SSRF Mitigation Bypass via Incomplete IPv4 Validation
- critical · 9.6CVE-2026-53513CVE-2026-53513: @better-auth/sso SSRF via Unvalidated OIDC Endpoints
- high · 7.4CVE-2026-49857CVE-2026-49857: auth-fetch-mcp SSRF Protection Bypass via IPv4-mapped IPv6 Loopback
- high · 8.5CVE-2026-54353CVE-2026-54353: @budibase/backend-core SSRF DNS Rebinding Bypass