SSRF guard re-resolves DNS at connect time, so rebinding is still possible
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- node.js, typescript
- Ambito
- backend, networking, security
Direzione di ricerca
Start with src/net/ssrf.ts and trace how its lookup, fetchImpl, and redirect handling work; then read the existing tests that exercise those injectable dependencies. Run those tests before making changes. Done means the connected address is one that was validated, TLS verification and redirect checks remain intact, the injections still work, a rebinding test passes, and the module comment accurately states the guarantee.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Follow-up to #407, which was closed by #488. That PR is a thorough guard and removed the whole easy attack surface — this is the residue it deliberately left.
Not a Wave issue right now. The repo's Wave budget for this round is exhausted, so this is filed for tracking rather than for points. It will be labelled for the Wave when the next round opens.
The gap
src/net/ssrf.ts validates and then fetches:
let url = await assertUrlSafe(target, opts)
const response = await fetchImpl(url.toString(), { ...init, redirect: 'manual' })
assertUrlSafe resolves the hostname and checks every returned address. fetchImpl is then given the hostname, and Node resolves it again when it opens the connection.
An attacker who controls a DNS zone can serve a short-TTL record that answers the first query with a public address and the second with 169.254.169.254. The check passes, the connection goes somewhere else. This is DNS rebinding, and it is the specific thing a post-resolution check is otherwise meant to defeat.
It matters here because the MCP server takes its target URL from an agent, and agents routinely read attacker-influenced text.
What to build
Pin the connection to an address that was actually validated.
- An undici dispatcher with a custom
connectorlookupis the usual route: resolve once, validate, and hand the chosen address to the connector so no second resolution happens. - Or connect by IP with the
Hostheader preserved — be careful, this breaks TLS SNI and certificate verification unlessservernameis set explicitly, so it is not the simpler option it appears to be. - Re-validate on every redirect hop, as the current code already does.
- The existing injectable
lookupandfetchImplshould stay injectable, because that is what makes the current tests possible.
Also
Correct the module comment. It currently reads:
to decide that after resolving the hostname, because a public-looking name can resolve to a private address — the classic way this check is bypassed.
True of a static name, not of an attacker-controlled one. Say plainly that connect-time resolution is not yet pinned, so nobody reads it as a guarantee it does not make.
Acceptance criteria
- The address connected to is one that was validated
- A test proves a hostname resolving differently on the second lookup does not reach the second address
- TLS verification still works against the original hostname
- Redirect hops remain validated
-
lookupandfetchImplstay injectable and the existing tests still pass - The module comment states what is and is not guaranteed
- Lingua principale
- TypeScript
- Stelle
- 4
- Fork
- 71
- Merge medio
- 1g 9h
- PR unite (30g)
- 46
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Divinity-Labs/Lens
-
Webhook retries have no jitter, so failures synchroniseForse già presa @Richard-tobi l’ha presa 2 giorni fa. Apertaarea:reliability difficulty:easy help wanted points:100 Stellar Wave
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
Divinity-Labs/Lens#341 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
area:security difficulty:easy help wanted points:100
Difficoltà 4/5 3-5 giorni Idoneità per principianti 58/100
Divinity-Labs/Lens#514 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
area:api-quality difficulty:intermediate help wanted points:150
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
Divinity-Labs/Lens#513 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
The key is accepted only as a bearer token, and nothing says soForse già presa @krsnak l’ha presa 1 giorno fa. Apertaarea:docs difficulty:easy help wanted points:100 Stellar Wave
Divinity-Labs/Lens#512 · 3 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
A 401 says the same thing for four different problemsForse già presa @Kingsley4867 l’ha presa oggi. Apertaarea:api-quality difficulty:easy help wanted points:100 Stellar Wave
Divinity-Labs/Lens#511 · 6 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di Divinity-Labs/Lens
Issue simili
-
"Contains" page watch never matches when its text has a trailing spaceForse già presa @RaphaelFakhri l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
CopilotKit/openmuse#184 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
bootstrap-vue-next/bootstrap-vue-next#3357 ·
I maintainer di solito rispondono entro 1 giorno
-
[quality] tide.ts: six mutation survivors in the merge-queue gate, draft refusal, fork-403 workflow-file diagnosis and getPull's fork flag are unpinned by any testForse già presa @hivecommons-hive l’ha presa oggi. Apertaagent/quality needs-kind stage/040-covered-by-pr testing
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
cncf/prow-github-actions#517 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
Unsampled pageload span is profiled when profileLifecycle is 'trace' (browser UI profiling)Forse già presa @Jxxunnn l’ha presa oggi. ApertaBrowser Waiting for: Product Owner
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
getsentry/sentry-javascript#25497 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno