Skip to content

fix(reliability): preflight converter payload allocations - #160

Draft
seonghobae wants to merge 100 commits into
mainfrom
fix/blob-size-preflight-20260811
Draft

fix(reliability): preflight converter payload allocations#160
seonghobae wants to merge 100 commits into
mainfrom
fix/blob-size-preflight-20260811

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Closes #159.
Closes #306.
Closes #307.
Closes #308.
Closes #316.
Closes #324.
Closes #334.
Closes #335.
Closes #345.
Closes #363.
Closes #364.
Closes #369.

Current boundary

Protected shipped truth remains exact main@3b38ead2d00f44eb578d0689087b9293b3dabe1e. Current exact Draft head is 42b3a5004ec1b93181cd1ae52227b0fac2506227 on fix/blob-size-preflight-20260811. GitHub reports the Draft mechanically mergeable; mergeability is not authorization.

This lane is the canonical single writer for framework-neutral converter hardening under src/converter/. It adds no network, persistence, credentials, tenancy, model/provider, deployment, retention, migration, authorization, or durable-audit authority.

Implemented contract

The branch retains Blob/File pre-read guards, canonical and WHATWG-forgiving base64 predecode accounting, strict maxBytes validation, descriptor-safe runtime options, intrinsic typed-array/Blob slot validation, bounded MIME metadata, stable payload-redacted parse/size failures, deterministic Node/browser behavior, and standalone no-service operation.

Current active-PR behavior additionally:

  • preserves data-URI payload text exactly after the comma while retaining accepted leading-input whitespace compatibility;
  • recognizes the RFC 2397 ;base64 encoding marker only when it is the exact final marker, so a media-type parameter such as ;base64=1 is not misclassified as base64 encoding;
  • decodes non-base64 %XX escapes as raw octets, including %80%FF, rather than routing them through UTF-8 URI-component decoding;
  • preserves unescaped Unicode string input as UTF-8, matching TextEncoder lone-surrogate replacement semantics;
  • computes exact non-base64 decoded byte length before output allocation and applies maxBytes to that exact length;
  • recognizes accepted leading data-URI whitespace directly in the parser grammar instead of first materializing a trimStart() copy of attacker-controlled input;
  • bounds declared data-URI MIME metadata to 1,024 UTF-16 code units before payload decoding, matching the existing explicit/Blob MIME resource ceiling while preserving the exact 1,024 boundary and omitted-declaration text/plain default;
  • classifies genuine Uint8Array values through captured intrinsic TypedArray brand/slot capabilities rather than instanceof;
  • classifies ArrayBuffer views through a module-captured ArrayBuffer.isView;
  • obtains Blob size and MIME metadata through intrinsic platform getters after genuine Blob-slot validation;
  • reads Blob payload bytes through a platform Blob.prototype.arrayBuffer method captured at module evaluation while preserving fallback selection;
  • captures the TextDecoder instance and intrinsic decode method at module evaluation for SVG/XML MIME sniffing; and
  • makes the Node/browser base64 startup branch measurable rather than coverage-suppressed while keeping the exported test seam declaration structural/browser-portable and retaining internally captured Node Buffer.from authority.

Latest test-first lineage

Earlier RED→GREEN lineages for #159, #306, #307, #308, #316, #324, #334, #335, #345, #363 and #364 remain historical behavior lineage only. No predecessor workflow/review evidence transfers to the current head.

Latest declared data-URI MIME resource-bound lineage:

  • test-only RED 5321c9dede813e88b7474b165a3ea8431fc34104, CI 32558481749, build/test 96996286302, proved that a 1,025-code-unit declared MIME with malformed %GG reached payload decoding and failed as malformed percent-encoding instead of being rejected at the metadata boundary; the exact 1,024 boundary and omitted-declaration default assertions passed;
  • current narrow repair 42b3a5004ec1b93181cd1ae52227b0fac2506227 reuses MAX_MIME_TYPE_CODE_UNITS in parseDataUri() before payload handling, with the dedicated boundary/default regression corpus green.

The preceding #369 false-green/package-contract lineage remains behavior history only: RED 1754029885c90980c58892af37a24b789a68bdc7 / CI 32473354959 / build-test 96744578570 exposed the removed browser-startup coverage path; first repair 1b5d037b4c97d8fc0c77a97197e65ee59fc111be correctly failed strict packed-consumer TypeScript because its generated declaration leaked Node-only globalThis.Buffer; repair ecbf842fdf131782cd28fd72a888b1d6d96a341b restored a structural/browser-portable test-seam declaration while retaining captured Node authority.

The preceding MIME-classifier-authority lineage also remains behavior history only: RED 07da81a11f29514dc5f44976adbcab699a21080e / CI 32262431173 / job 96098633176 proved a later hostile global TextDecoder replacement could escape the public MIME-sniff boundary; GREEN 30d5e4f6a984f26153f4a1535f306553887cf5c5 captured the trusted decoder capability.

Exact-current-head evidence

For unchanged exact head 42b3a5004ec1b93181cd1ae52227b0fac2506227 against protected base 3b38ead2d00f44eb578d0689087b9293b3dabe1e at the latest fresh refetch:

  • CI 32558675130: completed / success;
  • build-and-test 96996743975: checkout explicitly bound to 42b3a5004ec1b93181cd1ae52227b0fac2506227, 163 test files / 912 tests, 100% statements / branches / functions / lines, including src/converter/base64.ts and src/converter/base64DataUriMimeMetadata.test.ts;
  • packed-package ESM/CommonJS/subpath/strict-TypeScript consumers, library build and demo build: completed / success;
  • Cross-engine Clipboard / Playwright 1.62.0: completed / success;
  • Office Python 3.11, 3.12, 3.13 and 3.14: completed / success;
  • Security Scan 32558675113: completed / success;
  • SAST Semgrep 32558675118: completed / success;
  • formal submitted reviews: 0;
  • unresolved inline review threads: 0.

All observed repository-owned exact-current-head workflow generations are terminal success. Repository technical success does not substitute for separately applicable central workflows, qualifying independent approval, or then-live governance. Pending, queued, skipped, cancelled, absent, neutral, failed, stale, predecessor, status-only, model-only, or vacuous evidence remains non-passing.

Integration boundary

Keep this PR Draft and unmerged while #118 owns the frozen protected v0.6.0 publication/provenance identity and while qualifying independent approval plus every then-applicable governance/workflow gate remain incomplete. Before any lifecycle action, refetch exact head/live base, ancestry/mergeability, formal reviews/threads, live rules/permissions and every applicable repository/central workflow. Never self-approve, weaken gates, transfer predecessor evidence, force-push, destructively rebase, or synthesize release identity.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae seonghobae changed the title fix(reliability): reject oversized Blob inputs before reading fix(reliability): preflight converter payload allocations Aug 11, 2026
@opencode-agent opencode-agent Bot added priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior labels Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment