# Security Considerations: Niri Window Capture

## What This Skill Does

This skill enables invisible window capture across all workspaces using niri compositor's direct window rendering capability. **Any window can be captured without visual indication to the user.**

## Threat Model

### Access Control

**Who can capture windows?**
- Any process running as your user with access to niri's IPC socket
- The AI agent when this skill is deployed
- Malicious local processes (if compromised)

**What can be captured?**
- ANY window, regardless of workspace
- Windows you think are "hidden" on other workspaces
- Password managers (unless blocked via niri config)
- Banking apps, terminals with credentials, private messages
- Everything is fair game by default

### Privacy Implications

**Cross-workspace capture is invisible:**
```bash
# You're on workspace 1
# AI captures window from workspace 2
# You never see it happen
```

**No visual feedback** - Unlike regular screenshots which flash or show UI, these captures are completely silent (except for a notification popup).

**Clipboard pollution** - Every capture overwrites your clipboard with the screenshot (niri hardcoded behavior, cannot be disabled).

## Audit Trail

All captures are logged to systemd journal:

```bash
# View capture audit log
journalctl --user -t niri-capture

# Recent captures
journalctl --user -t niri-capture -n 20

# Follow live
journalctl --user -t niri-capture -f
```

**Log format:**
```
Nov 08 16:30:15 hostname niri-capture[PID]: Capturing window 12: 'Firefox Browser' (workspace: 2, matched: 'Firefox')
Nov 08 16:30:15 hostname niri-capture[PID]: Screenshot saved: /home/user/Pictures/Screenshots/Screenshot from 2025-11-08 16-30-15.png
```

## Protection Mechanisms

### 1. Window Blocking (Recommended)

Block sensitive applications from being captured by adding to `~/.config/niri/config.kdl`:

```kdl
window-rule {
    match app-id=r#"^org\.keepassxc\.KeePassXC$"#
    match app-id=r#"^org\.gnome\.World\.Secrets$"#
    match app-id=r#"^.*[Pp]assword.*$"#
    match app-id=r#"^.*[Bb]itwarden.*$"#
    
    block-out-from "screen-capture"
}
```

**Find app-id for your password manager:**
```bash
niri msg --json windows | jq -r '.[] | "\(.app_id) - \(.title)"'
```

### 2. Audit Logging (Automatic)

This skill logs all captures automatically. Review regularly:

```bash
# Check what was captured today
journalctl --user -t niri-capture --since today

# Check if specific window was captured
journalctl --user -t niri-capture | grep "Firefox"
```

### 3. Screenshot Directory Permissions

Ensure screenshots directory is private:

```bash
chmod 700 ~/Pictures/Screenshots
ls -la ~/Pictures/Screenshots
# Should show: drwx------ (owner only)
```

### 4. Clipboard Awareness

**WARNING:** Screenshots are ALWAYS copied to clipboard (niri limitation).

**Risks:**
- Clipboard history tools may log sensitive screenshots
- Other applications can read clipboard
- Sensitive data persists in clipboard until overwritten

**Mitigation:**
- Clear clipboard after AI analysis: `echo "" | wl-copy`
- Disable clipboard history tools for image/png mime type
- Be aware of what's in your clipboard

## Known Limitations

### Cannot Be Disabled

- ❌ Clipboard copy (hardcoded in niri)
- ❌ Notification popup (mako/notification daemon shows "Screenshot saved")
- ✅ Can disable via niri window rules (block-out-from)
- ✅ Can monitor via audit logs

### Wayland Security Model

This works because:
- Wayland applications continuously render to surface buffers
- niri compositor holds references to these buffers
- Buffers exist in memory even when windows not visible
- `screenshot-window` renders buffer directly without compositing to screen

**This is not a vulnerability** - it's how compositors work. The security boundary is niri's IPC socket (user-private).

## Recommendations

**Before deploying this skill:**

1. ✅ Enable block-out rules for password managers
2. ✅ Review audit logs regularly: `journalctl --user -t niri-capture`
3. ✅ Ensure screenshot directory is private: `chmod 700 ~/Pictures/Screenshots`
4. ✅ Be aware captures are invisible to you
5. ✅ Trust the AI agent you're deploying this to

**During use:**

1. Check what was captured: `journalctl --user -t niri-capture --since "5 minutes ago"`
2. Review screenshot files: `ls -lt ~/Pictures/Screenshots/ | head -10`
3. Clear sensitive screenshots: `rm ~/Pictures/Screenshots/Screenshot*.png`
4. Clear clipboard if sensitive: `echo "" | wl-copy`

**If compromised:**

1. Disable the skill: `rm ~/.claude/skills/niri-window-capture`
2. Review audit logs: `journalctl --user -t niri-capture`
3. Delete screenshots: `rm ~/Pictures/Screenshots/*.png`
4. Change passwords for anything captured

## Upstream Requests

**Filed with niri upstream:**
- [ ] Add `--no-clipboard` flag to `screenshot-window` action
- [ ] Document security implications of invisible window capture
- [ ] Optional: built-in audit logging

## Trust Model

**You must trust:**
- The AI agent (it can see everything)
- Yourself (you control block-out rules)
- niri compositor (it provides the capability)
- Your user account security (anyone as your user can capture)

**You cannot trust:**
- Other processes running as your user (they can capture too)
- The clipboard (screenshots persist there)
- Visual privacy (captures are invisible)

## Questions?

**"Can I disable cross-workspace capture?"**
No. If a window exists, it can be captured. Use block-out rules to protect specific apps.

**"Can I make captures visible?"**
The notification popup already shows captures happened. True visibility would require workspace switching, which defeats the purpose.

**"Can I review what AI captured?"**
Yes: `journalctl --user -t niri-capture` and `ls -lt ~/Pictures/Screenshots/`

**"Should I use this?"**
Only if you trust the AI agent and have protected sensitive apps via block-out rules.

## Further Reading

- [niri window rules](https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules)
- [niri screenshot configuration](https://github.com/YaLTeR/niri/wiki/Configuration:-Miscellaneous)
- Wayland security model: compositor as the security boundary
