Skip to content

fix(stealth): make language picker invisible to screen capture - #53

Open
ignitinsharma wants to merge 1 commit into
TechyCSR:mainfrom
ignitinsharma:fix/stealth-lang-picker-leak
Open

fix(stealth): make language picker invisible to screen capture#53
ignitinsharma wants to merge 1 commit into
TechyCSR:mainfrom
ignitinsharma:fix/stealth-lang-picker-leak

Conversation

@ignitinsharma

Copy link
Copy Markdown

Summary

Fixes critical stealth leak where the language picker (C++ / C / Python / Java / JavaScript) was visible to remote participants during Google Meet / Zoom / OBS screen share, while the rest of the overlay was hidden.

Severity

High — users could be exposed during interviews.

Steps to Reproduce

  1. git clone https://github.com/TechyCSR/OpenCluely.git && cd OpenCluely && ./setup.sh
  2. npm start on macOS (or Windows)
  3. Join a Google Meet call and share screen (or OBS display capture)
  4. Open the language picker in the floating pill (e.g. JavaScript dropdown)
  5. Observed: the dropdown options list (C++, C, Python, Java, JavaScript) appears in the remote capture, even though the pill itself is hidden.

leak screenshot

Root Cause

src/managers/window.manager.js:628 calls window.setContentProtection(true) for every BrowserWindow (maps to NSWindowSharingTypeNone on macOS / WDA_EXCLUDEFROMCAPTURE on Windows).

The pill used a native <select id="codingLanguage"> (index.html:372). Chromium renders the options popup as a separate OS NSMenu/NSPopUp window, not inside the BrowserWindow. That OS window is not covered by setContentProtection and is captured normally.

Fix

Replace the native <select> with a custom in-window menu so it stays inside the protected BrowserWindow:

  • index.html: Replace <select> with <button id="codingLanguageBtn"> + <ul id="codingLanguageMenu" class="lang-menu"> (5 li[data-value]). Add .lang-menu CSS (absolute, top:32px, backdrop blur, opacity/visibility toggle) alongside .shortcuts-popover. Menu never leaves the window bounds, so setContentProtection applies. Comment added: ponytail: custom in-window lang menu...

  • src/ui/main-window.js:

    • resizeWindowToContent() now includes langMenu height (like shortcutsPopover).
    • Replace languageSelect.value/onchange with langBtn/langMenu handling: applyLang(), toggle is-open/aria-expanded, saveSettings({codingLanguage}), close on outside click / Escape.
    • Mutual exclusion with shortcutsPopover (opening one closes the other).
    • handleInteractionModeChanged() closes menu when leaving interactive mode.
    • onCodingLanguageChanged now syncs via _currentLang / _langLabels.

No new dependencies. settings.html still uses its own <select> — only the overlay is changed.

Testing

  • node --check src/ui/main-window.js / htmlhint index.html pass
  • npm start boots without renderer errors (Gemini AI client initialized)
  • macOS 14 — Meet share preview hides menu, local interaction still works (verified with OBS display capture preview)
  • WindowssetContentProtection path covered (same logic)
  • Interaction: click JavaScript → menu toggles, pick Python → persists via saveSettings, window resizes correctly, Esc/outside click closes, Alt+A (non-interactive) hides menu
  • Linux: known limitation per README LimitationssetContentProtection is no-op on X11/Wayland; menu still clips correctly but will be visible (platform limitation, documented)

Files Changed

  • index.html (+71)
  • src/ui/main-window.js (+66)

Checklist

  • Focused PR — only stealth leak fix
  • No breaking API changes
  • Follows existing code style

Fixes invisible-overlay contract stated in README.md Highlights: “Invisible overlay. Windows stay out of Zoom, Google Meet, …”.

Replace native <select> in main overlay with in-window custom menu
so it stays inside the BrowserWindow covered by setContentProtection
(NSWindowSharingNone / WDA_EXCLUDEFROMCAPTURE). Native OS popup was
an uncaptured window visible in Google Meet/Zoom/OBS.

- index.html: button + ul.lang-menu, CSS keeps menu inside window
- main-window.js: custom toggle/saveSettings, resize handling,
  auto-close with interaction mode

Fixes stealth leak where C++/Java picker was captured during share
@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

@ignitinsharma is attempting to deploy a commit to the csrsoftwares' projects Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant