This issue respects the following points:
Which variant of the Monitoring Plugins do you use?
Bug description
When using the file-ownership plugin with additional --filename parameters, the default file list is still evaluated. Because --filename uses action='append' together with default=DEFAULT_FILES, the default list and user-supplied entries are merged without deduplication.
This leads to:
- duplicate checks for the same path
- conflicting "Expected" values if a default entry is redefined via --filename
- duplicate output lines
Example
Command:
file-ownership --filename root:sysinst,/etc/ssh/sshd_config
Result
/etc/ssh/sshd_config ! root:root ! root:sysinst
...
/etc/ssh/sshd_config ! root:sysinst ! root:sysinst
The first line comes from DEFAULT_FILES, the second from the custom --filename.
Expected behavior
One of the following:
- Either
--filename should override default entries for identical paths
- Or the plugin should deduplicate by path (last definition wins)
- Or there should be an option to disable the default file list entirely
Technical cause
In file-ownership:
parser.add_argument(
'--filename',
action='append',
default=DEFAULT_FILES,
...
)
This merges DEFAULT_FILES and user-defined values without deduplication.
Proposed fix
Deduplicate entries by path after parsing arguments. Example approach:
merged = {}
for spec in args.FILES:
if not spec:
continue
owner_group, path = spec.split(',', 1)
merged[path] = owner_group # last definition wins
Then iterate over merged.items() instead of the raw list.
Steps to reproduce - Plugin call
'/usr/lib64/nagios/plugins/file-ownership' '--filename' 'root:root,/boot/grub/grub.conf' '--filename' 'root:root,/boot/grub2/grub.cfg' '--filename' 'root:root,/boot/grub2/grubenv' '--filename' 'root:root,/boot/grub2/user.cfg' '--filename' 'root:root,/etc/anacrontab' '--filename' 'root:root,/etc/at.allow' '--filename' 'root:root,/etc/cron.allow' '--filename' 'root:root,/etc/cron.d' '--filename' 'root:root,/etc/cron.daily' '--filename' 'root:root,/etc/cron.hourly' '--filename' 'root:root,/etc/cron.monthly' '--filename' 'root:root,/etc/cron.weekly' '--filename' 'root:root,/etc/crontab' '--filename' 'graylog:graylog,/etc/graylog/certs' '--filename' 'root:root,/etc/group' '--filename' 'root:root,/etc/group-' '--filename' 'root:root,/etc/hosts.allow' '--filename' 'root:root,/etc/hosts.deny' '--filename' 'root:root,/etc/issue' '--filename' 'root:root,/etc/issue.net' '--filename' 'lool:lool,/etc/loolwsd/loolwsd.xml' '--filename' 'root:root,/etc/motd' '--filename' 'root:named,/etc/named.conf' '--filename' 'root:root,/etc/passwd' '--filename' 'root:root,/etc/passwd-' '--filename' 'root:sysinst,/etc/ssh/sshd_config' '--filename' 'root:root,/etc/sssd/sssd.conf' '--filename' 'vdsm:kvm,/home/ovirt' '--filename' 'root:root,/tmp' '--filename' 'icinga:icinga,/tmp/linuxfabrik-monitoring-plugins-sqlite.db' '--filename' 'hnet:hnet,/var/hnet' '--filename' 'unbound:unbound,/var/lib/unbound/root.key' '--filename' 'ldap:ldap,/var/run/openldap'
Steps to reproduce - Data
Output:
One or more problems with owners or groups.
Path ! Expected ! Found
---------------------+--------------+-----------------------
/etc/anacrontab ! root:root ! root:root
/etc/cron.d ! root:root ! root:root
/etc/cron.daily ! root:root ! root:root
/etc/cron.hourly ! root:root ! root:root
/etc/cron.monthly ! root:root ! root:root
/etc/cron.weekly ! root:root ! root:root
/etc/crontab ! root:root ! root:root
/etc/group ! root:root ! root:root
/etc/group- ! root:root ! root:root
/etc/hosts.allow ! root:root ! root:root
/etc/hosts.deny ! root:root ! root:root
/etc/issue ! root:root ! root:root
/etc/issue.net ! root:root ! root:root
/etc/motd ! root:root ! root:root
/etc/passwd ! root:root ! root:root
/etc/passwd- ! root:root ! root:root
/etc/ssh/sshd_config ! root:root ! root:sysinst
/tmp ! root:root ! root:root
/etc/anacrontab ! root:root ! root:root
/etc/cron.d ! root:root ! root:root
/etc/cron.daily ! root:root ! root:root
/etc/cron.hourly ! root:root ! root:root
/etc/cron.monthly ! root:root ! root:root
/etc/cron.weekly ! root:root ! root:root
/etc/crontab ! root:root ! root:root
/etc/group ! root:root ! root:root
/etc/group- ! root:root ! root:root
/etc/hosts.allow ! root:root ! root:root
/etc/hosts.deny ! root:root ! root:root
/etc/issue ! root:root ! root:root
/etc/issue.net ! root:root ! root:root
/etc/motd ! root:root ! root:root
/etc/passwd ! root:root ! root:root
/etc/passwd- ! root:root ! root:root
/etc/ssh/sshd_config ! root:sysinst ! root:sysinst
/tmp ! root:root ! roo
```t:root
### Environment
5.14.0-611.34.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Feb 23 12:07:36 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
Rocky Linux release 9.7 (Blue Onyx)
### Plugin Version
file-ownership: v2025061901 by Linuxfabrik GmbH, Zurich/Switzerland
### Python version
Python 3.9.25
### List of Python modules
_No response_
### Additional Information
_No response_
This issue respects the following points:
Which variant of the Monitoring Plugins do you use?
Bug description
When using the
file-ownershipplugin with additional--filenameparameters, the default file list is still evaluated. Because--filenameusesaction='append'together withdefault=DEFAULT_FILES, the default list and user-supplied entries are merged without deduplication.This leads to:
Example
Command:
file-ownership --filename root:sysinst,/etc/ssh/sshd_configResult
The first line comes from DEFAULT_FILES, the second from the custom
--filename.Expected behavior
One of the following:
--filenameshould override default entries for identical pathsTechnical cause
In
file-ownership:This merges DEFAULT_FILES and user-defined values without deduplication.
Proposed fix
Deduplicate entries by path after parsing arguments. Example approach:
Then iterate over
merged.items()instead of the raw list.Steps to reproduce - Plugin call
'/usr/lib64/nagios/plugins/file-ownership' '--filename' 'root:root,/boot/grub/grub.conf' '--filename' 'root:root,/boot/grub2/grub.cfg' '--filename' 'root:root,/boot/grub2/grubenv' '--filename' 'root:root,/boot/grub2/user.cfg' '--filename' 'root:root,/etc/anacrontab' '--filename' 'root:root,/etc/at.allow' '--filename' 'root:root,/etc/cron.allow' '--filename' 'root:root,/etc/cron.d' '--filename' 'root:root,/etc/cron.daily' '--filename' 'root:root,/etc/cron.hourly' '--filename' 'root:root,/etc/cron.monthly' '--filename' 'root:root,/etc/cron.weekly' '--filename' 'root:root,/etc/crontab' '--filename' 'graylog:graylog,/etc/graylog/certs' '--filename' 'root:root,/etc/group' '--filename' 'root:root,/etc/group-' '--filename' 'root:root,/etc/hosts.allow' '--filename' 'root:root,/etc/hosts.deny' '--filename' 'root:root,/etc/issue' '--filename' 'root:root,/etc/issue.net' '--filename' 'lool:lool,/etc/loolwsd/loolwsd.xml' '--filename' 'root:root,/etc/motd' '--filename' 'root:named,/etc/named.conf' '--filename' 'root:root,/etc/passwd' '--filename' 'root:root,/etc/passwd-' '--filename' 'root:sysinst,/etc/ssh/sshd_config' '--filename' 'root:root,/etc/sssd/sssd.conf' '--filename' 'vdsm:kvm,/home/ovirt' '--filename' 'root:root,/tmp' '--filename' 'icinga:icinga,/tmp/linuxfabrik-monitoring-plugins-sqlite.db' '--filename' 'hnet:hnet,/var/hnet' '--filename' 'unbound:unbound,/var/lib/unbound/root.key' '--filename' 'ldap:ldap,/var/run/openldap'
Steps to reproduce - Data
Output: