Bug description
While browsing the dashboard (app.unkey.com), the dashboard's own server side repeatedly calls POST /v2/apis.getApi for the workspace's API with a credential that lacks the read_api permission. Every call is rejected with 403 Insufficient Permissions, and each rejected request is written into the customer's workspace request logs and counted in the Requests page metrics.
The result: the workspace Logs page (/logs) fills with identical 403 entries the customer never sent, and the "invalid" counters on the Requests overview include this dashboard-generated noise, which makes real API traffic hard to read.
Evidence
Sample log entry as shown in the workspace's own Logs page:
POST /v2/apis.getApi, status 403
- Request body:
{"apiId": "<the workspace's API id>"}
- Response body:
{"error":{"detail":"Missing one of these permissions: api.*.read_api or api.<apiId>.read_api","status":403,"title":"Insufficient Permissions","type":"https://unkey.com/docs/errors/unkey/authorization/insufficient_permissions"},"meta":{"requestId":"req_..."}}
Request headers captured from the log detail pane, showing the caller is the dashboard's own deployment (Vercel + Sentry, User-Agent: node), with request-specific values redacted:
Accept: application/json
Accept-Encoding: br, gzip, deflate
Accept-Language: *
Authorization: [REDACTED]
Baggage: sentry-environment=vercel-production,sentry-release=5019ea8003091c6d3d264c493948c7941cb66029,sentry-public_key=08589d17fe3b4b7e8b70b6c916123ee5,sentry-trace_id=[REDACTED],sentry-org_id=4510544758046720
Content-Length: 28
Content-Type: application/json
Sec-Fetch-Mode: cors
Sentry-Trace: [REDACTED]
User-Agent: node
X-Invocation-Id: [REDACTED]
X-Vercel-Id: [REDACTED]
The sentry-release value is commit 5019ea8003091c6d3d264c493948c7941cb66029 in this repo ("fix(dashboard): give option to override vercel url (#6699)"), so the caller is the dashboard app itself, not customer code.
Additional observations:
- The 403s arrive in bursts (often pairs 1–2 seconds apart, then every 30–60 seconds) exactly while a workspace member is navigating the dashboard, and stop when nobody is browsing. Over a 4-week window, all occurrences cluster on the days the dashboard was in use.
- The affected integration only ever calls
keys.createKey, keys.deleteKey, and keys.verifyKey; nothing customer-side calls apis.getApi at all.
- A dashboard-initiated
keys.updateKey (200) appears in the same customer log stream, so dashboard-originated v2 API calls being logged into customer workspaces looks like a general behavior, not specific to the failing call.
Reproduction should be straightforward: watch any workspace's Logs page in Live mode while clicking through the Keyspaces/API pages of the dashboard, and the 403 apis.getApi entries appear in step with navigation.
Expected behavior
- The dashboard's internal reads should carry the permissions they need (or not be attempted), so they don't generate a stream of 403s.
- Dashboard-originated traffic should not appear in customer workspace request logs / request metrics, or at least be distinguishable from the customer's own API traffic.
Impact
- Logs page is flooded with 403 noise the customer cannot act on.
- Requests overview "invalid" counts are inflated, making it look like the customer's integration is failing when it isn't.
Bug description
While browsing the dashboard (app.unkey.com), the dashboard's own server side repeatedly calls
POST /v2/apis.getApifor the workspace's API with a credential that lacks theread_apipermission. Every call is rejected with 403 Insufficient Permissions, and each rejected request is written into the customer's workspace request logs and counted in the Requests page metrics.The result: the workspace Logs page (
/logs) fills with identical 403 entries the customer never sent, and the "invalid" counters on the Requests overview include this dashboard-generated noise, which makes real API traffic hard to read.Evidence
Sample log entry as shown in the workspace's own Logs page:
POST /v2/apis.getApi, status 403{"apiId": "<the workspace's API id>"}{"error":{"detail":"Missing one of these permissions: api.*.read_api or api.<apiId>.read_api","status":403,"title":"Insufficient Permissions","type":"https://unkey.com/docs/errors/unkey/authorization/insufficient_permissions"},"meta":{"requestId":"req_..."}}Request headers captured from the log detail pane, showing the caller is the dashboard's own deployment (Vercel + Sentry,
User-Agent: node), with request-specific values redacted:The
sentry-releasevalue is commit5019ea8003091c6d3d264c493948c7941cb66029in this repo ("fix(dashboard): give option to override vercel url (#6699)"), so the caller is the dashboard app itself, not customer code.Additional observations:
keys.createKey,keys.deleteKey, andkeys.verifyKey; nothing customer-side callsapis.getApiat all.keys.updateKey(200) appears in the same customer log stream, so dashboard-originated v2 API calls being logged into customer workspaces looks like a general behavior, not specific to the failing call.Reproduction should be straightforward: watch any workspace's Logs page in Live mode while clicking through the Keyspaces/API pages of the dashboard, and the 403
apis.getApientries appear in step with navigation.Expected behavior
Impact