SELF-HOSTED AI GATEWAY / SECURITY EVIDENCE
Twenty-three attacks, one run, no credentials
The repository ships a regression that boots the real gateway HTTP server and then attacks it. This page is the output of that run, reformatted - every row below is a line the tool printed. The content was generated from the run rather than typed, so a row cannot quietly disagree with the tool that produced it.
SECTION 01 / WHAT RAN
Not a unit test
- It imports the actual application and HTTP server modules and calls
listen(0, "127.0.0.1"), so requests travel over a real socket against a real router rather than through a mocked transport. - State is created in a temporary directory; nothing is read from a developer checkout's configuration and nothing persists after the process exits.
- The gateway runs with the local fake provider. No provider credential exists in the process, so the run costs nothing and sends nothing anywhere.
- Each check asserts the defense, and the tool prints
BREACH!!plus a non-zero exit if any check fails - so "all defended" is a conclusion the script reaches on its own.
SECTION 02 / THE 23 RESULTS
What was attempted, and what came back
| Attack | Observed response | Verdict |
|---|---|---|
| A0 public enterprise health hides storage paths | status=200 | defended |
| A1 seed | — | defended |
| A1 cross-tenant exact-cache isolation | tenant B served by a fresh provider call, never tenant A's cache lane | defended |
| A2 tenant header forgery | status=403 | defended |
| A2b admin tenant header forgery | status=403 | defended |
| A2c admin cross-tenant virtual-key creation | status=403 | defended |
| A2d cross-tenant audit filter | status=403 | defended |
| A2e cross-tenant global provider mutation | status=403 | defended |
| A2f statement body cannot select another tenant | status=400 | defended |
| A3 viewer-role key on chat | status=403 | defended |
| A4 viewer-role key on admin surface | status=403 | defended |
| A4b viewer-role key on statement reconciliation | status=403 | defended |
| A5 budget exhaustion enforced (429) | — | defended |
| A5b rate limit enforced (429) | — | defended |
| A6 cross-tenant key revoke | status=403 | defended |
| A7 secret-like text never cached | no cache marker on second call | defended |
| A8 anonymous /mcp/tools | status=401 | defended |
| A8b viewer on /mcp/tools | status=403 | defended |
| A8c unknown upstream rejected | status=400 | defended |
| A9 oversized mcp arguments rejected | code=MCP_UPSTREAM_UNKNOWN | defended |
| A10 revoked key instant invalidation | revoke=200 chat=401 | defended |
| A11 /metrics requires auth | status=401 | defended |
| A11b /metrics has no secret material | status=200 | defended |
The tool's own final line for this run was SECURITY AUDIT: ALL DEFENDED.
Read the list as a shape rather than a scoreboard: the recurring theme is tenant and role boundaries (a header carrying someone else's tenant, a viewer-role key on an admin surface, a cross-tenant cache or audit filter, a revoked key replaying), plus two things small gateways usually get wrong - what lands in the response cache when a prompt contains something secret-looking, and whether the metrics endpoint leaks material it authenticated everything else to protect.
SECTION 03 / RUN IT
Reproduce on any machine with Node
git clone --depth 1 https://github.com/happy520ai/unified-ai-system.git
cd unified-ai-system
pnpm install --frozen-lockfile
node tools/security-attack-regression.mjs
Expect one printed line per attack and the audit line at the end. No API key, no Docker, no account.
SECTION 04 / BOUNDARY
What this does not establish
- It is not a penetration test by an independent party, and not an audit. It is the project's own checklist, executed.
- It exercises the source build on one machine. It does not certify the published container, a deployment, or a cluster, and it says nothing about an installation that has enabled real providers.
- The list is exactly twenty-three checks long because that is what the file contains today. It is not exhaustive: an unlisted weakness is not excluded by a green run here.
- The numbers age. The commit and timestamp above are the version of this claim that was true when it ran; re-run it rather than trusting this page.