MCPJam / MCPJam/inspector

The hosted doctor echoes the stored bearer token back in its own response

Open
#5,001 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2.2k
Forks
283
Avg merge
11h 47m
Merged PRs (30d)
737

Description

Found during the review of #4884 (MJ-001 redaction). Out of scope for that PR, deliberately left for its own ticket. Not covered by anything merged.

## What happens

`sdk/src/server-probe.ts:501-513` builds the initialize attempt with the stored token on it:

```ts
if (accessToken) { headers.Authorization = `Bearer ${accessToken}`; }
return { name: "streamable_initialize", request: { method: "POST", url: config.url, headers, … } };
```

That `headers` object is stored on the attempt and ships to the caller inside `transport.attempts[].request.headers`. The token comes from server-side storage (`routes/web/servers.ts:224`, `auth.ts:958-964`), not from the caller's own request. The redactor added in #4884 rewrites `error.message`, `connection.detail`, `checks[].detail` and now `error.code` and `durationMs` — it does not touch `request.headers`.

## Why it matters

The caller is authorized for that server, so this is not a cross-tenant leak. It is a needless echo that puts a live OAuth access token into a JSON response body, which then reaches:

- browser memory and devtools
- HAR exports
- any support bundle or ticket a user pastes it into

A token that never had to leave the server is now in several places nobody is tracking.

## Suggested direction

Redact `Authorization` (and any other credential-shaped header) out of `attempts[].request.headers` unconditionally, hosted or not. The attempt record is for diagnosing the request shape; the secret value carries no diagnostic weight.

## Notes

Separate from #5000 (credential headers egressing to target-chosen metadata hosts), though both live on the same probe path.

Not a pentest finding. Reported here so it is tracked rather than sitting only in the review write-up.

Contributor guide

Open the contributing guide

Research direction

Start in sdk/src/server-probe.ts:501-513 and trace how the stored token enters the attempt record and reaches the response. Review routes/web/servers.ts:224 and auth.ts:958-964 for the token source, then inspect existing probe coverage if available. Done means credential values, including Authorization, are absent from attempts[].request.headers while the request shape remains diagnosable.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.