Skip to content

Commit 8c61acd

Browse files
committed
docs: add security disclosure policy
1 parent dffc895 commit 8c61acd

1 file changed

Lines changed: 190 additions & 0 deletions

File tree

SECURITY.md

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# Security Policy
2+
3+
`mcp-auth-proxy` sits on the authorization path between MCP clients
4+
and a private MCP server. Vulnerabilities here can let an attacker
5+
mint tokens, impersonate users, exfiltrate identity material, or
6+
deny service. We take reports seriously and want to make it as easy
7+
as possible to disclose responsibly.
8+
9+
## Reporting a vulnerability
10+
11+
**Please do not open public GitHub issues for security problems.**
12+
13+
Report privately via **GitHub Security Advisory**:
14+
<https://github.com/babs/mcp-auth-proxy/security/advisories/new>
15+
16+
This opens a confidential thread with the maintainers and gives us
17+
a place to coordinate the fix, CVE assignment, and the eventual
18+
public advisory.
19+
20+
We acknowledge new reports within **3 business days**. If you do not
21+
hear back within that window, please post a brief, *non-sensitive*
22+
nudge on the advisory thread — GitHub notification settings
23+
occasionally lose the initial ping.
24+
25+
### What to include
26+
27+
A useful report typically contains:
28+
29+
- Affected version or commit hash (`git rev-parse HEAD` from your
30+
local checkout, or the image digest if you deployed a release).
31+
- Reproduction steps or a minimal proof-of-concept. Curl commands
32+
are ideal; screenshots are acceptable.
33+
- The configuration that triggers the issue — env vars, IdP type,
34+
whether Redis is enabled, `PROD_MODE`, `RENDER_CONSENT_PAGE`,
35+
`PKCE_REQUIRED`, `TRUSTED_PROXY_CIDRS`, etc.
36+
- Expected vs. observed behavior, and the security impact you
37+
believe this enables (e.g. token theft, account takeover, SSRF,
38+
bypass of `ALLOWED_GROUPS`).
39+
- Any relevant log snippets (redact bearer tokens, authorization
40+
codes, refresh tokens, and `id_token` values before sending).
41+
42+
If you are not sure whether something is a vulnerability, send the
43+
report anyway — we would rather triage a non-issue than miss a real
44+
one.
45+
46+
## Supported versions
47+
48+
Security fixes are issued against the latest released minor version
49+
on `master`. Older versions do not receive backports.
50+
51+
| Version | Supported |
52+
|---------|-----------|
53+
| `v1.x` (latest minor) ||
54+
| `< v1.0` (pre-release) ||
55+
56+
The container images at
57+
`ghcr.io/babs/mcp-auth-proxy` follow the same support window. When a
58+
security fix lands, we publish a new patch tag (`v1.x.y`) and update
59+
the `:v1` floating tag.
60+
61+
## Coordinated disclosure timeline
62+
63+
Our default disclosure model is a **90-day** window from the date we
64+
acknowledge the report:
65+
66+
- **Day 0** — report received, acknowledgement sent.
67+
- **Day 0–7** — triage, severity scoring (CVSS v3.1), reproduction.
68+
- **Day 7–60** — fix developed in a private branch or security
69+
advisory fork; reviewed; tests added under `handlers/*_test.go`,
70+
`replay/*_test.go`, or a new e2e case.
71+
- **Day 60–90** — coordinated release: patch tag, image rebuild,
72+
public advisory, credit, optional CVE.
73+
74+
We are willing to extend the window if a fix requires upstream
75+
changes (Go stdlib, IdP, Redis client) or if you ask us to hold for
76+
your own coordinated rollout.
77+
78+
If the issue is already being actively exploited in the wild, we
79+
will accelerate the timeline and may publish the fix and advisory
80+
together.
81+
82+
## Scope
83+
84+
In scope — anything that can be reached by traffic going through the
85+
proxy:
86+
87+
- OAuth 2.1 endpoints: `/authorize`, `/token`, `/register`,
88+
`/consent`, `/callback`.
89+
- Discovery: `/.well-known/oauth-authorization-server`,
90+
`/.well-known/oauth-protected-resource[/<mount>]`.
91+
- The MCP pass-through path: `/mcp` (and any configured mount).
92+
- Token sealing / verification in the `token/` package.
93+
- Replay / single-use enforcement in the `replay/` package.
94+
- Authorization middleware in `middleware/auth.go`.
95+
- Configuration validation in `config/config.go`, especially flags
96+
that can weaken a control when set (`PROD_MODE`,
97+
`TRUSTED_PROXY_CIDRS`, `PKCE_REQUIRED`, `RENDER_CONSENT_PAGE`,
98+
`REDIS_REQUIRED`).
99+
- Container image hygiene (`Dockerfile`), supply chain (`go.sum`).
100+
- Metrics endpoint information disclosure (`/metrics`).
101+
102+
The [threat model](docs/threat-model.md) lists the specific threats
103+
we already mitigate and which code, tests, and runbooks back them.
104+
105+
Out of scope — documented, accepted residual risk (see the
106+
"Out of scope" section in `docs/threat-model.md` for the full
107+
discussion):
108+
109+
- **IdP compromise.** If the configured OIDC IdP is compromised, the
110+
proxy trusts what the IdP says. Bug reports about Keycloak, Entra,
111+
Auth0, Okta, etc. belong with those vendors.
112+
- **Backend MCP server vulnerabilities.** The proxy forwards
113+
authenticated traffic; it does not sanitize JSON-RPC payloads to
114+
the upstream MCP server beyond what is required for transport.
115+
- **Browser-engine bugs.** The consent page is JS-free and
116+
CSP-locked (`default-src 'none'`); we do not separately defend
117+
against escapes of the browser's contextual HTML escaping.
118+
- **Denial of service via raw network capacity.** Per-IP rate limits
119+
protect specific endpoints; absorbing volumetric L3/L4 floods is
120+
the deployment operator's responsibility (CDN, WAF, k8s ingress).
121+
- **Misconfiguration where the operator explicitly opted out** of a
122+
control (e.g. `RENDER_CONSENT_PAGE=false`, `PKCE_REQUIRED=false`,
123+
`REDIS_REQUIRED=false`). These flags exist for compatibility; the
124+
associated weakening is intentional. We will still accept reports
125+
about additional weaknesses they expose beyond the documented
126+
trade-off.
127+
- **Social engineering and physical attacks** against operators,
128+
maintainers, or end users.
129+
130+
If you are unsure whether a finding is in scope, send it anyway — we
131+
will tell you, and we will treat the conversation as confidential.
132+
133+
## Safe harbor
134+
135+
We will not pursue or support legal action against researchers who:
136+
137+
- Make a good-faith effort to comply with this policy.
138+
- Avoid privacy violations, destruction of data, or interruption of
139+
service for users other than themselves.
140+
- Do not exploit a discovered vulnerability beyond the minimum
141+
necessary to demonstrate impact.
142+
- Give us reasonable time to fix the issue before public disclosure.
143+
- Do not extort, threaten, or attempt to monetize the finding
144+
outside of the recognition described below.
145+
146+
Testing against your own deployment of the proxy is always allowed.
147+
Testing against deployments you do not control requires the
148+
operator's permission — the demo stack at `docker-compose.yml` and
149+
the Keycloak fixtures are explicitly available for this purpose.
150+
151+
## Recognition
152+
153+
We are happy to credit reporters in:
154+
155+
- The public GitHub Security Advisory.
156+
- The CHANGELOG entry for the fix release.
157+
- An optional "Security acknowledgements" section in the README,
158+
added when the first credited report ships.
159+
160+
If you prefer to stay anonymous, we will honor that.
161+
162+
There is no monetary bounty program at this time.
163+
164+
## Cryptographic verification (optional)
165+
166+
The container images at `ghcr.io/babs/mcp-auth-proxy` are built by
167+
GitHub Actions; the build is reproducible from the tagged commit
168+
(`docs/release-checklist.md` documents the procedure). If you need
169+
to verify a binary against the source, build from the same tag with
170+
the same Go toolchain and compare hashes.
171+
172+
We do not currently sign releases with a long-lived PGP key. The
173+
GitHub Security Advisory channel is already an encrypted,
174+
authenticated transport — please use it for sensitive material
175+
rather than email.
176+
177+
## Companion documents
178+
179+
- [`docs/threat-model.md`](docs/threat-model.md) — STRIDE coverage
180+
matrix mapping threats to code, tests, and runbooks. The
181+
authoritative list of what we already defend against.
182+
- [`docs/conformance.md`](docs/conformance.md) — RFCs the proxy
183+
claims to implement, with code and test evidence. Useful when
184+
scoping whether a report is a spec deviation or a vulnerability.
185+
- [`docs/configuration.md`](docs/configuration.md) — every
186+
configuration flag, its default, and the security trade-off if
187+
changed.
188+
- [`docs/runbooks/`](docs/runbooks/) — operational responses to
189+
security-relevant incidents (Redis outage, IdP outage, key
190+
rotation, consent-denial spikes, bulk revocation).

0 commit comments

Comments
 (0)