Back to Intelligence

File-Change Notification Side-Channel on Windows, Linux, and Android: How inotify and ReadDirectoryChangesW Leak Keystrokes, Browsing, and WhatsApp Activity — and How to Detect It

SA
Security Arsenal Team
September 25, 2026
9 min read

A new research disclosure covered by SecurityWeek this week demonstrates something experienced red teamers have long suspected but defenders rarely model: the file-change notification subsystems built into every major operating system — Linux's inotify/fanotify, Windows' ReadDirectoryChangesW / USN Journal, and Android's FileObserver — can be abused as a passive side-channel to reconstruct sensitive user activity. The researchers showed that an unprivileged process, with no special permissions and no exploit code, can infer keystroke timing, web browsing activity, and even WhatsApp media send/receive events simply by watching when and how files change on disk.

This is not a memory-corruption bug and it carries no CVE — it is a systemic architectural weakness in how notification APIs expose metadata about file activity to processes that should have no visibility into it. That makes it harder to patch and more important to detect. Any process running as a low-privilege user — including malware that has deliberately stayed away from privileged operations to evade EDR heuristics — can passively surveil a victim's behavior without triggering traditional alarms. For SOC teams, this research should immediately prompt a review of what processes in your environment are registering filesystem watches, and where.

Technical Analysis

Affected Platforms and Components

  • Linux: inotify and fanotify subsystems. Any unprivileged process can call inotify_add_watch() against world-readable directories and receive real-time events (IN_CREATE, IN_MODIFY, IN_DELETE, IN_ACCESS) for files it cannot otherwise read. fanotify requires CAP_SYS_ADMIN for the filesystem-wide mount monitoring mode, but inotify does not.
  • Windows: ReadDirectoryChangesW() allows a process holding a handle to a directory to receive change notifications for that directory tree. Combined with the NTFS USN Journal (FSCTL_READ_USN_JOURNAL / fsutil usn readjournal), an attacker can reconstruct file activity across user profile paths — browser cache writes, IME keystroke artifacts, autosave temp files — without ever reading file contents.
  • Android: FileObserver lets an app monitor paths it can stat. The researchers demonstrated that WhatsApp media events (photo/video received or sent) can be inferred from file creation patterns in media staging directories, and app-switch/browsing behavior leaks through shared storage write patterns — even post-Scoped Storage, residual paths (e.g., /sdcard/Android/media/) remain observable.

How the Side-Channel Works (Defender's View of the Attack Chain)

  1. Placement: The adversary gets an unprivileged foothold — a trojanized app, a low-integrity browser extension process, a malicious package, or simply a co-tenant process on a multi-user system. No exploitation is required beyond execution.
  2. Watch registration: The process registers recursive watches on high-signal directories: browser profile cache/history paths (~/.config/google-chrome/, %LOCALAPPDATA%\Google\Chrome\User Data\), shell/terminal temp paths, WhatsApp media directories, and input-method temp files.
  3. Timing inference: The attacker never reads file content — only event timing, sequence, and filename patterns. Keystroke timing is reconstructed from the cadence of autosave/cache writes; browsing activity from the sequence of cache object creation; WhatsApp send/receive events from media-file creation in staging folders.
  4. Exfiltration: Because the collected data is metadata (timestamps, event counts), it compresses to a tiny payload and blends into ordinary outbound traffic.

The critical property defenders must understand: this technique produces almost no traditional indicators. There is no suspicious child process, no credential access, no privilege escalation. The only reliable observables are (a) watch registration itself, (b) enumeration of /proc/*/fd inotify descriptors, and (c) execution of filesystem-watch tooling.

Exploitation Status

This is a research disclosure with demonstrated proof-of-concept, not a confirmed in-the-wild campaign, and it is not in CISA KEV. However, the barrier to weaponization is effectively zero — the APIs are documented, the code is trivial, and no vulnerability needs to be exploited. Treat this as an emerging TTP and instrument detection now, before commodity malware authors productize it (history suggests they will: similar side-channels via procfs and perf events were absorbed into spyware families within a year of disclosure).

Detection & Response

Detection strategy has three pillars: (1) execution of filesystem-watch tooling, (2) enumeration of inotify/watch descriptors, and (3) USN Journal access on Windows. High-fidelity signals exist for tooling execution and journal access; watch registration by custom binaries requires syscall-level telemetry (eBPF/Falco/auditd fanotify/inotify_add_watch rules) which most EDRs do not capture by default — enable auditd syscall auditing on sensitive Linux hosts.

YAML
---
title: Filesystem Watch Tooling Execution (Linux/macOS)
id: 3f8a2c14-7b5e-4d91-a6c2-9e1f4b8d7a30
status: experimental
description: Detects execution of filesystem event monitoring utilities that can be abused to passively surveil user file activity (keystroke timing, browsing, messaging app events) as described in recent side-channel research.
references:
  - https://www.securityweek.com/windows-linux-android-file-notification-systems-leak-user-activity/
  - https://attack.mitre.org/techniques/T1083/
author: Security Arsenal
date: 2026/02/09
tags:
  - attack.discovery
  - attack.collection
  - attack.t1083
logsource:
  category: process_creation
  product: linux
detection:
  selection_img:
    Image|endswith:
      - '/inotifywait'
      - '/inotifywatch'
      - '/fswatch'
      - '/watchmedo'
  selection_cli:
    CommandLine|contains:
      - 'inotify_add_watch'
      - 'fanotify_mark'
  condition: selection_img or selection_cli
falsepositives:
  - Legitimate developer/build tooling (webpack, nodemon, cargo-watch) using fswatch
  - Backup and sync agents
level: medium
---
title: USN Journal Read via Fsutil (Windows)
id: 8c1d4e62-3a97-4f25-b8d1-2c6e9a5f1047
status: experimental
description: Detects reading of the NTFS USN change journal, which can be abused to reconstruct user file activity (browser cache writes, temp files) as a passive surveillance side-channel.
references:
  - https://www.securityweek.com/windows-linux-android-file-notification-systems-leak-user-activity/
  - https://attack.mitre.org/techniques/T1083/
author: Security Arsenal
date: 2026/02/09
tags:
  - attack.discovery
  - attack.t1083
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    Image|endswith: '\fsutil.exe'
    CommandLine|contains:
      - 'usn readjournal'
      - 'usn enumdata'
      - 'usn readdata'
falsepositives:
  - Forensic/IR tooling and backup software
  - Administrators auditing file system changes
level: medium
---
title: Inotify Descriptor Enumeration via Procfs (Linux)
id: 5b9e3a71-1f46-4c83-92de-7a2c6d8b1e54
status: experimental
description: Detects processes enumerating inotify file descriptors under /proc, a reconnaissance or abuse pattern associated with filesystem-notification side-channel surveillance.
references:
  - https://www.securityweek.com/windows-linux-android-file-notification-systems-leak-user-activity/
  - https://attack.mitre.org/techniques/T1057/
author: Security Arsenal
date: 2026/02/09
tags:
  - attack.discovery
  - attack.t1057
logsource:
  category: process_creation
  product: linux
detection:
  selection:
    CommandLine|contains:
      - '/proc/*/fd'
      - '/proc/self/fd'
      - 'fdinfo'
  filter_known_tools:
    Image|endswith:
      - '/lsof'
      - '/ls'
  condition: selection and not filter_known_tools
falsepositives:
  - System administration scripts inspecting open descriptors
  - Container runtime health checks
level: low
KQL — Microsoft Sentinel / Defender
// Hunt for filesystem-watch tooling and journal access across Windows and Linux endpoints
// Union Windows process telemetry with Linux Syslog/audit ingestion in Sentinel
let watchToolNames = dynamic(["inotifywait", "inotifywatch", "fswatch", "watchmedo", "fsutil.exe"]);
let linuxProc =
    Syslog
    | where TimeGenerated > ago(7d)
    | where ProcessName in~ ("inotifywait", "inotifywatch", "fswatch")
       or SyslogMessage has_any ("inotify_add_watch", "fanotify_mark", "usn readjournal")
    | project TimeGenerated, Computer, ProcessName, SyslogMessage, HostIP;
let winProc =
    DeviceProcessEvents
    | where TimeGenerated > ago(7d)
    | where FileName in~ (watchToolNames)
       or ProcessCommandLine has_any ("usn readjournal", "usn enumdata", "inotify_add_watch")
    | project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName;
union linuxProc, winProc
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
    by DeviceName = coalesce(DeviceName, Computer), FileName = coalesce(FileName, ProcessName), ProcessCommandLine = coalesce(ProcessCommandLine, SyslogMessage)
| order by EventCount desc;
VQL — Velociraptor
-- Hunt for processes holding inotify/fanotify watches or watch tooling on Linux endpoints
-- Identifies both watch-utility execution and processes with active inotify descriptors
SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(inotifywait|inotifywatch|fswatch|watchmedo|fanotify_mark|inotify_add_watch)'
   OR Exe =~ '(?i)(inotify|fswatch)'

-- Complement on Linux clients: enumerate open inotify descriptor links
SELECT Pid, Fd, Target AS WatchDescriptor
FROM glob(globs='/proc/*/fd/*', accessor='raw_file')
WHERE Target =~ 'anon_inode:inotify'
   OR Target =~ 'anon_inode:\[fanotify\]'

The following Bash audit script inventories which processes on a Linux host currently hold inotify/fanotify watches and flags non-baselined watchers. Run it on multi-user systems, jump hosts, and developer workstations:

Bash / Shell
#!/bin/bash
# audit_fs_watchers.sh — Inventory processes holding inotify/fanotify watches
# Run as root. Baseline output and alert on deviations.

BASELINE="/etc/security/fs_watchers_baseline.txt"
REPORT="/var/log/fs_watch_audit_$(date +%Y%m%d_%H%M%S).log"

echo "=== Filesystem Watch Audit: $(hostname) $(date -Iseconds) ===" | tee "$REPORT"

# Enumerate all anon_inode:inotify / fanotify descriptors across processes
for pid in $(ls /proc | grep -E '^[0-9]+$'); do
  for fd in /proc/$pid/fd/*; do
    target=$(readlink "$fd" 2>/dev/null)
    case "$target" in
      anon_inode:inotify|"anon_inode:[fanotify]"*)
        comm=$(cat /proc/$pid/comm 2>/dev/null)
        cmdline=$(tr '\0' ' ' < /proc/$pid/cmdline 2>/dev/null)
        uid=$(stat -c %u /proc/$pid 2>/dev/null)
        echo "PID=$pid UID=$uid COMM=$comm TYPE=$target CMD=$cmdline" | tee -a "$REPORT"
        ;;
    esac
  done
done

# Check for watch tooling binaries present on disk
echo "--- Watch tooling binaries ---" | tee -a "$REPORT"
for tool in inotifywait inotifywatch fswatch watchmedo; do
  which "$tool" 2>/dev/null && echo "FOUND: $tool" | tee -a "$REPORT"
done

# Diff against baseline if one exists
if [ -f "$BASELINE" ]; then
  echo "--- Deviations from baseline ---" | tee -a "$REPORT"
  grep '^PID=' "$REPORT" | awk -F'CMD=' '{print $2}' | sort -u > /tmp/current_watchers.txt
  comm -13 <(sort -u "$BASELINE") /tmp/current_watchers.txt | while read -r dev; do
    echo "NEW WATCHER: $dev" | tee -a "$REPORT"
  done
else
  echo "No baseline found at $BASELINE — create one from a known-good state." | tee -a "$REPORT"
fi

# Report sysctl limits that constrain watch abuse surface
echo "--- inotify limits ---" | tee -a "$REPORT"
sysctl fs.inotify.max_user_watches fs.inotify.max_user_instances 2>/dev/null | tee -a "$REPORT"

Remediation

Because this is an architectural side-channel rather than a patchable vulnerability, remediation is about reducing observability and restricting who can watch what:

  1. Constrain inotify capacity on Linux. Lower fs.inotify.max_user_watches (default 524,288) and fs.inotify.max_user_instances (default 128) to the minimum your legitimate workloads require — e.g., fs.inotify.max_user_instances=8 on multi-user servers. This does not eliminate the channel but sharply limits recursive surveillance scope. Persist via /etc/sysctl.d/90-inotify-hardening.conf.
  2. Audit syscall-level watch registration. Deploy auditd rules on sensitive Linux hosts: -a always,exit -F arch=b64 -S inotify_add_watch -S fanotify_mark -k fs_watch. Forward to your SIEM and alert on watchers targeting browser profile paths (~/.mozilla, ~/.config/google-chrome, ~/.config/chromium) or messaging app directories.
  3. Enforce Android Scoped Storage and app hygiene. On managed Android fleets, use your MDM to deny MANAGE_EXTERNAL_STORAGE (all-files access) to all but explicitly approved apps, keep devices on current Android versions (each release further restricts cross-app media visibility), and audit installed apps for unnecessary storage permissions. WhatsApp and similar apps should be kept current as vendors relocate staging paths into protected storage.
  4. Windows: restrict USN Journal and monitor directory handles. Audit fsutil usn execution (see Sigma rule above), alert on non-forensic processes reading the USN journal, and use EDR with handle-visibility to flag processes holding recursive ReadDirectoryChangesW handles on C:\Users\ trees without a legitimate reason (backup agents, search indexers are the normal holders).
  5. Reduce the signal at the source. Where feasible, direct browsers to use memory-backed caches on high-risk shared systems, disable IME/browser temp-file persistence, and ensure messaging apps store media in app-private storage rather than shared paths.
  6. Baseline and hunt. Run the audit script above across your Linux fleet, establish a known-good watcher baseline, and alert on deviations. Treat unexpected inotify holders the way you treat unexpected listeners — as a presumptive-compromise indicator worth triage.

Track the researchers' publication and any follow-on OS vendor guidance via the original SecurityWeek coverage: https://www.securityweek.com/windows-linux-android-file-notification-systems-leak-user-activity/. No vendor patch exists; expect mitigations to arrive as incremental permission hardening in future OS releases rather than a discrete update.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.