From 532c40d311fcf8160630b2dec7f7d9b877586cec Mon Sep 17 00:00:00 2001 From: damien cavagnini Date: Wed, 30 Jul 2025 10:09:28 +0200 Subject: [PATCH] feat: add debian12 scripts - at_is_restricted.sh -> 2.4.2.1 - wireless_interfaces_disabled.sh -> 3.1.2 - bluetooth_is_disabled.sh -> 3.1.3 - sudo_no_nopasswd.sh -> 5.2.4 - aide_is_installed.sh -> 6.1.1 --- .pre-commit-config.yaml | 7 + bin/hardening/aide_is_installed.sh | 66 ++++++++ bin/hardening/at_is_restricted.sh | 155 ++++++++++++++++++ bin/hardening/bluetooth_is_disabled.sh | 91 ++++++++++ bin/hardening/sudo_no_nopasswd.sh | 59 +++++++ bin/hardening/wireless_interfaces_disabled.sh | 81 +++++++++ hooks/check_is_executable.sh | 7 + tests/hardening/aide_is_installed.sh | 20 +++ tests/hardening/at_is_restricted.sh | 71 ++++++++ tests/hardening/bluetooth_is_disabled.sh | 36 ++++ tests/hardening/sudo_no_nopasswd.sh | 9 + .../hardening/wireless_interfaces_disabled.sh | 10 ++ 12 files changed, 612 insertions(+) create mode 100755 bin/hardening/aide_is_installed.sh create mode 100755 bin/hardening/at_is_restricted.sh create mode 100755 bin/hardening/bluetooth_is_disabled.sh create mode 100755 bin/hardening/sudo_no_nopasswd.sh create mode 100755 bin/hardening/wireless_interfaces_disabled.sh create mode 100755 hooks/check_is_executable.sh create mode 100644 tests/hardening/aide_is_installed.sh create mode 100644 tests/hardening/at_is_restricted.sh create mode 100644 tests/hardening/bluetooth_is_disabled.sh create mode 100644 tests/hardening/sudo_no_nopasswd.sh create mode 100644 tests/hardening/wireless_interfaces_disabled.sh diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f98f44e..dbb73cc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,3 +22,10 @@ repos: language: script pass_filenames: true files: "^(bin|tests)/hardening/" + - id: check_is_executable + name: check_is_executable.sh + description: Ensure checks are executables + entry: hooks/check_is_executable.sh + language: script + pass_filenames: true + files: "^bin/hardening/" diff --git a/bin/hardening/aide_is_installed.sh b/bin/hardening/aide_is_installed.sh new file mode 100755 index 0000000..2b69a55 --- /dev/null +++ b/bin/hardening/aide_is_installed.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +# run-shellcheck +# +# CIS Debian Hardening +# + +# +# Ensure AIDE is installed (Automated) +# + +set -e # One error, it's over +set -u # One variable unset, it's over + +# shellcheck disable=2034 +HARDENING_LEVEL=3 +# shellcheck disable=2034 +DESCRIPTION="Ensure AIDE is installed" +PACKAGE="aide" + +# This function will be called if the script status is on enabled / audit mode +audit() { + AIDE_INSTALLED=1 + is_pkg_installed "$PACKAGE" + if [ "$FNRET" != 0 ]; then + crit "$PACKAGE is absent!" + else + AIDE_INSTALLED=0 + ok "$PACKAGE is installed" + fi +} + +# This function will be called if the script status is on enabled mode +apply() { + audit + if [ "$AIDE_INSTALLED" -eq 1 ]; then + info "installing '$PACKAGE'" + apt_install "$PACKAGE" + info "'$PACKAGE' installed, please follow the documentation to init and configure it" + fi +} + +# This function will check config parameters required +check_config() { + : +} + +# Source Root Dir Parameter +if [ -r /etc/default/cis-hardening ]; then + # shellcheck source=../../debian/default + . /etc/default/cis-hardening +fi +if [ -z "$CIS_LIB_DIR" ]; then + echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment." + echo "Cannot source CIS_LIB_DIR variable, aborting." + exit 128 +fi + +# Main function, will call the proper functions given the configuration (audit, enabled, disabled) +if [ -r "${CIS_LIB_DIR}"/main.sh ]; then + # shellcheck source=../../lib/main.sh + . "${CIS_LIB_DIR}"/main.sh +else + echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening" + exit 128 +fi diff --git a/bin/hardening/at_is_restricted.sh b/bin/hardening/at_is_restricted.sh new file mode 100755 index 0000000..d681571 --- /dev/null +++ b/bin/hardening/at_is_restricted.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +# run-shellcheck +# +# CIS Debian Hardening +# + +# +# Ensure at is restricted to authorized users (Automated) +# + +set -e # One error, it's over +set -u # One variable unset, it's over + +# shellcheck disable=2034 +HARDENING_LEVEL=2 +# shellcheck disable=2034 +DESCRIPTION="Ensure at is restricted to authorized users" +PACKAGE="at" + +# This function will be called if the script status is on enabled / audit mode +audit() { + ALLOW_EXISTS=1 + ALLOW_VALID=0 + DENY_EXISTS=1 + DENY_EMPTY=1 + DENY_VALID=0 + + is_pkg_installed "$PACKAGE" + if [ "$FNRET" -eq 1 ]; then + ok "$PACKAGE is not installed" + else + does_file_exist "/etc/at.allow" + if [ "$FNRET" -eq 0 ]; then + ALLOW_EXISTS=0 + + if [ "$(stat -Lc '%U' /etc/at.allow)" != 'root' ]; then + ALLOW_VALID=1 + crit "'/etc/at.allow' is not owned by root" + fi + + group="$(stat -Lc '%G' /etc/at.allow)" + if [ "$group" != 'root' ] && [ "$group" != 'daemon' ]; then + ALLOW_VALID=1 + crit "'/etc/at.allow' is not owned by group root or group 'daemon'" + fi + + if [ "$(stat -Lc '%a' /etc/at.allow)" != '640' ]; then + ALLOW_VALID=1 + crit "'/etc/at.allow' perms is not '640'" + fi + + fi + + does_file_exist "/etc/at.deny" + if [ "$FNRET" -eq 0 ]; then + DENY_EXISTS=0 + is_file_empty "/etc/at.deny" + if [ "$FNRET" -eq 0 ]; then + DENY_EMPTY=0 + fi + + if [ "$(stat -Lc '%U' /etc/at.deny)" != 'root' ]; then + DENY_VALID=1 + crit "'/etc/at.deny' is not owned by root" + fi + + group="$(stat -Lc '%G' /etc/at.deny)" + if [ "$group" != 'root' ] && [ "$group" != 'daemon' ]; then + DENY_VALID=1 + crit "'/etc/at.deny' is not owned by group 'root' or group 'daemon'" + fi + + if [ "$(stat -Lc '%a' /etc/at.deny)" != '640' ]; then + DENY_VALID=1 + crit "'/etc/at.deny' perms is not '640'" + fi + + fi + + if [ "$ALLOW_EXISTS" -eq 1 ] && [ "$DENY_EXISTS" -eq 1 ]; then + ok "only superuser is allowed to run 'at' commands" + elif [ "$ALLOW_EXISTS" -eq 1 ] && [ "$DENY_EXISTS" -eq 0 ]; then + if [ "$DENY_EMPTY" -eq 0 ]; then + crit "all users are allowed to execute 'at' commands" + elif [ "$DENY_VALID" -eq 1 ]; then + crit "'/etc/at.deny' exists but is misconfigured" + else + ok "'/etc/at.deny' exists and is well configured" + fi + fi + + if [ "$ALLOW_EXISTS" -eq 0 ] && [ "$ALLOW_VALID" -eq 1 ]; then + crit "'/etc/at.allow' exists but is misconfigured" + elif [ "$ALLOW_EXISTS" -eq 0 ] && [ "$ALLOW_VALID" -eq 0 ]; then + ok "'/etc/at.allow' exists and is well configured" + fi + + fi + +} + +# This function will be called if the script status is on enabled mode +apply() { + audit + + if [ "$ALLOW_EXISTS" -eq 1 ] && [ "$DENY_EXISTS" -eq 0 ]; then + if [ "$DENY_EMPTY" -eq 0 ]; then + info "Removing '/etc/at.deny'" + rm -f /etc/at.deny + elif [ "$DENY_VALID" -eq 1 ]; then + info "set perms and owner on '/etc/at.deny'" + chmod 0640 /etc/at.deny + chown root /etc/at.deny + if [ "$(stat -Lc '%G' /etc/at.deny)" != "daemon" ]; then + chgrp root /etc/at.deny + fi + fi + fi + + if [ "$ALLOW_EXISTS" -eq 0 ] && [ "$ALLOW_VALID" -eq 1 ]; then + info "set perms and owner on '/etc/at.allow'" + chmod 0640 /etc/at.allow + chown root /etc/at.allow + if [ "$(stat -Lc '%G' /etc/at.allow)" != "daemon" ]; then + chgrp root /etc/at.allow + fi + fi + +} + +# This function will check config parameters required +check_config() { + : +} + +# Source Root Dir Parameter +if [ -r /etc/default/cis-hardening ]; then + # shellcheck source=../../debian/default + . /etc/default/cis-hardening +fi +if [ -z "$CIS_LIB_DIR" ]; then + echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment." + echo "Cannot source CIS_LIB_DIR variable, aborting." + exit 128 +fi + +# Main function, will call the proper functions given the configuration (audit, enabled, disabled) +if [ -r "${CIS_LIB_DIR}"/main.sh ]; then + # shellcheck source=../../lib/main.sh + . "${CIS_LIB_DIR}"/main.sh +else + echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening" + exit 128 +fi diff --git a/bin/hardening/bluetooth_is_disabled.sh b/bin/hardening/bluetooth_is_disabled.sh new file mode 100755 index 0000000..1b4c7df --- /dev/null +++ b/bin/hardening/bluetooth_is_disabled.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# run-shellcheck +# +# CIS Debian Hardening +# + +# +# Ensure bluetooth services are not in use (Automated) +# + +set -e # One error, it's over +set -u # One variable unset, it's over + +# shellcheck disable=2034 +HARDENING_LEVEL=3 +# shellcheck disable=2034 +DESCRIPTION="Ensure bluetooth services are not in use." +PACKAGE='bluez' +SERVICE="bluetooth.service" + +# 2 scenario here: +# - bluez is a dependency for another package -> disable the service +# - bluez is not a dependency for another package -> remove the package + +# This function will be called if the script status is on enabled / audit mode +audit() { + # 0 means true in bash + PACKAGE_INSTALLED=1 + PACKAGE_IS_DEPENDENCY=1 + SERVICE_ENABLED=1 + + is_pkg_installed "$PACKAGE" + [ "$FNRET" = 0 ] && PACKAGE_INSTALLED=0 # 0 means true in bash + + is_pkg_a_dependency "$PACKAGE" + # dnsmasq is installed with dnsmasq-base, which + [ "$FNRET" = 0 ] && PACKAGE_IS_DEPENDENCY=0 + + is_service_enabled "$SERVICE" + [ "$FNRET" = 0 ] && SERVICE_ENABLED=0 + + if [ "$PACKAGE_INSTALLED" -eq 0 ] && [ "$PACKAGE_IS_DEPENDENCY" -eq 1 ]; then + crit "$PACKAGE is installed and not a dependency" + elif [ "$PACKAGE_INSTALLED" -eq 0 ] && [ "$PACKAGE_IS_DEPENDENCY" -eq 0 ] && [ "$SERVICE_ENABLED" -eq 0 ]; then + crit "$SERVICE is enabled" + else + ok "$PACKAGE is not in use" + fi +} + +# This function will be called if the script status is on enabled mode +apply() { + audit + if [ "$PACKAGE_INSTALLED" -eq 0 ] && [ "$PACKAGE_IS_DEPENDENCY" -eq 1 ]; then + crit "$PACKAGE is installed and not a dependency, removing it" + apt_remove "$PACKAGE" -y + apt-get autoremove -y + elif [ "$PACKAGE_INSTALLED" -eq 0 ] && [ "$PACKAGE_IS_DEPENDENCY" -eq 0 ] && [ "$SERVICE_ENABLED" -eq 0 ] && [ "$IS_CONTAINER" -eq 1 ]; then + crit "$SERVICE is enabled, i'm going to stop and mask it" + systemctl stop "$SERVICE" + systemctl mask "$SERVICE" + else + ok "$PACKAGE is not in use" + fi +} + +# This function will check config parameters required +check_config() { + : +} + +# Source Root Dir Parameter +if [ -r /etc/default/cis-hardening ]; then + # shellcheck source=../../debian/default + . /etc/default/cis-hardening +fi +if [ -z "$CIS_LIB_DIR" ]; then + echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment." + echo "Cannot source CIS_LIB_DIR variable, aborting." + exit 128 +fi + +# Main function, will call the proper functions given the configuration (audit, enabled, disabled) +if [ -r "${CIS_LIB_DIR}"/main.sh ]; then + # shellcheck source=../../lib/main.sh + . "${CIS_LIB_DIR}"/main.sh +else + echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening" + exit 128 +fi diff --git a/bin/hardening/sudo_no_nopasswd.sh b/bin/hardening/sudo_no_nopasswd.sh new file mode 100755 index 0000000..48bed1a --- /dev/null +++ b/bin/hardening/sudo_no_nopasswd.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# run-shellcheck +# +# CIS Debian Hardening +# + +# +# Ensure users must provide password for privilege escalation (Manual) +# + +set -e # One error, it's over +set -u # One variable unset, it's over + +# shellcheck disable=2034 +HARDENING_LEVEL=3 +# shellcheck disable=2034 +DESCRIPTION="Ensure users must provide password for privilege escalation " + +# This function will be called if the script status is on enabled / audit mode +audit() { + sudo_nopasswd=$($SUDO_CMD grep -HR NOPASSWD /etc/sudoers*) + if [ "$(wc -l <<<"$sudo_nopasswd")" -gt 0 ]; then + crit "There are sudo commands with NOPASSWD: \n$sudo_nopasswd" + else + ok "There are no NOPASSWD sudo commands" + fi +} + +# This function will be called if the script status is on enabled mode +apply() { + audit + info "Please review and fix sudo commmands manually if needed" +} + +# This function will check config parameters required +check_config() { + : +} + +# Source Root Dir Parameter +if [ -r /etc/default/cis-hardening ]; then + # shellcheck source=../../debian/default + . /etc/default/cis-hardening +fi +if [ -z "$CIS_LIB_DIR" ]; then + echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment." + echo "Cannot source CIS_LIB_DIR variable, aborting." + exit 128 +fi + +# Main function, will call the proper functions given the configuration (audit, enabled, disabled) +if [ -r "${CIS_LIB_DIR}"/main.sh ]; then + # shellcheck source=../../lib/main.sh + . "${CIS_LIB_DIR}"/main.sh +else + echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening" + exit 128 +fi diff --git a/bin/hardening/wireless_interfaces_disabled.sh b/bin/hardening/wireless_interfaces_disabled.sh new file mode 100755 index 0000000..de0888e --- /dev/null +++ b/bin/hardening/wireless_interfaces_disabled.sh @@ -0,0 +1,81 @@ +#!/bin/bash + +# run-shellcheck +# +# CIS Debian Hardening +# + +# +# Ensure wireless interfaces are disabled (Automated) +# + +set -e # One error, it's over +set -u # One variable unset, it's over + +# shellcheck disable=2034 +HARDENING_LEVEL=2 +# shellcheck disable=2034 +DESCRIPTION="Ensure wireless interfaces are disabled" + +# This function will be called if the script status is on enabled / audit mode +audit() { + AVAILABLE_MODULES="" + + wireless_drivers=$(find /sys/class/net/*/ -type d -name wireless) + if [ "$(wc -w <<<"$wireless_drivers")" -gt 0 ]; then + # not the most readable syntax, took as is from the CIS pdf (just changed the vars name) + for module in $(for wireless_driver in $(find /sys/class/net/*/ -type d -name wireless | xargs -0 dirname); do readlink -f "$wireless_driver"/device/driver/module; done); do + + is_kernel_module_available "$module" + if [ "$FNRET" -eq 0 ]; then + # is available in kernel config, but may be disabled in modprobe + is_kernel_module_disabled "$module" + if [ "$FNRET" -eq 1 ]; then + AVAILABLE_MODULES="$AVAILABLE_MODULES $module" + fi + fi + done + fi + + if [ -n "$AVAILABLE_MODULES" ]; then + crit "There are some wireless modules available: $AVAILABLE_MODULES" + else + ok "There are no wireless modules available" + fi + +} + +# This function will be called if the script status is on enabled mode +apply() { + audit + + for module in $AVAILABLE_MODULES ]; do + echo "install $module /bin/true" >>/etc/modprobe.d/"$module".conf + info "$module has been disabled in modprobe configuration" + done +} + +# This function will check config parameters required +check_config() { + : +} + +# Source Root Dir Parameter +if [ -r /etc/default/cis-hardening ]; then + # shellcheck source=../../debian/default + . /etc/default/cis-hardening +fi +if [ -z "$CIS_LIB_DIR" ]; then + echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment." + echo "Cannot source CIS_LIB_DIR variable, aborting." + exit 128 +fi + +# Main function, will call the proper functions given the configuration (audit, enabled, disabled) +if [ -r "${CIS_LIB_DIR}"/main.sh ]; then + # shellcheck source=../../lib/main.sh + . "${CIS_LIB_DIR}"/main.sh +else + echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening" + exit 128 +fi diff --git a/hooks/check_is_executable.sh b/hooks/check_is_executable.sh new file mode 100755 index 0000000..f3ca2db --- /dev/null +++ b/hooks/check_is_executable.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +for script in "$@"; do + chmod +x "$script" +done + +exit 0 diff --git a/tests/hardening/aide_is_installed.sh b/tests/hardening/aide_is_installed.sh new file mode 100644 index 0000000..2328f6b --- /dev/null +++ b/tests/hardening/aide_is_installed.sh @@ -0,0 +1,20 @@ +# shellcheck shell=bash +# run-shellcheck +test_audit() { + describe Running on blank host + register_test retvalshouldbe 1 + # shellcheck disable=2154 + run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Fixing situation + sed -i 's/audit/enabled/' "${CIS_CONF_DIR}/conf.d/${script}.cfg" + "${CIS_CHECKS_DIR}/${script}.sh" || true + + describe Checking resolved state + register_test retvalshouldbe 0 + run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Clean installation + apt remove -y aide + apt autoremove -y +} diff --git a/tests/hardening/at_is_restricted.sh b/tests/hardening/at_is_restricted.sh new file mode 100644 index 0000000..37616e9 --- /dev/null +++ b/tests/hardening/at_is_restricted.sh @@ -0,0 +1,71 @@ +# shellcheck shell=bash +# run-shellcheck +test_audit() { + + describe prepare test + rm -f /etc/at.allow + apt install -y at + + # at package is going to provide at.deny with default content + describe Running on blank host + register_test retvalshouldbe 0 + # shellcheck disable=2154 + run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Prepare failing test at.deny + # wrong perm + chmod 0644 /etc/at.deny + + describe Running failed test at.deny + register_test retvalshouldbe 1 + run failure "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Correcting situation + sed -i 's/audit/enabled/' "${CIS_CONF_DIR}/conf.d/${script}.cfg" + "${CIS_CHECKS_DIR}/${script}.sh" || true + + describe Running success test at.deny + register_test retvalshouldbe 0 + run success "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Prepare failing test at.deny + # empty file + at.allow inexistent = all users allowed + # shellcheck disable=2188 + >/etc/at.deny + + describe Running failed test at.deny + register_test retvalshouldbe 1 + run failure "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Correcting situation + "${CIS_CHECKS_DIR}/${script}.sh" || true + + describe Running success test at.deny + register_test retvalshouldbe 0 + run success "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Prepare failing test at.allow + touch /etc/at.allow + # wrong user + chown secaudit:root /etc/at.allow + + describe Running failed test at.allow + register_test retvalshouldbe 1 + run failure "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Correcting situation + "${CIS_CHECKS_DIR}/${script}.sh" || true + + describe Running success test at.allow + register_test retvalshouldbe 0 + run success "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe cleanup at + apt remove -y at + apt autoremove -y + rm -f /etc/allow + + describe Running success at package missing + register_test retvalshouldbe 0 + run success "${CIS_CHECKS_DIR}/${script}.sh" --audit-all +} diff --git a/tests/hardening/bluetooth_is_disabled.sh b/tests/hardening/bluetooth_is_disabled.sh new file mode 100644 index 0000000..bca3e24 --- /dev/null +++ b/tests/hardening/bluetooth_is_disabled.sh @@ -0,0 +1,36 @@ +# shellcheck shell=bash +# run-shellcheck +test_audit() { + + describe Prepare on purpose failed test + apt install -y bluez + # running on a container, will can only test the package installation, not the service management + + describe Running on purpose failed test + register_test retvalshouldbe 1 + # shellcheck disable=2154 + run failed "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe correcting situation + sed -i 's/audit/enabled/' "${CIS_CONF_DIR}/conf.d/${script}.cfg" + "${CIS_CHECKS_DIR}/${script}.sh" --apply || true + + describe Checking resolved state + register_test retvalshouldbe 0 + run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe Prepare test package dependencies + # try to install a package that depends on 'bluez' + apt install -y bluez-test-tools + # running on a container, we can only test the package installation, not the service management + + describe Running successfull test + register_test retvalshouldbe 0 + # shellcheck disable=2154 + run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + + describe clean installation + apt remove -y bluez-test-tools bluez + apt autoremove -y + +} diff --git a/tests/hardening/sudo_no_nopasswd.sh b/tests/hardening/sudo_no_nopasswd.sh new file mode 100644 index 0000000..9ceffe0 --- /dev/null +++ b/tests/hardening/sudo_no_nopasswd.sh @@ -0,0 +1,9 @@ +# shellcheck shell=bash +# run-shellcheck +test_audit() { + describe Running on blank host + # we are providing a "NOPASSWD" sudoers for cis tests + register_test retvalshouldbe 1 + # shellcheck disable=2154 + run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all +} diff --git a/tests/hardening/wireless_interfaces_disabled.sh b/tests/hardening/wireless_interfaces_disabled.sh new file mode 100644 index 0000000..00ec662 --- /dev/null +++ b/tests/hardening/wireless_interfaces_disabled.sh @@ -0,0 +1,10 @@ +# shellcheck shell=bash +# run-shellcheck +test_audit() { + describe Running on blank host + register_test retvalshouldbe 0 + dismiss_count_for_test + # shellcheck disable=2154 + run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all + +}