Skip to content

hardening(dap): DapFrameDecoder accepts unbounded Content-Length and concats per chunk #402

Description

@debugmcpdev

Problem

DapFrameDecoder (src/proxy/dap-framing.ts:39-110) accepts any finite positive Content-Length with no upper bound (:96 rejects only null/≤0/non-finite). A peer advertising a huge frame makes rawData accumulate indefinitely until the "full frame" arrives — i.e. until OOM.

Exposure:

  • Adapter side (src/proxy/minimal-dap.ts:36): a buggy or compromised debug adapter can OOM the proxy worker.
  • IDE-facing side (src/proxy/dap-mirror-server.ts:186): expose_session mirror clients are loopback + token-gated, but a malformed client (or anything that reaches the loopback port and passes auth) gets the same unbounded buffer. Defense-in-depth says the decoder itself should cap.

Secondary inefficiency: push() does Buffer.concat([this.rawData, data]) on every chunk (:49) — accumulating an N-byte frame from small chunks is O(N²) copying. Fine for typical DAP messages, pathological for large ones (huge variable payloads, base64 blobs some adapters emit).

Proposal

  • Add a maxContentLength option (generous default — e.g. 64 MB, matching the repo's existing maxBuffer: 64MB precedent in docker test utils; env-overridable if someone hits it legitimately). On violation: invoke onError with a distinct context and reset, same recovery contract as the malformed-header path.
  • Replace the per-chunk concat with a chunk list + byte count, concatenating once per completed frame (or when scanning for the header separator).
  • Property tests in this area already exist (the file header references them) — extend them with a cap-violation case and a many-small-chunks large-frame case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions