Known limitations¶
This page enumerates the classes of finding where you should interpret the report with care.
Scope¶
privmap analyses local Linux privilege relationships. As of v2.0 it covers 35 distinct check categories spanning identity, filesystem permissions (including group-writable, sticky-suppressed), execution contexts (cron + systemd with config-argument and unqualified-binary chains), capabilities, login-time scripts, library loading, authentication (sudo, doas, PAM, polkit), SSH, network surfaces (NFS exports, fstab, hosts.equiv, listeners), container detection (Docker, LXC, k8s, writable bind mounts), PATH abuse, D-Bus policies, legacy super-servers (inetd, xinetd), and AppArmor.
It explicitly does not:
- Perform network enumeration or remote service fingerprinting. Listening ports are recorded but reachability is not probed.
- Run exploits or attempt actual privilege escalation.
- Cover Windows or macOS.
- Match installed binary versions against a CVE database. Pair with
trivy,grype, or your distribution's vulnerability scanner. - Scan application configuration files for embedded credentials
(Apache, MySQL, Tomcat, etc.; there are ~100 such checks in
LinPEAS). This overlaps with
gitleaksandtrufflehog. - Query cloud metadata services (AWS IMDS, GCP, Azure). Requires network egress, which privmap does not do.
- Inspect kernel exploits, container escapes from a non-root context, or hypervisor flaws.
- Read user shell history, mail spools, or browser data.
It is a structural analysis tool. Pair it with a vulnerability scanner, a secret scanner, and a network mapper for full coverage.
Argument-restricted sudo rules¶
Rules like sudo /usr/bin/systemctl restart nginx receive a reduced
exploitability score but are not fully argument-validated. A rule with
restricted arguments may still appear as a finding if the binary is on
the GTFOBins shell-escape list. privmap errs on the side of surfacing.
Full sudoers argument parsing (with glob, quote, and EXEC: / SETENV:
tag semantics) is hard to do correctly with regex and is currently
best-effort. If you depend on argument restriction for security,
validate the rule manually rather than relying on the scoring
difference.
Third-party capability binaries¶
The known-safe allowlist for capability binaries covers standard system
tools (snap-confine, ping, mtr, chronyd, and similar) on
Debian, Ubuntu, RHEL, and Fedora defaults. Capability binaries from
third-party packages are not on the allowlist and may produce false
positives if they legitimately need a dangerous capability for internal
use.
If you see a third-party capability binary repeatedly flagged on systems where it is known to be intentional, open a GitHub issue with the binary name, package source, and what it uses the capability for. The allowlist is updated regularly.
Snapshot mode conservatism¶
Snapshot mode falls back to conservative behavior when a check cannot be performed against an archive:
- Per-user
CAN_EXECchecks on capability binaries require the snapshot'spermissions.txt. If absent, the edge is not emitted. - Symlink resolution uses
readlink -f(transitive) in snapshot mode and rawos.readlink(single-step) in live mode. Results may differ on systems with chained symlinks. - Filesystem permission checks for sticky-bit handling are limited to what was captured.
Live mode is always more accurate. Use snapshot mode when live access is impossible (incident response, air-gapped systems) and interpret the results accordingly.
Cron command parsing¶
Cron and systemd command extraction handles shell separators (&&,
||, ;, |), drops leading env-var assignments, and only emits
absolute paths as EXECUTES targets. It does not:
- Resolve relative
$PATHlookups. - Expand
$VARIABLEreferences inside the command. - Parse complex pipelines beyond the head of each segment.
A cron entry that invokes a binary via $PATH lookup, or whose actual
target is deeply embedded in a shell pipeline, may not produce an
EXECUTES edge.
No CVE matching¶
privmap does not check binary versions against known vulnerabilities. Specifically:
- pkexec is filtered as auth-required. The PwnKit family (CVE-2021-4034 et al.) requires a vulnerability scanner to detect.
sudoitself is filtered as auth-required. Baron Samedit (CVE-2021-3156) and similar require a vulnerability scanner.- Kernel SUID exploit primitives (Dirty Cow, Dirty Pipe, and similar) are out of scope entirely.
Pair privmap with a CVE scanner (Trivy, Grype, or your distribution's auditing tool) for version-based findings.
Filesystem walk scope¶
The default scan paths (/etc, /usr, /opt, /tmp, /var)
deliberately exclude /home. Many real escalation paths originate in
user home directories (writable scripts, SSH keys, .bashrc injection
on shared hosts). Add /home to --scan-paths if your threat model
includes multi-user systems.
Large directories with no privilege relevance are pruned (/usr/share,
/var/log, /snap, and similar). If you are auditing an unusual
system where these contain escalation-relevant files, the prune list is
hardcoded in privmap.ingestion.filesystem.EXCLUDED_PATH_PREFIXES and
would need a PR to extend.
Group ACLs¶
Group-ACL entries (group:NAME:rw- in getfacl output) are expanded
into per-member CAN_WRITE edges. If group membership changes between
the ingestion run and the actual exploit attempt, the report may
overstate or understate access. Re-run after any gpasswd activity.
Performance on very large filesystems¶
The filesystem walk is single-threaded and not cached between runs. On
a server with millions of files in the scan paths, expect the walk to
be the dominant phase. Tightening --scan-paths is the main lever.
Parallel walk support is on the roadmap but not in 1.x.