
Research artifacts for file-notification side-channel attacks on Linux, Windows, and macOS, demonstrating inotify/FSEvents leakage, keystroke timing, and website fingerprinting.
This repository contains the artifacts for the paper "File Notification Attacks: Templating and Exploiting Side-Channel Leakage from the File-Notification Systems on Linux, Windows, and macOS", accepted at CCS '26.
Visit the website with demos at: https://inoti.fyi/
The full artifact, including the VM image, is archived on Zenodo at: https://zenodo.org/records/22843469
Read the paper at: https://snee.la/pdf/pubs/file-notification-attacks.pdf or http://inoti.fyi/pubs/file-notification-attacks.pdf
As a part of artifact evaluation at CCS'26, we shipped a Debian 13 + KDE Plasma 6 VM with a pre-patched kernel. This VM was not used to produce the paper's evaluation results and is not intended to reproduce their exact magnitude.
Find this VM at: https://zenodo.org/records/22843469 (linux-vm.tar)
We employed Claude (Opus 4.8) for wrapping our code into decently well-documented and high-performant artifacts (for example, the Windows one was a bit laggy). However, the code, scripts, makefiles it generated were based on our own code used for the paper.
The VM exists purely for convenience, so that mounting each attack does not require an environment setup from scratch, or a kernel downgrade. The underlying mechanism demonstrated in the VM is identical to the one described in the paper, but please note that we did not use the VM to produce the numbers reported in the paper. Absolute timings may differ due to the virtualized environment and underlying hardware.
If you would like to run this on your own Linux system (specifically the /dev/
leakage below), the kernel you use must predate
the fsnotify fix (CVE-2025-68788). The shipped VM already runs a vulnerable
kernel (6.12.43+deb13-amd64).
Findings are reproduced inside a Debian 13 VM (linux-vm/), installed from the
official live Debian ISO with KDE Plasma 6 (Wayland) installed with a kernel
that predates the fsnotify
fix.
inotify-tools, Qt6 dev headers, and pkexec are installed. Nothing else is
upgraded, and the kernel is never touched after install. Please DO NOT run
apt upgrade or attempt to upgrade the kernel. This VM image is
deliberately old, is not up to date, and does not have the latest security
patches. This VM image is only meant for quick validation and testing!
The code, attacks, and demonstrations located within the VM are mirrored in
Linux/.
Note: We mention as which user to run the commands at the top of each
command block. There is the [host], which is the host machine which runs the
VM, [user] which is the victim of the attacks in the VM, and [spyuser] which
requires to be set up and will be the attacker in most Linux attacks.
The disk image is shipped as linux-vm-upload.qcow2, compressed with zstd.
Rename it to linux-vm.qcow2 before running run.sh (which expects that
filename):
# Run As: [host]
cd linux-vm/
mv linux-vm-upload.qcow2 linux-vm.qcow2
./run.sh
Reading zstd-compressed qcow2 requires qemu-img/qemu-system-x86_64 version
5.2 or newer (2020+), check with qemu-img --version. If you're stuck on an
older QEMU and it fails to open the image, decompress it into a flat qcow2
first:
qemu-img convert -O qcow2 linux-vm-upload.qcow2 linux-vm.qcow2
4 cores, 4GB RAM, GUI display. Logins are:
root, password password,user, password password,spyuser, password password (do not login as spyuser!)The supplied VM already runs a vulnerable, pre-patched kernel
(6.12.43+deb13-amd64), so no downgrade is needed to use it. You will need QEMU
to run this image (which has a GUI). The artifact lives at
/home/user/Linux-File-Notification-Attacks inside the VM.
One command sets things up fresh in the VM: (i) an unprivileged spyuser
account (non-sudo), (ii) its own copy of the artifact directory (a separate
unprivileged account cannot traverse into user's home directory otherwise),
(iii) and every script made executable in both copies.
# In the VM, Run As: [user]
sudo bash ~/Linux-File-Notification-Attacks/setup_attacks.sh
Every attack below runs as spyuser (su - spyuser, password password),
except auth-ui-redress, which runs as user (explained below).
Proves file-operation notifications are delivered on files that cannot be read directly, as long as their parent directory is readable.
# Run As: [spyuser]
# To switch to spyuser, in a new terminal type `su - spyuser`. The password
# is `password`.
cd ~/Linux-File-Notification-Attacks/unreadable-file-bypass
./watch-syslog.sh
Leave it running, then generate a log line from another terminal as user:
# Run As: [user]
logger "hello"
This Debian 13 image has no rsyslog, so there is no /var/log/syslog file as
shown in the paper. The script falls back to watching
/var/log/journal/<machine-id>/ instead. This is the same idea, as the
.journal files being monitored are owned by root (user) and
systemd-journal (group), neither of which are spyuser.
Expected output (shortened. Machine-id, timestamps, and which .journal
file is accessed will differ):
spyuser@inotify-artifact-debian:~/.../unreadable-file-bypass$ ./watch-syslog.sh
proof we can't read the journal files directly, as spyuser:
total 36384
drwxr-sr-x+ 2 root systemd-journal 4096 Jan 24 01:24 . # <-- directory IS readable
-rw-r-----+ 1 root systemd-journal 8388608 Jan 24 01:24 system.journal # <-- but files are 640 root:systemd-journal
-rw-r-----+ 1 root systemd-journal 8388608 Jan 24 01:24 user-1000.journal
...
cat: /var/log/journal/fdcae48e.../system.journal: Permission denied # <-- we cannot read them
watching /var/log/journal/fdcae48e... for writes, run 'logger "hello"' from another terminal now ...
Setting up watches.
Watches established.
# ...meanwhile, in a second terminal [user]: $ logger "hello"
01:24:33 user-1000.journal MODIFY # <-- We are told the file changed
Measures inotify's notification delay.
stats.py is the only part of the Linux artifact with a dependency (numpy) that
may not already be in the image:
# Run As: [user]
python3 -c "import numpy" 2>/dev/null || sudo apt install python3-numpy
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/temporal-resolution
./run.sh
watcher opens an inotify watch on a test file and timestamps every IN_ACCESS
it receives. accessor reads that same file 1000 times with a random 5-10ms
delay between reads, timestamping each read itself. stats.py diffs the two
timestamp recordings and prints the average/stddev/min delay between the read
happening and the notification arriving, i.e. the temporal resolution of
inotify.
Expected output (numbers may differ as this is from the VM):