ignore_mounts is a performance option that removes fapolicyd visibility from a mounted tree. That can be useful for data-only mounts with high file churn, such as cache, log, or content-serving partitions. It should not be used to make policy denials disappear, and it should not be used for trees that applications treat as code or runtime input.
The practical rule is:
- ignore_mounts is for data-only mounts.
- noexec is required, but noexec is only the first check.
- The risk report shows whether the ignored tree still looks like code.
What ignore_mounts means
The ignore_mounts option is configured in fapolicyd.conf. It is a comma-separated list of absolute mount points that fapolicyd should not watch, even if the filesystem type is otherwise listed in watch_fs.
The paths must match the mount point names shown by /proc/mounts. The root filesystem is always monitored, and ignore_mounts cannot be combined with allow_filesystem_mark=1.
Each ignored mount must be mounted with noexec. If it is not, fapolicyd warns and monitors the mount instead.
That is the configuration side. The policy side is just as important: when a mount is ignored, fapolicyd does not receive the normal file access events for that mounted tree. Opens and reads inside that mount are not evaluated by fapolicyd policy.
This is why the option belongs on data-only mounts. It is reasonable to ignore a tree whose contents are logs, cache objects, uploaded documents, or other data that the workload does not load as code. It is not reasonable to ignore a runtime tree, plugin directory, dependency cache, developer workspace, or application install path.
Why noexec is required
The first guardrail is noexec. The Linux mount command documents noexec as a mount option that prevents direct execution of binaries from that filesystem mount(8).
That is necessary, but it is not sufficient.
noexec helps with direct execve() from the ignored mount. It does not mean the content is inert. A trusted program can still read files from that tree. Interpreters, plugin systems, Java runtimes, browser stacks, build tools, and application frameworks often treat files as instructions even when the kernel does not execute those files directly.
The risk is the blind spot. The kernel may block direct execution, but fapolicyd will not see a trusted runtime reading code-like content from an ignored mount.
![]() |
| noexec blocks direct execution, but ignored mounts still create blind spots for interpreter and plugin reads |
What changed in fapolicyd 1.6
--check-ignore_mounts already existed. Earlier releases checked whether the ignored mount was mounted noexec and looked for files matching the %languages macro.
fapolicyd 1.6 expands that operational check. The command still starts with the mount itself: whether the path exists, whether it is a directory, whether it is a mount point, and whether noexec is present. It then reports several risk categories:
- executable regular files
- ELF/shared objects
- archives/JARs/ZIPs
- bytecode caches
- plugin/runtime directories
- language/interpreter files
This is a natural evolution of providing all necessary information to make an informed decision. It is a broader evidence report for administrators who already chose, or are considering, an ignored mount.
Run the configured check:
fapolicyd-cli --check-ignore_mounts
Check one proposed mount:
fapolicyd-cli --check-ignore_mounts=/path/to/mount
Use verbose mode when you need the evidence behind the counts:
fapolicyd-cli --check-ignore_mounts=/path/to/mount --verbose
The summary is the quick view. --verbose shows the matching paths, the category, and MIME information when file type detection is available.
What the categories mean
The categories are practical signals. They do not prove that a file is malicious. They answer a narrower question:
Does this ignored mount still look data-only?Executable regular files are not automatically a vulnerability. On a mount that is supposed to be data-only, they are still useful evidence. An executable bit often means somebody expected the file to be run.
ELF/shared objects are native code. For a temporary download area, a few ELF files may be artifacts waiting to be scanned, unpacked, moved, or deleted. For a runtime path, plugin path, library path, application directory, or developer tree, they are a much stronger warning.
Archives/JARs/ZIPs are archives. They can hold documents, and they can hold code. JARs are the obvious case because Java runtimes consume them directly, but ZIP, wheel, egg, WAR, EAR, APK, tar, and compressed archives can also deliver programmatic content.
Bytecode caches are runtime-consumed programmatic content. Python .pyc files, Java .class files, WebAssembly modules, Emacs Lisp bytecode, Lua bytecode, and __pycache__ directories are all signals that the mount is not just inert data.
Plugin/runtime directories are directory-name signals, not proof. Names such as site-packages, node_modules, vendor, plugins, extensions, and gems should make an administrator ask which process reads from the tree and whether that process treats the contents as code.
Language/interpreter files are the original %languages style check. A trusted interpreter may still be able to run a script from an ignored noexec mount:
python3 /ignored/script.pyIf fapolicyd is not watching that mount, it will not see the interpreter open the script.
Reading the report
Read the report as a risk review, not as a magic yes/no scanner.
A clean result is the easiest case:
- the mount exists
- the mount is noexec
- risky category counts are zero
- the mount is genuinely data-only
- write access is controlled
- the workload does not load code from it
That does not mean risk is literally zero. It means the mount matches the design intent of ignore_mounts.
A mixed result needs context. Archives in a controlled intake area, stale executable bits on inert files, language files that no trusted interpreter reads, or empty plugin-looking directories may be explainable. This is where --verbose matters:
fapolicyd-cli --check-ignore_mounts=/path/to/mount --verbose
If the output is explainable, fix what can be fixed and document what remains. Useful controls include:
- remove stale executable bits
- move code and plugins to watched filesystems
- split data and runtime dependencies onto separate mounts
- restrict write access to the ignored mount
- run the check after application updates
- scan archive contents in a separate intake process
Some results should stop the change. Do not ignore a mount that contains active runtime directories, dependency trees, shared objects, language source, bytecode, or JARs that applications use directly.
Common stop cases include developer workspaces, home directories, application install directories, plugin directories, Python virtual environments, node_modules trees, Java application trees full of jars, container or image build directories, and shared writable locations where users can add scripts or code.
The problem is not that every file in those directories is bad. The problem is that the mount is not data-only. Ignoring it trades away policy visibility in a place where policy visibility is useful.
![]() |
| The ignored-mount risk report helps sort data-only mounts from runtime content that should stay watched. |
Exit status and review evidence
The command is usable in automation. A clean scan returns zero. Risk findings return non-zero so automated workflows can gate a proposed change.
For a proposed mount, capture both the report and the exit status:
fapolicyd-cli --check-ignore_mounts=/path/to/mount; echo "exit status: $?"
If the summary is not clean, include the verbose report:
fapolicyd-cli --check-ignore_mounts=/path/to/mount --verbose; echo "exit status: $?"
The exit status should not replace judgment. It should prevent accidental approval. A non-zero result means somebody needs to look at the matching paths and decide whether the mount is still appropriate for ignore_mounts.
For a change review, ask for:
- why the mount needs to be ignored
- proof that it is mounted noexec
- the --check-ignore_mounts summary
- the --verbose output if any category is non-zero
Show the active mount options:
findmnt -no TARGET,OPTIONS /path/to/mount
Then include the fapolicyd report:
fapolicyd-cli --check-ignore_mounts=/path/to/mount
That gives reviewers enough context to tell the difference between a data-only
cache partition and an application runtime tree.
A compact demo
A short demo can show why noexec and "data-only" are different claims. Use a throwaway mount, add representative files, run the checker, and remove the mount.
sudo mkdir -p /mnt/fapolicyd-ignore-demo
sudo mount -t tmpfs -o noexec,nosuid,nodev tmpfs /mnt/fapolicyd-ignore-demo
sudo install -m 755 /bin/true /mnt/fapolicyd-ignore-demo/native-helper
sudo mkdir -p /mnt/fapolicyd-ignore-demo/app/{__pycache__,site-packages}
printf 'print("hello")\n' | sudo tee /mnt/fapolicyd-ignore-demo/app/demo.py >/dev/null
printf 'not really bytecode\n' | sudo tee /mnt/fapolicyd-ignore-demo/app/__pycache__/demo.pyc >/dev/null
fapolicyd-cli --check-ignore_mounts=/mnt/fapolicyd-ignore-demo --verbose; echo "exit status: $?"
sudo umount /mnt/fapolicyd-ignore-demo
sudo rmdir /mnt/fapolicyd-ignore-demoThe useful part of the output is not the exact MIME string. It is that one ignored noexec mount can still produce concrete code-like risk categories.
The practical rule
ignore_mounts is a performance option with a security cost. Use it when the mount is data-only and the report agrees with that story.
If the report shows a few explainable artifacts, clean them up or add controls before moving ahead.
If the report shows active code, runtime dependencies, plugins, bytecode, shared objects, or interpreter files that applications use directly, do not ignore the mount. Split the data from the code, keep the runtime content on a watched filesystem, or solve the performance problem another way.
The improved --check-ignore_mounts report does not make the decision for you.
It gives you the evidence needed to make the decision defensibly.











