Skip to content

interop/v1: pin a cross-SDK collection-size bound for interop values (element caps currently SDK-local) #20

Description

@27Bslash6

Surfaced by the LAB-247 review panels on cachekit-ts PR 71 (one reviewer read the TS decode cap as breaking the array32/map32 tier for cross-SDK reads; another read it as a legitimate DoS bound — both are right, which is why this needs a spec decision, not an SDK-local one).

Facts

  • The spec's canonical-encoding ladder makes the *32 tier (>= 65 536 elements) normative for encoders, but the spec is silent on what element counts a reader must accept.
  • cachekit-ts (PR 71) bounds interop decode at 10 000 elements per collection (maxArrayLength/maxMapLength), symmetric with its encoder cap and its existing auto-mode maxCollectionSize. Rationale: @msgpack/msgpack preallocates arrays from headers (new Array(size)) with a default cap of UINT32_MAX, so a 5-byte forged array32 header is a multi-GB allocation without an explicit bound.
  • msgpack-python defaults are payload-proportional (max_array_len=-1 since v1.0) — a 20 000-element array in a ~60 KB payload decodes fine with defaults, and nothing stops a Python writer producing it.
  • rmp-serde deserializes sequences incrementally with serde's cautious size-hint capping — no hard element cap, effectively bounded by input size.
  • Neither the Python (LAB-245) nor Rust (LAB-246) interop implementation exists yet, so there is no live inconsistency — this is the cheap moment to pin the rule before there is.

The gap: once py/rs ship with their libraries' natural behaviour, a Python-written 20 000-element interop value (well under any byte cap) fails on TypeScript read. Per-SDK caps that differ = cross-SDK read failures that look like data loss.

Options

  1. Pin a minimum element count interop readers MUST accept (e.g. 65 536, making the *16 tier fully portable and *32 explicitly best-effort), leaving DoS protection to byte-size caps.
  2. Pin a shared maximum (writers MUST NOT exceed N elements per collection; readers MAY reject above N) — makes today's TS 10 000 the de facto N if chosen.
  3. Declare caps SDK-local and document per-SDK limits in the feature matrix (weakest; keeps the silent-failure class).

The real DoS variable is bytes, not elements — element caps only exist because some decoders preallocate from headers. That argues for option 1 with a normative note that readers must not preallocate from untrusted headers.

cachekit-ts keeps its 10 000 bound until this is decided; the py/rs implementation issues should link here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions