atis.http.* reads the entire HTTP response body into memory with no size limit and no default timeout #200

Closed
opened 2026-09-26 18:36:25 +00:00 by advisor-bot · 0 comments
Owner

Description

httpReq (the shared implementation behind atis.http.get/post/put/patch/delete) reads the whole response body via body, err := io.ReadAll(resp.Body) with no upper bound whatsoever. The http.Client used for these calls is http.DefaultClient (assigned directly in NewAtisRuntime), whose Timeout is the zero value (no timeout) unless a script explicitly calls atis.http.set_timeout(...) beforehand. There is no equivalent here of the size/count guard rails the project already added elsewhere for archive extraction (atis.misc.unzip_targz's maxCount / maxSize parameters).

Location

  • internal/atis/http.go, function httpReq, the body, err := io.ReadAll(resp.Body) call (~line 155)
  • internal/atis/atis.go, client construction: httpClient: http.DefaultClient (~line 53)

Risk

Any script that calls atis.http.get/post/etc. against an untrusted, misbehaving, or compromised endpoint — or simply one that returns an unexpectedly large response — will have the entire response body buffered into process memory in one call, with no cap. This is a straightforward memory-exhaustion vector (up to an OOM kill of the process/host) for any automation that fetches a URL influenced by external input, e.g. a webhook payload, a value read from a config/manifest file, or a redirect/response from a third-party API. Because the client has no default timeout either, a slow or stalled peer can also hang the call indefinitely, tying up an automation run with no bound. This is the same general class of "unbounded resource consumption from untrusted input" that the project already treated as worth a dedicated fix for archive extraction, but the HTTP path has no equivalent protection today.

Advice for fix

Wrap resp.Body in a bounded reader (e.g. io.LimitReader or an http.MaxBytesReader-style approach) with a sane default maximum response size, ideally exposed as a configurable parameter similar to unzip_targz's maxSize. Also set a sensible default Timeout on the HTTP client at construction time instead of leaving it at Go's zero value ("no timeout") until a script opts in via set_timeout.

**Description** `httpReq` (the shared implementation behind `atis.http.get/post/put/patch/delete`) reads the whole response body via `body, err := io.ReadAll(resp.Body)` with no upper bound whatsoever. The `http.Client` used for these calls is `http.DefaultClient` (assigned directly in `NewAtisRuntime`), whose `Timeout` is the zero value (no timeout) unless a script explicitly calls `atis.http.set_timeout(...)` beforehand. There is no equivalent here of the size/count guard rails the project already added elsewhere for archive extraction (`atis.misc.unzip_targz`'s `maxCount` / `maxSize` parameters). **Location** - `internal/atis/http.go`, function `httpReq`, the `body, err := io.ReadAll(resp.Body)` call (~line 155) - `internal/atis/atis.go`, client construction: `httpClient: http.DefaultClient` (~line 53) **Risk** Any script that calls `atis.http.get`/`post`/etc. against an untrusted, misbehaving, or compromised endpoint — or simply one that returns an unexpectedly large response — will have the entire response body buffered into process memory in one call, with no cap. This is a straightforward memory-exhaustion vector (up to an OOM kill of the process/host) for any automation that fetches a URL influenced by external input, e.g. a webhook payload, a value read from a config/manifest file, or a redirect/response from a third-party API. Because the client has no default timeout either, a slow or stalled peer can also hang the call indefinitely, tying up an automation run with no bound. This is the same general class of "unbounded resource consumption from untrusted input" that the project already treated as worth a dedicated fix for archive extraction, but the HTTP path has no equivalent protection today. **Advice for fix** Wrap `resp.Body` in a bounded reader (e.g. `io.LimitReader` or an `http.MaxBytesReader`-style approach) with a sane default maximum response size, ideally exposed as a configurable parameter similar to `unzip_targz`'s `maxSize`. Also set a sensible default `Timeout` on the HTTP client at construction time instead of leaving it at Go's zero value ("no timeout") until a script opts in via `set_timeout`.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pandora/atis#200
No description provided.