Handbook sections

Effective configuration: the truth no file holds

Last reviewed

Pavois reads the configuration a service actually resolves, not the files that try to set it. The drop-in is the easy case; the real point is the state in no file at all: compiled-in defaults, resolved precedence, kernel values and generated units.

The drop-in is the easy case

The usual pitch goes: a file scanner reads /etc/ssh/sshd_config, misses the drop-in in sshd_config.d/, and reports a value that was overridden. True, but it undersells the point, because a competent file scanner can glob sshd_config.d/* too. If that were the whole story, parsing files more carefully would close the gap.

It isn't the whole story. The reason to ask the running system is that a large part of the effective configuration is in no file at all, and no amount of file parsing reaches it. Pavois shells out to sshd -T, sysctl, systemctl show, auditctl -l precisely because those commands return the resolved state, defaults and runtime included.

Three things no file tells you

1. Defaults nobody wrote

A directive you never set still has an effective value: the daemon's compiled-in default. sshd -T prints all ~90 effective directives, including the ones absent from every file in /etc/ssh. CIS and STIG routinely require a specific value for a directive most hosts leave unset (MaxAuthTries, ClientAliveInterval, LoginGraceTime). A file scanner that reads sshd_config and every drop-in still finds nothing to check: the value lives in the binary. Only asking the daemon tells you whether the default you rely on is the secure one.

2. Resolved precedence and kernel defaults

A running sysctl value is computed from a stack: the kernel built-in default, then /usr/lib/sysctl.d/, /run/sysctl.d/, /etc/sysctl.d/, /etc/sysctl.conf, last writer wins, across directories most people never look in. Reading /etc/sysctl.conf gives you one input out of six, and not even the authoritative one. sysctl net.ipv4.conf.all.rp_filter returns the single value the kernel is enforcing right now; reconstructing it from files means re-implementing the kernel precedence rules and hoping you got the ordering right.

3. State with no file

Some configuration has no source file to read. systemd generators synthesize units at boot (systemd-fstab-generator turns /etc/fstab lines into live mount units, systemd-getty-generator spawns getty units), and systemctl show resolves vendor presets, drop-ins from a dozen directories and those generated units into one effective answer. Likewise auditctl -l lists the rules the kernel is actually enforcing, which can differ from audit/rules.d/ when augenrules merged them differently or a rule failed to load; and /proc/cmdline is what the kernel actually booted with, not what GRUB proposes. There is simply no file that holds the answer.

A worked SSH example

A real host, three files:

/etc/ssh/
├── sshd_config              # Include /etc/ssh/sshd_config.d/*.conf
│                            # PermitRootLogin yes
│                            # #MaxAuthTries 6     <- commented: left at default
└── sshd_config.d/
    ├── 50-cloud-init.conf   # PasswordAuthentication yes
    └── 99-hardening.conf    # PermitRootLogin no

Read only sshd_config and you conclude root login is allowed, wrong, the drop-in overrode it. Read every file and you get PermitRootLogin no, but you still find nothing about MaxAuthTries: it is commented everywhere. Now ask the daemon, the exact command Pavois runs:

sshd -T | grep -E 'permitrootlogin|passwordauthentication|maxauthtries'
# permitrootlogin no          <- resolved after the drop-in (file said yes)
# passwordauthentication yes  <- from the cloud-init drop-in
# maxauthtries 6              <- compiled default, in NO file at all

Three facts fall out that the files cannot give you together: the resolved permitrootlogin no (so ssh-disable-root-login, CIS 5.1.x / ANSSI BP-028 R33, passes), a passwordauthentication yes easy to miss by eye, and maxauthtries 6, the compiled default in no file, where CIS wants 4, so ssh-set-max-auth-tries fails. Pavois reports that third line as a real finding, with the effective value 6 as evidence.

Effective (runtime) vs persistent (config)

The two questions are different, and Pavois is explicit about which it answers per control:

Question Effective source (what Pavois reads) Persistent source
Is root SSH login on now? sshd -T sshd_config + drop-ins
Is rp_filter set now? sysctl net.ipv4... /etc/sysctl.d/*
Is the audit rule loaded? auditctl -l audit/rules.d/*
Did the kernel boot with this flag? /proc/cmdline /etc/default/grub
Is the unit enabled and sandboxed? systemctl show unit + drop-ins

Limits: runtime is not persistence

Reading the resolved state proves the current value; it does not prove the value survives a reboot. A sysctl -w set at runtime and never written to /etc/sysctl.d/ reads as compliant now and regresses on the next boot. That is why Pavois separates the two axes in its qualified verdict: a control can prove running without proving persistent, and the grade reflects that. Each control declares the evidence it gathers (runtime, persistent-config, inventory, filesystem), so the report never conflates true now with true after reboot. Effective configuration is necessary and powerful; it is not the same thing as persistence, and Pavois says so per control rather than pretending otherwise.

Why this is the whole design

Be precise about the line, because a careless version of this claim is wrong. SCAP is not purely file-based: OVAL has a sysctl_test that reads /proc/sys, and a systemdunitproperty_test that queries systemd, so "it only reads files" is false and an OpenSCAP maintainer will say so. The real, defensible line is narrower and still decisive: no SCAP probe asks the daemon itself. None runs sshd -T to get the value OpenSSH resolved after every Include, Match block and default; none reproduces first-keyword-wins precedence across an arbitrary include tree; none reads the effective policy of a service that keeps it in memory, not on disk. Pavois asks the program that owns the setting. That is what file parsing, however thorough, cannot reach. Pavois audits the resolved state because that is the only state an attacker, and your kernel, actually obeys.

FAQ

Why not just parse the config files carefully? Because compiled-in defaults, six-level sysctl precedence and generator-synthesized units have no file to parse. File parsing reaches drop-ins; it never reaches the state that lives only in the running kernel and daemons.

Does an effective PASS mean it survives a reboot? No. It proves the value is in force now. Persistence is a separate axis the qualified verdict tracks; a runtime-only pass is capped accordingly.

Which commands does Pavois run? The resolved-state ones: sshd -T, sysctl, systemctl show, auditctl -l, and reads of /proc/cmdline and /proc/self/mountinfo, never the bare config file when a daemon can report its effective state.