Skip to content

Copy keys and passwords client-side so Copy works over HTTP - #319

Merged
bbangert merged 2 commits into
mainfrom
fix/security-copy-over-http
Nov 10, 2026
Merged

bbangert merged 2 commits into
mainfrom
fix/security-copy-over-http

Conversation

@bbangert

Copy link
Copy Markdown
Owner

Summary

  • Security tab (API key + SSH fingerprint) and Overview drive-password Copy buttons now use the CopyToClipboard hook, which falls back to execCommand on plain HTTP and only shows "Copied" on confirmed success.
  • Removed the phx:copy listener, push_event("copy") handlers and the copied/ssh_copied/drive_password_copied state with their timers.
  • The hook's label swap now targets a data-copy-label span so icons survive, and selecting a failed copy's target works for <input> elements.
  • The drive password Copy is shown only while revealed (the password is deliberately absent from the DOM before Reveal), matching the Audio pairing-token behaviour.

Fixes #230

🤖 Generated with Claude Code

The Security tab's key and fingerprint Copy buttons and the drive
password Copy went through push_event and navigator.clipboard, which is
undefined on the plain-HTTP device UI, yet showed "Copied" regardless.
They now use the CopyToClipboard hook (execCommand fallback, honest
outcome); the drive password Copy is offered only once revealed so the
secret stays out of the DOM until then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟡 Changes recommended

After a mount-time SSHAccess failure, the fingerprint is never refreshed, so Copy keeps copying the unavailable placeholder and reporting success even after the service recovers.

1 open issue
What changed in this PR

Moves Security and drive-password copying to the existing client-side clipboard hook, addressing HTTP clipboard failures in #230 without reporting unconfirmed success.

Changes:

  • Replaces server-driven copy events and state with client-side hooks.
  • Preserves button icons during feedback and supports selecting input text after copy failure.
  • Restricts drive-password copying to revealed passwords and updates LiveView tests.
File Description
test/​universal_proxy_web/​live/​security_live_test.exs Verifies clipboard hooks and selection-target attributes.
test/​universal_proxy_web/​live/​overview_live_test.exs Verifies Copy appears only while the password is revealed.
lib/​universal_proxy_web/​live/​security_live.ex Migrates key and fingerprint copying to client-side hooks.
lib/​universal_proxy_web/​live/​overview_live.ex Removes server-driven password copying and feedback state.
lib/​universal_proxy_web/​components/​storage.ex Adds a clipboard hook for the revealed drive password.
assets/​js/​app.js Preserves icons, supports input selection, and removes the legacy copy listener.

Review effort: Balanced

ssh_fingerprint/0 now returns nil when SSHAccess is unavailable, so the
placeholder text is display-only and never lands in data-clipboard. The
Copy button is disabled meanwhile, and a connected LiveView retries
every 2 s until the fingerprint is readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟢 Approval recommended

No active review issues are reported for the client-side clipboard changes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@bbangert
bbangert merged commit f79f37d into main Nov 10, 2026
9 checks passed
@bbangert
bbangert deleted the fix/security-copy-over-http branch November 10, 2026 01:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Security tab: copying the API encryption key silently fails over HTTP

2 participants