bug(envd): PostInit reads request body with io.ReadAll and no size limit, enabling OOM via oversized payload
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 76/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Tranquilla
- Stack tecnologico
- go
- Ambito
- backend-api-design, security
Direzione di ricerca
Inizia in packages/envd/internal/api/init.go, in PostInit, e verifica come viene letto il corpo della richiesta /init prima dell’autenticazione. Conferma il completamento quando i body sovradimensionati vengono rifiutati con la risposta di errore indicata, mentre i payload legittimi di EnvVars e CaBundle continuano a funzionare e il comportamento esistente di eliminazione dei token rimane coperto.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
PostInit in packages/envd/internal/api/init.go reads the request body with an unbounded io.ReadAll:
// packages/envd/internal/api/init.go ~L141
body, err := io.ReadAll(r.Body) // no MaxBytesReader
defer memguard.WipeBytes(body)
Any process inside the VM that can reach the envd HTTP port can send an arbitrarily large body, allocating heap memory until envd is OOM-killed.
Why it matters
envd is the sandbox control plane — it manages file I/O, process execution, cgroup freezing, NFS mounts, and live-upgrade handover. An OOM kill of envd:
- leaves all user processes running but orphaned (no envd to receive commands)
- prevents graceful sandbox teardown (cleanup callbacks, slot release)
- breaks any in-progress pause/resume sequence, potentially corrupting snapshot state
The /init endpoint is excluded from authExcludedPaths but does accept unauthenticated bodies — the auth check happens after the body is fully read. A guest process (e.g. user code running inside the sandbox) that discovers the envd port can therefore trigger OOM without any credentials.
Secondary issue: memguard.WipeBytes security value is reduced
memguard.WipeBytes(body) is deferred to scrub the access token from heap memory. But if body contains the token and is first replicated into a large allocation (e.g. a 500 MiB body), Go's allocator may have already copied the slice header or the GC may have paged parts to disk before the wipe runs. Capping the body to a size where the entire buffer fits comfortably in memory preserves the intent of the wipe.
Fix
Wrap r.Body with http.MaxBytesReader before reading. The largest legitimate /init payload contains EnvVars (many vars) and CaBundle (multiple PEM certs); 1 MiB is a generous upper bound that no real orchestrator payload will approach:
if r.Body != nil {
// Cap body to 1 MiB. /init carries credentials and CA bundles but no
// bulk data. An unbounded io.ReadAll lets a guest process OOM envd,
// the sandbox control plane, by sending an oversized body.
r.Body = http.MaxBytesReader(w, r.Body, 1<<20)
body, err := io.ReadAll(r.Body)
defer memguard.WipeBytes(body)
if err != nil {
var maxErr *http.MaxBytesError
if errors.As(err, &maxErr) {
logger.Error().Msg("request body exceeds 1 MiB limit")
w.WriteHeader(http.StatusRequestEntityTooLarge)
} else {
logger.Error().Msgf("Failed to read request body: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
return
}
...
No changes needed to imports (errors, io, net/http are all already imported).
Severity
Medium. The envd HTTP port is not externally exposed; exploitation requires code execution inside the VM. However sandboxes are explicitly designed to run untrusted LLM-generated code, so "arbitrary code inside the VM" is the normal threat model, not an unusual escalation.
- Lingua principale
- Go
- Stelle
- 1.6k
- Fork
- 438
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Apri 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 e2b-dev/runtime
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
sandbox cache: StartRemoving state transition not broadcast, all allocations see stale Running state Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 86/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
Tutte le issue di e2b-dev/runtime
Issue simili
-
kind/bug needs-triage
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 72/100
matrixorigin/matrixone#29223 ·
-
needs-acceptance wg/data-plane-networking
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
vllm-project/semantic-router#4024 · 1 commento ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
alexgorbatchev/dotfiles#107 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 84/100