Skip to content

privateai0/macos-window-privacy-research

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

macOS Window Privacy Research

Technical research on macOS window privacy APIs, screen capture exclusion, and window server internals.

macOS Research Updated

Overview

This repository documents the macOS window server APIs that control window visibility in screen captures, recordings, and window enumeration. These APIs are used by macOS itself for system UI elements (e.g., the screenshot selection overlay, Notification Center) and are accessible to third-party applications.

CGWindowList

Window Enumeration

CGWindowListCopyWindowInfo is the primary API for discovering on-screen windows:

CFArrayRef windowList = CGWindowListCopyWindowInfo(
    kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
    kCGNullWindowID
);

Returns an array of dictionaries containing:

  • kCGWindowNumber - unique window ID
  • kCGWindowOwnerPID - process ID of the owning application
  • kCGWindowOwnerName - process name
  • kCGWindowBounds - position and size
  • kCGWindowLayer - window level (normal, floating, status bar, etc.)
  • kCGWindowSharingState - capture/sharing permissions
  • kCGWindowName - window title (requires accessibility permissions)

Window Sharing States

The sharing state determines whether a window appears in screen captures:

State Value CGWindowList Screen Capture Screen Recording
kCGWindowSharingNone 0 Excluded Excluded Excluded
kCGWindowSharingReadOnly 1 Included Excluded Excluded
kCGWindowSharingReadWrite 2 Included Included Included

CoreGraphics SPI

CGSSetWindowSharingState

Private API to set a window's sharing state:

extern CGError CGSSetWindowSharingState(
    CGSConnectionID cid,
    CGSWindowID wid,
    CGSSharingState state
);

Where CGSSharingState:

  • 0 = None (fully private)
  • 1 = Read only
  • 2 = Read/Write (default)

Getting a CGS Connection

extern CGSConnectionID CGSMainConnectionID(void);
// or
extern CGSConnectionID _CGSDefaultConnection(void);

Setting Window Level

extern CGError CGSSetWindowLevel(
    CGSConnectionID cid,
    CGSWindowID wid,
    CGWindowLevel level
);

Common levels:

  • kCGNormalWindowLevel (0) - standard windows
  • kCGFloatingWindowLevel (3) - floating panels
  • kCGStatusWindowLevel (25) - status bar level
  • kCGScreenSaverWindowLevel (1000) - above everything

ScreenCaptureKit (macOS 12.3+)

Modern framework for screen capture that respects sharing states:

let filter = SCContentFilter(
    display: display,
    excludingWindows: [privateWindow]
)
let stream = SCStream(filter: filter, configuration: config, delegate: delegate)

Windows with sharingType = .none are automatically excluded from all SCStream output, SCScreenshotManager captures, and SCRecordingOutput.

NSWindow.SharingType

The public AppKit API for setting sharing type:

window.sharingType = .none      // Excluded from capture
window.sharingType = .readOnly  // Visible but not capturable
window.sharingType = .readWrite // Default - fully visible

Important: Setting sharingType on an NSWindow calls through to CGSSetWindowSharingState internally. However, AppKit may reset this value during certain window operations (e.g., makeKeyAndOrderFront).

Reliable Exclusion Pattern

To ensure a window stays excluded from screen capture:

  1. Set sharingType = .none after window creation
  2. Use orderFrontRegardless() instead of makeKeyAndOrderFront(_:) to avoid AppKit resetting the sharing type
  3. Re-apply sharingType = .none after any operation that might reset it

Verification

Checking Window Visibility

Python script to check if a window appears in CGWindowList:

import Quartz

options = Quartz.kCGWindowListOptionOnScreenOnly
windows = Quartz.CGWindowListCopyWindowInfo(options, Quartz.kCGNullWindowID)
for w in windows:
    print(f"{w.get('kCGWindowOwnerName', '?')}: {w.get('kCGWindowName', '?')} (sharing={w.get('kCGWindowSharingState', '?')})")

Checking Screen Capture

screencapture -x /tmp/test.png
# Windows with sharingType .none will not appear

Applications

This research is used in LDBypass, a macOS application that renders AI assistants (ChatGPT, Claude) in a private overlay window that is invisible to proctoring software. The overlay uses sharingType = .none at the window server level to remain excluded from all screen capture and window enumeration.

Related Resources


This is a research document. All APIs described are publicly documented or discoverable through standard reverse engineering techniques. No proprietary source code is included.

About

Research on macOS window privacy APIs — CGWindowList, CGSSetWindowSharingState, ScreenCaptureKit exclusion, and screen capture prevention techniques

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors