Your File-Integrity Monitor Is Probably Hashing Your Movie Folder
I went to fix one small thing on the friend’s Lenovo Legion and found a file-integrity monitor that had been quietly trying to checksum a Star Wars movie. This is the post-mortem on why that happens by default on Debian and Ubuntu, how I noticed, and the short scope file that turned a useless tripwire into a real one.
The trigger was boring. The system dashboard flagged that dailyaidecheck.service was in a failed state. AIDE is the Advanced Intrusion Detection Environment, a host integrity checker. It takes a cryptographic fingerprint of every file it monitors, stores that in a database, and on each run it compares the current filesystem against the stored database. If a system binary changes when no package update explains it, AIDE tells you. That is the entire value proposition: it notices tampering you did not authorize.
A failed AIDE service is the kind of thing that looks like a five-minute fix. It was not.
The database had never been built
The first cause was simple. There was no database. The directory /var/lib/aide/ held a single cache file and no aide.db at all. A check with nothing to compare against fails immediately, which is exactly what the service had been doing every night. So I triggered a rebuild with aideinit and moved on to the next item, expecting it to finish in a couple of minutes.
It did not finish in a couple of minutes.
The receipts: caught reading a film
Twenty-four minutes later the rebuild was still running at 97 percent of one core. That is not normal for a system-integrity scan. A tripwire fingerprints /etc, /usr, /bin, the parts of the system that hold executable code and configuration. On a normal laptop that is somewhere between ten and fifteen gigabytes and it takes a few minutes of hashing.
So I looked at what the process actually had open. The aide worker had read 49 gigabytes by that point, and the file descriptor it was sitting on was a movie file in the friend’s home directory. /home, on this machine, holds 146 gigabytes of Ollama models, downloaded video, and a browser cache. The tripwire was hashing all of it. It had walked out of the system directories, into the home partition, and was grinding through a film at two gigabytes a minute with another hundred-plus gigabytes ahead of it.
That is the bug. Not a crash, not a permission error. The monitor was doing exactly what its configuration told it to do, and the configuration was wrong.
The default selection is the whole filesystem
The Debian and Ubuntu AIDE packages ship a configuration assembled from fragments in /etc/aide/aide.conf.d/. The selection line, the rule that says which paths to monitor, lives in a fragment named 99_aide_root and reads:
/ 0 Full
That single line selects the root of the filesystem with the Full rule group and recurses without limit. Everything under / is in scope unless a more specific negative rule prunes it. The package fragments do prune a handful of package-specific paths, the apt cache, a few service state directories. They do not prune /home. They do not prune /data. They do not prune /run, which on a desktop holds the user’s gvfs FUSE mounts that AIDE cannot even stat.
On a server with no user data this default is defensible. On a workstation it means the integrity monitor fingerprints your home directory every single night. Your models, your media, your ~/.cache, all of it gets a SHA-256 pass and a database entry.
Why this is worse than running nothing
A tripwire that scans your home directory fails in two directions at once.
The runtime problem is obvious from the 49-gigabyte receipt. A nightly job that has to hash 150 gigabytes will run for an hour or more and hammer the disk while it does. On a laptop that often means the scan is still running when the machine suspends, so it never completes cleanly and the service stays in a failed state, which is where this whole investigation started.
The alerting problem is the one that actually breaks security. The point of a tripwire is that a change is an event worth reading. If the database includes /home, then every model you pull, every file you save, every browser-cache write produces a difference on the next run. The morning report becomes a wall of legitimate changes. Nobody reads a wall. After the third day of noise the human stops opening the report, and a tripwire that nobody reads detects nothing. An ignored monitor is worse than an absent one, because it costs disk and CPU and buys a false sense of coverage.
The fix is a scope file, not an edit
The instinct is to edit the 99_aide_root fragment and change the selection. That is the wrong move, because the fragment is package-owned and the next AIDE update will overwrite it. The right move is to add your own fragment that prunes the paths a tripwire has no business reading.
AIDE resolves overlapping rules by longest match, so a negative rule for a specific path wins over the broad / selection regardless of which fragment loads first. That property is what makes a separate scope file safe. I wrote one fragment, /etc/aide/aide.conf.d/99_aide_local_excludes:
# Scope AIDE to system integrity (/etc /usr /bin /sbin /lib /boot /opt /root).
# Exclude user data and large, volatile, or virtual trees, or the nightly
# run takes hours and the report fills with legitimate changes.
!/home
!/data
!/mnt
!/media
!/run
!/proc
!/sys
!/dev
!/tmp
!/var/tmp
!/var/log
!/var/cache
!/var/lib/docker
!/var/lib/containerd
!/var/lib/flatpak
!/var/lib/aide
A ! prefix in AIDE is a negative rule: the path and everything under it is excluded. After writing the fragment I ran aide --config-check to confirm the config still parsed, then rebuilt the database with aideinit.
The second run finished in about twelve minutes. The resulting aide.db is 81 megabytes and holds 366,991 entries, against a first run that was past 49 gigabytes of reads before I killed it. The difference between those two numbers is the entire point.
Verifying the scope, not trusting it
A config file that looks correct is not the same as a database with the right contents. AIDE stores its database as a flat list of paths, so you can check exactly what it monitors by reading it directly. The database is plain text under a gzip wrapper:
zcat -f /var/lib/aide/aide.db | grep -c '^/home/' # 0
zcat -f /var/lib/aide/aide.db | grep -c '^/data/' # 0
zcat -f /var/lib/aide/aide.db | grep -c '^/run/' # 0
zcat -f /var/lib/aide/aide.db | grep -c '^/etc/' # 3008
zcat -f /var/lib/aide/aide.db | grep -c '^/usr/bin/' # 1795
Zero entries for /home, /data, and /run. Three thousand for /etc, eighteen hundred for /usr/bin. That is what a system-integrity database should look like. The scope is now the executable and configuration surface, which is the surface an attacker would actually tamper with, and nothing else.
One trap to note while you verify. If you rebuild the database while anything is moving files around underneath it, a check run during that window will report differences that are not real tampering, just the filesystem changing mid-scan. I hit exactly that and spent ten minutes convinced the fix had not worked before I realized the check had overlapped a separate operation. Read the database contents to confirm scope. Do not trust the output of a check that ran during a busy moment.
How to check your own box
This is not a setting most people chose. It is the package default, so if you installed AIDE from apt and never touched the fragments, you very likely have it. The check is one command:
grep -rhE '^\s*/[a-zA-Z]' /etc/aide/aide.conf.d/*root* /etc/aide/aide.conf 2>/dev/null
If the output contains a bare / ... Full selection and you do not see a matching !/home exclusion anywhere in /etc/aide/aide.conf.d/, your nightly integrity scan is reading your home directory. Add a scope fragment like the one above, run aide --config-check, rebuild with aideinit, and grep the database to confirm.
What it cost and what it bought
The whole fix is one file with sixteen lines and a twelve-minute rebuild. What it bought is a tripwire that finishes its nightly run, produces a report short enough that a human will actually read it, and watches the part of the disk where tampering would actually show up. Before the change the monitor was hashing 150 gigabytes of models and films, running for over an hour, failing to complete, and producing noise nobody would read. The default was not malicious. It was just written for a server and shipped onto a laptop, and the gap between those two cases is where the bug lived.
The general lesson sits one level above AIDE. A security tool that is configured to watch everything watches nothing in practice, because the signal drowns in the volume. Scope is not a nice-to-have for a tripwire. Scope is the feature.