Skip to content

fix(security): fail closed on hostile clipboard throw values - #351

Draft
seonghobae wants to merge 21 commits into
mainfrom
fix/clipboard-hostile-throw-349
Draft

fix(security): fail closed on hostile clipboard throw values#351
seonghobae wants to merge 21 commits into
mainfrom
fix/clipboard-hostile-throw-349

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Scope

Test-first repair for #349 on Inkspan's deterministic local SafeClipboard failure-containment boundary only. No transport, persistence, auth, tenancy, credential, model/provider, network, deployment, retention, durable-audit, or clipboard-exfiltration authority is added.

Current authority

  • Live protected shipped truth: main@3b38ead2d00f44eb578d0689087b9293b3dabe1e.
  • Historical branch-base metadata: e8109ec2a17de8bd6594487aa12c8c8a93cb2c03; do not mistake it for the live protected tip.
  • Historical pre-synchronization Draft head: 3460f2d4233177a29607dd9b181ff4fad3d363bf.
  • Exact current Draft head: 61936f2d9e26373115fed1dee1ce93387ebcfc12 on fix/clipboard-hostile-throw-349.
  • GitHub reports the Draft mechanically mergeable; mergeability is not authorization.

RED → GREEN lineage

  • RED 758c36c05f104be0cc6b608acd5c753ea5b9b709: hosted CI 31901402934 reached the real ProseMirror transform after immutable setup/typecheck and failed because a hostile thrown Proxy's prototype trap escaped.
  • GREEN ce8223071aa658d70edfde6b70df936eb7e77e77 / 3f963bfe0cb0e96366ad3eb42ed4546c197cfeaf: replace instanceof classification of unknown thrown values with module-owned WeakSet identity branding for genuine ClipboardSanitizationError instances; all unknown values normalize directly to stable payload-redacted boundaries without prototype/property/string coercion.
  • e54c7769feecffe62734a7e18bd5a3f440d98358 preserves the remaining unique direct-sanitizer hostile-configuration regression from closed stale fix(reliability): bound rich clipboard resource preflight #164 before that duplicate lane was retired.
  • Pre-synchronization head 3460f2d4233177a29607dd9b181ff4fad3d363bf adds a real adapter regression where the host config getter throws a primitive string; Inkspan returns '', emits one stable invalid_html observation, and does not leak the primitive.
  • Synchronization merge 61936f2d9e26373115fed1dee1ce93387ebcfc12 incorporates protected main@3b38ead2d00f44eb578d0689087b9293b3dabe1e without changing the intended SafeClipboard ownership boundary.

Review contradiction resolved

The prior Cursor CHANGES_REQUESTED review asserted that WeakSet.prototype.has(primitive) throws. That premise conflicts with the ECMAScript weak-collection contract: when the candidate cannot be held weakly, WeakSet.prototype.has returns false. The branch also guards primitives before the set lookup and proves the primitive-string path through the real adapter regression. The factually invalid review is dismissed, explicitly not converted into an approval; its inline thread is resolved/outdated.

This does not relax the product contract or governance. Unknown thrown values still must not be stringified, enumerated, coerced, or prototype-inspected merely to classify them.

Scope ownership

Stale #164 mixed resource preflight, release-control history, and hostile-throw containment. Current ownership is split intentionally:

Do not create a competing writer or reintroduce unrelated SafeLink/release-control changes here.

Exact-current-head evidence

For exact head 61936f2d9e26373115fed1dee1ce93387ebcfc12 against protected main@3b38ead2d00f44eb578d0689087b9293b3dabe1e, at the latest fresh 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.

All observed repository-owned exact-head workflows are terminal success. The older successful 31960596587 / 31960596547 / 31960596548 generations are predecessor evidence for 3460f2d4233177a29607dd9b181ff4fad3d363bf and do not transfer. Repository-local technical success does not substitute for separately applicable central workflows, fresh live-base reconciliation, or qualifying independent approval. Absent approval remains non-passing.

Integration boundary

Keep Draft/unmerged while #118 owns exact protected v0.6.0 publication/provenance/digest operational acceptance. Before any later Ready/merge transition, refetch the unchanged exact head, live protected tip, ancestry/mergeability, formal reviews/threads, live governance and every applicable repository/central workflow. Do not force-push, destructively rebase, self-approve, transfer predecessor evidence, weaken gates, or fabricate release identity.

Refs #349

@coderabbitai

coderabbitai Bot commented Aug 15, 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.

cursor[bot]
cursor Bot previously requested changes Aug 16, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Draft #351 correctly moves throw-value recognition off instanceof prototype inspection and keeps the change on current main@e8109ec. Do not merge 1518a5684c37dbe02c23e758823d501629d50bb5 until the brand helper is primitive-safe.

CLIPBOARD_SANITIZATION_ERRORS.has(value as object) throws for null, strings, and numbers. The new catch sites therefore fail open on primitive throws that the previous instanceof path contained.

Keep this PR scoped to #349. Resource preflight (#163, #327) is #359. Keep Draft while #118 owns the exact v0.6.0 publication identity.

Open in Web View Automation 

Sent by Cursor Automation: Fix Issues

Comment thread src/extensions/SafeClipboard.ts Outdated
@seonghobae
seonghobae dismissed cursor[bot]’s stale review August 18, 2026 18:31

Dismissed as factually invalid, not as approval. ECMAScript WeakSet.prototype.has returns false when CanBeHeldWeakly(value) is false; it does not throw for null/string/number inputs. Exact head 3460f2d also carries a real adapter regression for a primitive string throw and repository CI/Security/SAST are terminal-success. #351 remains Draft, unmerged, and still requires fresh live-base/central-workflow/governance evidence plus qualifying independent approval before any lifecycle transition.

Copy link
Copy Markdown
Contributor Author

Addressed the outstanding primitive-safety review in commit 9529b81: isClipboardSanitizationError now guards object/function values before consulting the WeakSet, with a direct string/number/null regression. Exact-head verification passed: SafeClipboard extension suite 12 files / 44 tests, targeted SafeClipboard.ts coverage 100% statements/branches/functions/lines, and tsc --noEmit. The PR remains Draft and unmerged pending fresh review and protected gates.

Copy link
Copy Markdown
Contributor Author

@opencode-agent review exact current head 9529b81e4091a88dac3b2e22f54faf5b213accf7 against base e8109ec2a17de8bd6594487aa12c8c8a93cb2c03. Re-check the primitive-safe isClipboardSanitizationError boundary and the 44-test/100%-coverage evidence after the fix. Submit a formal current-head verdict only after required Checks settle; do not transfer the dismissed predecessor review or bypass Draft/protected gates.

@opencode-agent opencode-agent Bot added area: security Security boundary, hardening, or vulnerability prevention 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 Author

Exact-head local validation for 8881f2a: the four SafeClipboard hostile-throw and adapter contract files passed in a detached worktree, 4/4 files and 24/24 tests. This validates the targeted regression path only; the PR remains Draft and this is not approval or merge evidence.

@opencode-agent

opencode-agent Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Scheduled review-feedback autofix for this PR head.

  • Head SHA: 8881f2a44e6e7a2b49477133ba3a86fcdbaf4f5b

@seonghobae

Copy link
Copy Markdown
Contributor Author

Draft head baea226da8d30a0d4efab1c77559f1ccb03027ce를 protected main@a40b9489665bed7d95af619a6079b9c51cab299a에 비파괴 재스택했습니다. 삭제된 이전 Strix 실패 로그는 현재 원인 근거로 재사용하지 않았습니다. 새 head 검증: hostile-throw 경계 4/4, TypeScript typecheck, 전체 158 files / 885 tests, statements·branches·functions·lines 100%, Python CI 계약 4/4, git diff --check 통과. #118의 릴리스 의존성 때문에 Draft 상태는 유지하며 새 exact-head Checks를 기다립니다.

@seonghobae

Copy link
Copy Markdown
Contributor Author

@codex review exact current head baea226da8d30a0d4efab1c77559f1ccb03027ce against protected main@a40b9489665bed7d95af619a6079b9c51cab299a. Keep the PR Draft while #118 owns release acceptance.

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

Signed-off-by: Seongho Bae <me@seonghobae.me>
@seonghobae

seonghobae commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

후속 리뷰에서 발견된 CI 계약의 분기 연결 검증도 반영했습니다. Draft exact head d7f83fc8ffb7b086e027f116e0965bbd2753214b에서 PR/latest 배열과 push/전체 배열의 조건 연결까지 검사합니다. hostile-throw 4/4와 Python 계약 4/4를 다시 통과했으며 Draft·#118 의존성은 그대로 유지합니다.

Remove the duplicated Python support contract changes from this clipboard branch. PR #405 remains the single writer while this branch keeps its hostile-throw containment delta.

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: security Security boundary, hardening, or vulnerability prevention 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.

1 participant