Skip to content

Incognito windows are captured on macOS when enhanced detection is enabled (Chrome) #5531

Description

@Rafaelpta

Summary

With enhanced_detection enabled on macOS, Chrome incognito windows are captured (frames, OCR text, accessibility text) even though ignore_incognito_windows is on. Basic title based detection is not affected: opting into enhanced detection is what opens the gap, which is the opposite of what a user enabling it would expect.

Root cause

In crates/screenpipe-a11y/src/incognito/macos.rs, is_incognito() treats any answer from the AppleScript strategy as final:

if self.enhanced_detection && Self::is_chromium_browser(app_name) {
    if let Some(is_private) = self.check_with_cache(app_name, window_title) {
        return is_private;
    }
    // AppleScript failed — fall through to title check.
}

check_with_cache compares titles by exact match (titles.contains(window_title)). The AppleScript query returns tab titles (for example Privacy - Wikipedia), while the AX window title passed in by the tree walk carries a suffix (Privacy - Wikipedia - Google Chrome (Incognito)). The lookup misses, Some(false) is returned, and the localized title fallback is_title_private() never runs, even though it would have matched the (Incognito) marker in that same title.

The fallback only runs when AppleScript errors out (None), not when it succeeds with a non matching answer.

Reproduction

macOS 26, Chrome, ignore_incognito_windows on, enhanced detection on:

  1. screenpipe record --data-dir ./data --use-all-monitors
  2. Open a Chrome incognito window, focus it, browse two tabs for a minute
  3. sqlite3 ./data/db.sqlite "SELECT id, window_name, text_source FROM frames WHERE window_name LIKE '%Incognito%';"

Observed (reproduced three times, 6 to 9 rows each run):

id  window_name                                      text_source
--  -----------------------------------------------  -------------
3   Example Domain - Google Chrome (Incognito)       accessibility
4   Privacy - Wikipedia - Google Chrome (Incognito)  accessibility
5   Privacy - Wikipedia - Google Chrome (Incognito)  accessibility
...

Page text from those windows is present in the extracted text as well. Expected: TreeWalkResult::Skipped(SkipReason::Incognito) and no capture.

Suggested fix

Treat a negative AppleScript answer as non final and let the localized title check have the last word. A false positive skips one window; a false negative records private browsing.

if self.enhanced_detection && Self::is_chromium_browser(app_name) {
    if let Some(true) = self.check_with_cache(app_name, window_title) {
        return true;
    }
    // A negative answer is not trusted as final: the AppleScript query
    // returns tab titles, while the AX title carries a browser suffix,
    // so the exact match lookup can miss a window that is private.
}
is_title_private(window_title)

An alternative is to make the cache lookup tolerant (window_title.contains(title) in addition to the exact match), but falling through is the smaller and safer change.

Happy to open a PR if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions