Skip to content

fix(reliability): preflight clipboard size and traversal budget - #359

Draft
cursor[bot] wants to merge 19 commits into
fix/clipboard-hostile-throw-349from
cursor/bc-9fd6356f-8539-49e9-9129-02a28cd4a490-7e7b
Draft

fix(reliability): preflight clipboard size and traversal budget#359
cursor[bot] wants to merge 19 commits into
fix/clipboard-hostile-throw-349from
cursor/bc-9fd6356f-8539-49e9-9129-02a28cd4a490-7e7b

Conversation

@cursor

@cursor cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown

Closes #163.
Closes #327.

Scope and stack ownership

This Draft is the canonical SafeClipboard resource-preflight owner: reject obviously oversized strings before UTF-8 allocation and enforce visited+queued+enqueueable node capacity before child materialization. It preserves deterministic allowlist reconstruction, source order, hidden-subtree rules, fail-closed errors and actionable redacted customer guidance. Hostile thrown-value containment remains with prerequisite #351; its source is inherited through the existing stack, not duplicated.

Protected implementation authority remains main@0b88c16f14f51b54a87eb7164f0edfb06dd60902. The live base is fix/clipboard-hostile-throw-349 at cff066f0c3a0b61d7d0964b7d5642402b732420f (Draft #351). Candidate 36037015e3715d9c1590438bafde888d62487f86 normally descends from remote predecessor bb3187ce98f0769d1d6b08ceebb7e829d9f1f951. No force/amend/reset, ownership change, dependency change, new public API, altered limits, or weakened deadlines/coverage thresholds.

Accepted-child list reuse — 2026-09-07

Test-first 9061addbfec9d3880f6e5daac31fc1364cbf57cf reproduced4 childNodes getter reads for a three-child fragment (1failed/1passed, exact output unchanged). ea65e3bf0776646f83aaf7c27b156cd6697174be adds one local reference in the shared enqueue function, preserving the existing capacity check before item reads and reverse-order stack traversal. The regression now requires1 getter read. 1ca6ed3c records the Proposed result and limitations in the existing doctoring record.

The DOM Standard defines childNodes as a SameObject NodeList attribute; reusing its live native reference does not make a copied document snapshot or a new cache. WHATWG DOM. This proves reduced property access, not a measured buyer-latency improvement or the cause of earlier Word-capacity timeouts.

Expanded clipboard coverage at ea65e3b retained 50 passed / 1 failed / 51 tests in 15 files, 27.09s. The failure is the existing 5000ms Word-capacity timeout; the chained TypeScript command did not run. Independent TypeScript then passed, and the getter/preflight plus unchanged full 3000-paragraph capacity diagnostic passed 4 tests in 3.97s. This focused result does not erase the failed broader acquisition. Full unchanged default coverage at1ca6ed3c terminated exit1: 861 passed / 32 failed / 893 tests, 162 files, 793.78s. All 32 failures are existing 5000ms timeouts across multiple editor/collaboration/autosave/clipboard cases; no cause is inferred and no deadlines are relaxed. Internal read-only review through1ca6ed3c found no actionable defect, but is not GitHub approval.

Final36037015 only renames the regression's local binding to sourceChildren; runtime, documents and manifests are unchanged. Its two regression tests, independent TypeScript and complete package verification passed. The fresh archive is byte-identical to the successful1ca6ed3c build, SHA-256 77b60ab6903a6124f167dc8f55567ae530db5ee2bbcccf481d698193ae5be4aa. A public packed synthetic unit probe passed: one accepted fragment-list read, zero child-item reads on capacity rejection, exact output order retained. That probe uses installed peers; independent consumer proof comes from complete package verification. Normal push and independent remote SHA check confirm36037015. Current-head full-suite, browser, Office, hosted and release acceptance remain unproven. Evidence and failed attempts: /private/tmp/inkspan-pr359-child-list.2yBMyH.

Preserved earlier test-first history

Current36037015 full configured coverage is now terminal and failed (exit1): 890 passed / 3 failed / 893 tests, 162 files, 339.21s. Toolbar affordance invocation, autosave schema-evidence value-count traversal, and Word capacity each exceeded the unchanged5000ms timeout. All inputs and assertions remain; the smaller failure count versus the predecessor does not establish causality or a performance gain. No full coverage/browser/Office/hosted/release acceptance is claimed. The internal reviewer also checked the exact test-only1ca6ed3c..3603701 follow-up and found no actionable defect; this is not formal GitHub approval.

  • Resource preflight RED 51f9edfdff7de9072cafa8cebaf068dc39f92208: oversized ASCII still reached TextEncoder; broad fragment exceeded traversal budget only after excess child-item reads.
  • Resource repair 71654a8e59eecd72f2a23ebec173e4e537c927d9; original doctoring 58f004e5053e2a9b686814b4b9c724ab389a83ec.
  • Customer guidance RED 37105d712c774b7ef638315d7d691311fd52c1ad and repair d0255ecb05e77b3c98f365c51fc3a15c630c736a preserve stable machine-readable rejection codes while giving customers bounded next actions.
  • Compatibility-contract updates 4cfa7eff674c8d66dd1e10b61beba6324ca307a7, 8185d86a413c216335b4f9a10521ef5beead8d3f, 47032a59c2cd2fc040c00793dcf819f44577acd3 and the later ordinary stack synchronization remain retained. Old head/base/workflow snapshots are historical, not current evidence.

Remaining gates

Current36037015 canonical packed-browser gate failed (exit1):49passed/1failed/20notrun/70total,0flaky,113.593014s. Firefox active-script timed out in the unchanged20s afterEach networkidle wait; missing Firefox/consensus receipts remain non-passing. Chromium/WebKit receipts and all logs are retained. Three workers, zero retries, fixtures, assertions and startup/test limits were unchanged. Built CSS matched the exact77b60ab6 packed stylesheet. Shared browser-teardown diagnosis stays with #380; no bypass is copied into this sanitizer lane.

Keep Draft pending the canonical prerequisite order and applicable exact-head independent review/check/security/package/browser/release evidence. Missing, pending, skipped, stale and predecessor checks are non-passing. Internal read-only agent review does not provide GitHub approval. No self-approval, CODEOWNERS gate re-enablement, admin bypass or fabricated status is authorized. #118 remains the version-neutral next-stable release/publication authority; no current package is declared published. No transport, credentials, authentication, tenancy, durable persistence/audit, model or deployment authority is added.

Clipboard capacity profiling — 2026-09-07

At unchanged36037015, the exact two-case Word-capacity unit file printed2passing cases (3000paragraph case1372ms), but the overall CPU-profile command required cleanup of two confirmed-owned idle worker processes and terminated exit1 with a Node/tinypool cleanup exception. It is not an unassisted passing gate. The completed worker profile retained479sanitizer-subtree samples, including58own CSSStyleDeclaration-constructor samples with parsing and output-element construction ancestors. This identifies jsdom construction cost in that acquisition, not a proved native-browser bottleneck or the cause of prior capacity timeouts. Existing thresholds, fixtures, guards, source and dependencies remain unchanged. Full failures are retained; no speed improvement or acceptance upgrade is claimed. Protocol, exact command, terminal log and read-only profile summarizer: /private/tmp/inkspan-clipboard-profile.Cxmh7O.

cursoragent and others added 3 commits August 16, 2026 15:17
Add exact RED regressions for oversized UTF-8 encoding and
broad-source child materialization on current protected main.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Reject oversized UTF-16 clipboard HTML before UTF-8 allocation and
reject broad source trees before child materialization, preserving
existing redacted error codes on current protected main.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment

This is a current-main successor for clipboard UTF-8 and maxNodes preflight (#163 / #327). The production change is the right shape:

  • sourceHtml.length > maxHtmlBytes short-circuits before TextEncoder.prototype.encode.
  • assertTraversalCapacity(visited + queued + enqueueable) runs before NodeList.item().
  • Closed-details uses the same queue invariant.
  • Redacted codes/messages are unchanged.
  • Doctoring uses APA 7th citations (Unicode 16.0 §3.9, ECMA-262 string length, WHATWG DOM, CWE-770, Clipboard API WD) and tells the host to raise only the matching ceiling.

Writer conflict

Issue #327 still names Draft #164 as the sole SafeClipboard writer. #164’s live base is stale (50ac98c, not current main@e8109ec) and also carries hostile-throw branding plus release-workflow convergence. Draft #351 remains the current-main writer for clipboard throw-value containment (#349).

Prefer this PR for the resource-preflight product change on current main. Keep #164 unmerged. Do not fold throw-value or release-workflow work into this branch.

Next action

  1. Keep Draft/unmerged while #118 owns v0.6.0.
  2. Re-verify exact-head CI/Security/SAST on the unchanged head before any Ready decision.
  3. If a paste is rejected with input_too_large or node_limit_exceeded, measure a trusted source and raise only that ceiling.
Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

@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
@seonghobae

Copy link
Copy Markdown
Contributor

Exact-head local validation for 9ab6980: seven clipboard preflight, guidance, adapter, and documentation contract files reached 28/30 tests passed. Two failures are stale expectations in SafeClipboardPreflightSize.test.ts and SafeClipboardTraversalBudget.test.ts: the implementation returns the current actionable messages for input_too_large and node_limit_exceeded, while those tests still expect the former generic messages. The PR is dirty and this validation did not modify its branch.

@seonghobae
seonghobae changed the base branch from main to fix/clipboard-hostile-throw-349 September 4, 2026 18:06
@seonghobae

Copy link
Copy Markdown
Contributor

Restacked onto exact parent #351 head d7f83fc8ffb7b086e027f116e0965bbd2753214b; exact head is d7a8a3212421c7990cb4e4e8f580e651742d8cf6. The PR base is now the parent branch so ownership and review evidence follow the actual SafeClipboard dependency order.

Integration repair:

  • preserved both parent security hardening and child resource-preflight/customer-guidance behavior
  • aligned four stale exact-message assertions with the child public guidance contract while preserving stable codes and redaction

Fresh verification:

  • focused SafeClipboard stack: 9 files / 34 tests passed
  • TypeScript typecheck: passed
  • full Vitest suite: 162 files / 892 tests passed
  • coverage: 100% statements, branches, functions, and lines
  • Python support contract: 4 passed
  • unresolved review threads: 0

This remains draft and dependency-gated by #351/#118.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Adopt the parent single-writer repair without rewriting the child history. The clipboard resource preflight delta remains isolated above the updated parent.

Signed-off-by: Seongho Bae <seonghobae@users.noreply.github.com>

Commit-Message-Assisted-by: Claude (via Claude Code)
@seonghobae seonghobae added the bug Something isn't working label Sep 7, 2026 — with ChatGPT Codex Connector
Signed-off-by: Seongho Bae <me@seonghobae.me>
Signed-off-by: Seongho Bae <me@seonghobae.me>
Signed-off-by: Seongho Bae <me@seonghobae.me>
Signed-off-by: Seongho Bae <me@seonghobae.me>
@seonghobae

Copy link
Copy Markdown
Contributor

Native follow-up to the jsdom capacity profile

Unchanged head 36037015e3715d9c1590438bafde888d62487f86, existing packed archive SHA-256 77b60ab6903a6124f167dc8f55567ae530db5ee2bbcccf481d698193ae5be4aa, pinned Playwright 1.62.0. No rebuild, source/dependency change, retry, warm-up, or threshold adjustment.

The existing 3,000-paragraph synthetic unit fixture was executed once per engine, serially in fresh contexts through the public packed browser harness:

Engine Full probe interval Outcome
Chromium 151.0.7922.34 131.4 ms pass
Firefox 153.0 268 ms pass
WebKit 26.5 139 ms pass

All acquisitions retained the 20-second network-idle guard and checked 3,000 document paragraphs, 3,000 output paragraphs/strong elements, first/last text, no class/style attributes, no sanitizer error, and zero external HTTP requests. Command exit 0; owned server stopped afterward.

This interval includes editor construction, clipboard transformation, document parsing, JSON extraction, and destruction. It is not sanitizer-only time, not the canonical 800-paragraph browser fixture, and not a customer workload or p95 measurement. Host contention is uncontrolled. These three observations do not reproduce the 5-second unit timeout in native engines and do not establish its cause or a speedup. The failed canonical full coverage and browser acquisitions above remain failed.

Retained protocol, runnable probe and all three results: /private/tmp/inkspan-native-word-diagnostic.caSvvd. The next implementation decision must be based on a localized measured cost, not jsdom constructor samples alone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working priority: medium Normal-priority or P2 work status: draft Draft pull request type: bug Defect or incorrect behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(reliability): reject obviously oversized rich clipboard HTML before UTF-8 encoding

2 participants