DCR initialAccessToken fails open: an unresolved ${VAR} placeholder becomes the bearer secret, an empty value opens registration
Maintainers usually reply within 6 days
@heskew is already working on this.
Since Oct 1, 2026.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- api, authentication, security
Research direction
Start with src/lib/mcp/dcr.ts, especially checkInitialAccessToken and the warning, then read src/lib/config.ts around expandEnvVar and the placeholder regex. Verify the behavior for unresolved and empty declared values, while preserving open registration only when the key is omitted; run the relevant test suite if available.
Written by the indexing model from the issue text.
Description
What happens
mcp.dynamicClientRegistration.initialAccessToken is the gate on POST /oauth/mcp/register (RFC 7591 Dynamic Client Registration). Two misconfigurations turn it into no gate:
- Unset env var.
initialAccessToken: ${DCR_TOKEN}withDCR_TOKENunset reachescheckInitialAccessTokenas the literal string${DCR_TOKEN}—expandEnvVarkeeps an unresolved placeholder as-is (src/lib/config.ts~L25-34) — and that literal is then the accepted bearer value. Anyone who can read the app's config (placeholders are routinely committed) can register clients. Nothing is logged. - Set but empty.
initialAccessToken: ""(or an env var set to empty) hitsif (!configured) return null(src/lib/mcp/dcr.ts~L39-41): open registration, with a once-per-process warning (dcr.ts~L229-234) whose wording describes the legitimate RFC 7591 open mode, so it reads as intentional.
Verified by reading main @ 92ab477; not executed.
Why it matters
#182 closed "absent dynamicClientRegistration block ⇒ open registration". These two shapes reopen it on an operator mistake that the docs' own ${VAR} convention makes likely (an env var missing on one host). Registration alone does not grant tokens — a user still has to authorize the registered client — so this is a consent-phishing surface, not a direct token bypass. It is still a security gate failing open, silently in the placeholder case.
Expected
The fail-closed rule from #236 (mcp.signingKeyPem) and #238 (redirectUri): a declared value that is an unresolved ${…} placeholder or empty throws at boot naming the key. Open registration remains available only by omitting the key. src/lib/config.ts already carries the placeholder regex (~L94) and #236/#238 each add a copy — one shared isUnresolvedEnvPlaceholder() helper is the natural home once the second of those lands.
Scope
Only deployments that enable DCR (a deprecated compat path since 2026-07-28; CIMD is primary) and misconfigure the token. clientId/clientSecret placeholders expand the same way but fail at the IdP, so they are out of scope here.
Found during the cross-model review round on #236.
- Dominant language
- JavaScript
- Stars
- 1
- Forks
- 3
- Avg merge
- 3d 21h
- Merged PRs (30d)
- 10
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from HarperFast/oauth
-
2.5.0: unresolved env placeholder on an mcp boolean gate now drops to its default (behavior change not in CHANGELOG)Possibly taken @heskew claimed this 1 day ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 82/100
HarperFast/oauth#207 · 1 assignee ·
Maintainers usually reply within 6 days
-
Validate resource at the token endpoint for the authorization_code and refresh_token grantsPossibly taken @heskew claimed this today. Open
HarperFast/oauth#250 · 1 assignee ·
Maintainers usually reply within 6 days
-
A declared redirect-host allowlist that resolves empty means no restrictionPossibly taken @heskew claimed this today. Open
HarperFast/oauth#249 · 1 assignee ·
Maintainers usually reply within 6 days
-
TenantManager.registerTenant: additionalConfig with scope: undefined wipes the preset scope (#243 bug class, multi-tenant path)Possibly taken @heskew claimed this today. Open
HarperFast/oauth#248 · 1 assignee ·
Maintainers usually reply within 6 days
-
Difficulty 3/5 1-2 days Newbie friendliness 70/100
HarperFast/oauth#244 · 2 comments · 1 assignee ·
Maintainers usually reply within 6 days
All issues in HarperFast/oauth
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
daisy/a11y-meta-viewer#18 ·
-
good first issue status: needs triaging type: bug version: 2.0
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
medusajs/medusa#17094 · 2 comments ·
Maintainers usually reply within 1 day
-
browser: chrome package: @carbon/react package: styles
Difficulty 1/5 Under an hour Newbie friendliness 92/100
carbon-design-system/carbon#23567 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
clerk/javascript#10033 ·
Maintainers usually reply within 1 day
-
bug client p1
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
vercel/eve#4173 · 2 comments ·
Maintainers usually reply within 1 day