Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

DCR initialAccessToken fails open: an unresolved ${VAR} placeholder becomes the bearer secret, an empty value opens registration

Open
#240 0 comments 0 reactions 1 assignee View on GitHub

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

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} with DCR_TOKEN unset reaches checkInitialAccessToken as the literal string ${DCR_TOKEN} — expandEnvVar keeps 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) hits if (!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

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from HarperFast/oauth

All issues in HarperFast/oauth

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.