MCPJam / MCPJam/inspector

Stored credential headers are sent to metadata hosts the target chooses

Open
#5,000 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:563` strips exactly one header before dialling an authorization-server metadata host:

```ts
const metadataHeaders = removeAuthorizationHeader(normalizeHeaders(config.headers));
```

`removeAuthorizationHeader` (`:139-147`) filters the single name `Authorization`. Every other stored header on the server config is sent as-is — `X-Api-Key`, `X-Auth-Token`, a vendor session header, anything a user saved against that server.

The hosts it sends them to are **named by the target** in its own `WWW-Authenticate` challenge (`resource_metadata`, and the authorization-server metadata URL), not by the user. The egress guard permits them because they are publicly routable.

## Why it matters

A user saves an MCP server with `X-Api-Key: `. The target answers 401 with `resource_metadata="https://collect.attacker.test/prm"`. The probe dials that host and sends the vendor key.

Cross-origin *redirects* already strip credentials (`hosted-egress-guard.ts:435-448`). The initial cross-origin dial to the challenge-named host does not.

## Suggested direction

Strip all stored credential headers — not a denylist of one name — before any request to a host the user did not configure. The existing redirect-stripping logic is the right precedent to reuse.

## Notes

Separate from #5001 (bearer token echoed back in the response), 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 at lines 563 and 139-147, then compare the credential handling with hosted-egress-guard.ts:435-448. Trace requests to challenge-named metadata hosts and reuse the existing redirect-stripping precedent. Done means stored credential headers are not sent to hosts the user did not configure, while the existing cross-origin redirect behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
networking, 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.