harden(gateway): uniform 404 on API key revoke to hide cross-tenant existence (Stage 1 PR4)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1445043649
2026-06-28 20:19:20 +08:00
parent dee1eb2374
commit 938c2eb0be
2 changed files with 19 additions and 1 deletions
+3 -1
View File
@@ -104,6 +104,8 @@ async def revoke_api_key(
key = await key_repo.get(key_id)
if key is None:
raise HTTPException(status_code=404, detail="api key not found")
await _require_sa_in_workspace(key["service_account_id"], sa_repo)
sa = await sa_repo.get(key["service_account_id"])
if sa is None or sa["workspace_id"] != _current_workspace_id():
raise HTTPException(status_code=404, detail="api key not found")
await key_repo.revoke(key_id)
return Response(status_code=204)
+16
View File
@@ -157,3 +157,19 @@ async def test_create_for_suspended_sa_409(tmp_path):
assert r.status_code == 409
finally:
await _cleanup()
async def test_revoke_404_bodies_are_indistinguishable(tmp_path):
await _init_db_with_sa(tmp_path, sa_id="sa-1", workspace_id="w-1")
try:
client_a = TestClient(_make_app(workspace_id="w-1"))
created = client_a.post("/api/v1/api-keys", json={"service_account_id": "sa-1", "name": "k", "scopes": ""}).json()
client_b = TestClient(_make_app(workspace_id="w-2"))
# cross-workspace existing key, and a non-existent key, must return identical 404 bodies
cross = client_b.delete(f"/api/v1/api-keys/{created['id']}")
missing = client_b.delete("/api/v1/api-keys/does-not-exist")
assert cross.status_code == 404
assert missing.status_code == 404
assert cross.json() == missing.json()
finally:
await _cleanup()