Conversation
legacyCopy() appended the scratch textarea and read the operator's selection before entering the try/catch that guards execCommand, and called source.remove() only on the happy path after that block. If getSelection() or select() throws (a detached document, per the issue report), the textarea holding the copied secret is left in the DOM for the life of the page. Move the whole sequence into a single try/finally so the textarea is always removed and the selection/focus restored, whatever throws. The propagated error is unchanged; only the cleanup is now unconditional. Fixes mozilla-ai#1149
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review. WalkthroughChanges
ChangesClipboard cleanup
Priority: ⬆️ High Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: High Suggested reviewers: Merge Risk: ⚪ Minimal · up to The temporary clipboard textarea is removed when selection setup fails, preventing copied content from remaining in the page DOM. The change is ready to merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
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. Comment |
Description
legacyCopy(the execCommand fallback used on plain-HTTP LAN origins, wherenavigator.clipboardis undefined) builds an offscreen textarea holding the copied text, often an API key sinceCopyFieldroutes through this helper. It callsdocument.getSelection(), readsdocument.activeElement, and callssource.select()before entering the only try/catch in the function, which guardsexecCommandalone.source.remove()runs after that, on the happy path only.select()is documented to throw in a detached-document/cross-document situation, and if it does, the textarea is never removed: the plaintext stays in the DOM for the life of the page.Moved the removal, and the selection/focus restore that already existed to protect the operator's tab position, into a
finallyso they run regardless of what throws once the textarea is in the DOM.How to test it locally
pnpm --dir web vitest run src/design-system/helpers/clipboard.test.ts. The new test stubsHTMLTextAreaElement.prototype.selectto throw and asserts no<textarea>is left behind; it fails onmain(1 leaked node) and passes on this branch.PR Type
Relevant issues
Fixes #1149
Checklist
tests/unit,tests/integration).make lint,make typecheck,make test).uv run python scripts/generate_openapi.py).AI Usage
AI Model/Tool used: Claude
Any additional AI details you'd like to share:
Summary
legacyCopyto always remove its temporary textarea and restore selection and focus.select()throws.This prevents copied credentials from remaining in the document after a setup failure.