Repository navigation
fix(security): fail closed on hostile clipboard sanitizer throw values #349
Description
Buyer-visible clipboard fail-closed defect — canonical Draft #351
Protected shipped truth is exact main@3b38ead2d00f44eb578d0689087b9293b3dabe1e. Draft PR #351 / branch fix/clipboard-hostile-throw-349 is the canonical single writer for this hostile-thrown-value containment boundary. Historical pre-synchronization head 3460f2d4233177a29607dd9b181ff4fad3d363bf and historical branch-base metadata e8109ec2a17de8bd6594487aa12c8c8a93cb2c03 are predecessor state. Current exact Draft head is 61936f2d9e26373115fed1dee1ce93387ebcfc12, synchronized non-destructively with protected main; GitHub reports the Draft mechanically mergeable.
Protected production classified sanitizer/configuration failures with instanceof ClipboardSanitizationError. A hostile host option/config getter could throw a Proxy whose getPrototypeOf trap throws a private sentinel; prototype-based classification inside the catch path could then leak that second exception instead of returning the stable empty paste result and payload-redacted invalid_html observer error.
Inkspan owns this deterministic local clipboard error-containment boundary. No transport, persistence, auth, tenancy, credentials, model/provider, network, deployment, retention, durable audit, or clipboard-exfiltration authority is added.
TDD and repair lineage
- RED
758c36c05f104be0cc6b608acd5c753ea5b9b709: hosted CI31901402934reached the real ProseMirrortransformPastedHTMLregression after immutable setup/typecheck and failed because the hostile thrown Proxy's prototype trap escaped. - GREEN source commits
ce8223071aa658d70edfde6b70df936eb7e77e77and3f963bfe0cb0e96366ad3eb42ed4546c197cfeaf: module-createdClipboardSanitizationErrorvalues are tracked with a side-effect-free module-ownedWeakSetidentity brand; every other unknown thrown value normalizes directly to stable redacted failure without prototype/property/string coercion. e54c7769feecffe62734a7e18bd5a3f440d98358preserves stale fix(reliability): bound rich clipboard resource preflight #164's remaining unique direct-sanitizer hostile-configuration regression before fix(reliability): bound rich clipboard resource preflight #164 was closed/superseded.- Pre-synchronization head
3460f2d4233177a29607dd9b181ff4fad3d363bfalso exercises a hostconfiggetter that throws a primitive string; the real adapter returns''and emits exactly one stableinvalid_htmlobservation without leaking the primitive. - Current synchronization merge
61936f2d9e26373115fed1dee1ce93387ebcfc12incorporates exact protectedmain@3b38ead2d00f44eb578d0689087b9293b3dabe1ewithout changing the intended SafeClipboard ownership boundary. Predecessor workflow/review evidence does not transfer after this head movement.
Review contradiction resolved
A formal Cursor CHANGES_REQUESTED review on this lane asserted that WeakSet.prototype.has(primitive) throws. That premise is factually inconsistent with the ECMAScript weak-collection contract; the branch additionally guards primitives before the set lookup and proves the primitive-string path through the real adapter regression. The factually invalid review is dismissed and its only inline thread is resolved/outdated. Dismissal is not approval.
Unknown thrown values must still never be stringified, enumerated, coerced or prototype-inspected merely to classify them.
Current exact-head evidence
For unchanged exact head 61936f2d9e26373115fed1dee1ce93387ebcfc12 against protected main@3b38ead2d00f44eb578d0689087b9293b3dabe1e at the fresh pre-write refetch:
- CI
32438908748: completed / success; - Security Scan
32438908692: completed / success; - SAST Semgrep
32438908699: completed / success; - effective formal
CHANGES_REQUESTED: 0 after dismissal of the factually invalid predecessor review; - unresolved inline review threads: 0;
- qualifying approving reviews: 0;
- GitHub reports the Draft mechanically mergeable.
The older successful 31960596587 / 31960596547 / 31960596548 generations belong to predecessor head 3460f2d4233177a29607dd9b181ff4fad3d363bf and are non-passing for the current head. Repository-local exact-head success is technical evidence only; it does not replace applicable central required workflows, qualifying independent approval, fresh live-base reconciliation, or then-live governance. Pending/queued/skipped/cancelled/absent/stale/predecessor/status-only/model-only evidence remains non-passing.
Ownership / integration boundary
#351 owns hostile thrown-value containment. Draft #359 separately owns SafeClipboard resource preflight (#163/#327), and #176 owns the overlapping SafeLink/Markdown policy surface. Do not create a competing writer or reintroduce unrelated SafeLink/release-control changes here.
Keep #351 Draft/unmerged while #118 owns exact protected v0.6.0 publication/provenance/digest operational acceptance. Before any lifecycle transition refetch exact head/live protected tip, ancestry/mergeability, formal reviews/threads, live governance and every applicable repository/central workflow. Do not self-approve, transfer predecessor evidence, weaken gates, move protected main or fabricate release identity.
Activity