Skip to content

fix: only report genuinely-installed packages in is_pkg_installed#326

Open
nicodarge wants to merge 1 commit into
ovh:masterfrom
nicodarge:fix_is_pkg_installed_false_positive
Open

fix: only report genuinely-installed packages in is_pkg_installed#326
nicodarge wants to merge 1 commit into
ovh:masterfrom
nicodarge:fix_is_pkg_installed_false_positive

Conversation

@nicodarge

Copy link
Copy Markdown

Summary

is_pkg_installed() reports packages as installed when they are not, because it keys off the dpkg desired-action field instead of the actual package status.

Root cause

dpkg -s "$PKG_NAME" 2>/dev/null | grep -q '^Status: install '

The Status: line is <desired-action> <error> <status>. The pattern ^Status: install only checks the desired-action field, so it also matches packages that are not installed but still carry an install selection, e.g.:

  • install ok not-installed (a leftover selection, e.g. after dpkg --set-selections)
  • install ok config-files
  • install ok half-installed

Impact

Every package-based check is affected. In practice this shows up on disable_http_server (2.2.10) and disable_http_proxy (2.2.13): a host that once had nginx/squid and still carries a residual install selection gets a false crit even though the package is gone.

Reproduction:

echo "nginx install" | dpkg --set-selections   # residual selection, nothing installed
dpkg -s nginx | grep '^Status:'                 # -> Status: install ok not-installed
# disable_http_server now crits on nginx, which is not installed

Fix

Query the real status field and match only the functionally-installed states:

dpkg-query -W -f='${db:Status-Status}' "$PKG_NAME" 2>/dev/null \
    | grep -Eqx 'installed|triggers-awaited|triggers-pending'

This is independent of the desired-action field, so:

  • residual install selections on absent packages are no longer reported as installed;
  • a held package (hold ok installed) is still correctly reported as installed;
  • triggers-awaited / triggers-pending (functionally installed) are matched.

The same inline pattern was duplicated in the auditd test scenarios (used to decide whether to install auditd before the test) and is updated to the same idiom.

How tested

  • shellcheck and shfmt -i 4 clean on all changed files.
  • Full functional test suite (debian docker target) passes; the affected auditd and disable_http_* scenarios run green.
  • Verified across the supported targets that dpkg-query -W -f='${db:Status-Status}' is available (dpkg ≥ 1.17).

is_pkg_installed matched '^Status: install ', which keys off the dpkg
*desired-action* field rather than the actual package status. A package
that is not installed but still carries an "install" selection (states
such as "install ok not-installed" or "install ok config-files") was
reported as installed.

This produced false positives in every package-based check: on hosts
with such residual selections, disable_http_server (2.2.10) and
disable_http_proxy (2.2.13) crit on nginx/squid that are not actually
installed.

Query the real status field via 'dpkg-query -W -f=${db:Status-Status}'
and match installed/triggers-awaited/triggers-pending (all functionally
installed). This is immune to the desired-action field, so a held package
("hold ok installed") is still reported as installed while residual
selections are not.

The same buggy pattern is also replaced in the auditd test scenarios.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant