OpenVAPT Self-Assessment Report
lab-vulnerable (simulated) - Ubuntu 18.04.6 LTS - 2026-10-16 02:10 UTC
OpenVAPT is an academic, non-commercial project with source-available code built by AI Cybersecurity Engineers (AI systems, not people or registered engineers). This report was produced by automated, read-only checks run by the user on their own machine, for their own use, 100% at their own risk. It is not a penetration test, an audit, a certification, a service or professional advice, and it may be wrong or incomplete. The developers accept no responsibility or liability for any decision taken from it. OpenVAPT may not be sold or used to provide services. No data from this report was sent anywhere.
Executive Summary
Scope: this report covers one machine, lab-vulnerable (simulated), assessed on 2026-10-16 02:10 UTC, with root access. 310 checks ran, read-only and limited to this machine.
Result: 308 checks failed (14 Critical, 73 High, 89 Medium, 123 Low, 9 Info) and 2 passed. Critical weaknesses require immediate attention.
Coverage: 0 Incomplete, 0 Error and 0 Skipped, plus 3 targets inside other checks that could not be fully read. These areas are not shown to be free of weaknesses; see Coverage Gaps.
Vulnerability snapshot: 2021-01-01 (2114 days old, 7 advisories). Warning: older than 90 days; newer vulnerabilities are not in it. This warning is not a failure.
Limitation: this is an automated, read-only self-assessment, not a penetration test. A clean result does not prove the machine is free of weaknesses.
14Critical
73High
89Medium
123Low
2Passed
0Incomplete
3Incomplete Targets
0Skipped
0Errors
| Scope | This machine only (310 checks, sites: shop.example.test) |
| Run As Root | Yes |
| Tool | OpenVAPT v0.1.0-dev (commit unknown) Pre-Release: dev |
| Vulnerability Data | Snapshot 2021-01-01, 2114 days old, 7 advisories Warning: older than 90 days; newer vulnerabilities are not in it (not a failure) |
Top 5 Risks
| ID | Risk | Severity | CVSS | Why It Matters |
HOST-CTR-001 | Docker API Exposed Over TCP Without TLS | Critical | 10.0 | The Docker API is equivalent to root on the host. |
HOST-K8S-001 | Kubelet Allows Anonymous or Unauthorised Access | Critical | 10.0 | The kubelet API can run commands in every pod on the node. |
HOST-CVE-002 | Known Exploited Vulnerabilities Present | Critical | 9.8 | Known vulnerable package versions can expose a server to documented attacks. |
HOST-SSH-003 | SSH Permits Empty Passwords | Critical | 9.8 | Any account without a password becomes an open door to anyone on the network. |
NET-DB-002 | Redis Authentication and Network Binding | Critical | 9.8 | An unauthenticated network-reachable Redis instance can disclose or alter data and may permit dangerous administrative operations. |
Notable Coverage Gaps
- NET-TLS-001 (shop.example.test on port 10000): Modern TLS handshake failed, so legacy protocol rejection could not be verified
- NET-TLS-005 (shop.example.test on port 10000): TLS certificate could not be read
- NET-TLS-006 (shop.example.test on port 10000): TLS certificate could not be read
Risk Heat Map
Failed checks by security control area and severity.
| Category | Critical | High | Medium | Low | Info |
| Identity and Authentication | 3 | 8 | 13 | 12 | 2 |
| Access Control | 0 | 18 | 7 | 6 | 0 |
| Patch and Vulnerability Management | 1 | 9 | 3 | 4 | 2 |
| Secure Configuration | 2 | 5 | 19 | 54 | 4 |
| Cryptography and TLS | 0 | 7 | 14 | 2 | 0 |
| Logging and Monitoring | 0 | 0 | 1 | 22 | 0 |
| Network Exposure | 2 | 6 | 4 | 1 | 0 |
| Data Services | 4 | 8 | 4 | 1 | 0 |
| Web Application Security | 1 | 1 | 10 | 4 | 1 |
| Information Exposure | 1 | 11 | 14 | 17 | 0 |
Compliance Coverage
Coverage shows mapped automated checks and does not certify compliance.
| Framework | Safeguard or Subcategory | Checks Run | Failed | Passed |
| CIS Controls v8 | 2.2 | 5 | 5 | 0 |
| CIS Controls v8 | 2.5 | 1 | 1 | 0 |
| CIS Controls v8 | 3.3 | 51 | 51 | 0 |
| CIS Controls v8 | 3.10 | 23 | 23 | 0 |
| CIS Controls v8 | 4.1 | 75 | 75 | 0 |
| CIS Controls v8 | 4.3 | 1 | 1 | 0 |
| CIS Controls v8 | 4.4 | 6 | 5 | 1 |
| CIS Controls v8 | 4.7 | 1 | 1 | 0 |
| CIS Controls v8 | 4.8 | 24 | 23 | 1 |
| CIS Controls v8 | 5.2 | 23 | 23 | 0 |
| CIS Controls v8 | 5.3 | 1 | 1 | 0 |
| CIS Controls v8 | 5.4 | 5 | 5 | 0 |
| CIS Controls v8 | 7.3 | 8 | 8 | 0 |
| CIS Controls v8 | 7.4 | 5 | 5 | 0 |
| CIS Controls v8 | 8.2 | 11 | 11 | 0 |
| CIS Controls v8 | 8.3 | 4 | 4 | 0 |
| CIS Controls v8 | 8.4 | 1 | 1 | 0 |
| CIS Controls v8 | 8.5 | 5 | 5 | 0 |
| CIS Controls v8 | 8.9 | 1 | 1 | 0 |
| CIS Controls v8 | 16.2 | 1 | 1 | 0 |
| CIS Controls v8 | 16.7 | 58 | 58 | 0 |
| NIST CSF 2.0 | DE.CM-09 | 1 | 1 | 0 |
| NIST CSF 2.0 | ID.RA-01 | 18 | 18 | 0 |
| NIST CSF 2.0 | ID.RA-08 | 1 | 1 | 0 |
| NIST CSF 2.0 | PR.AA-01 | 25 | 25 | 0 |
| NIST CSF 2.0 | PR.AA-05 | 56 | 56 | 0 |
| NIST CSF 2.0 | PR.DS-01 | 51 | 51 | 0 |
| NIST CSF 2.0 | PR.DS-02 | 23 | 23 | 0 |
| NIST CSF 2.0 | PR.IR-01 | 30 | 28 | 2 |
| NIST CSF 2.0 | PR.PS-01 | 158 | 157 | 1 |
| NIST CSF 2.0 | PR.PS-02 | 18 | 18 | 0 |
| NIST CSF 2.0 | PR.PS-04 | 22 | 22 | 0 |
| NIST CSF 2.0 | PR.PS-05 | 1 | 1 | 0 |
Prioritised Remediation Plan
High-severity, low-effort quick wins appear first.
- HOST-CTR-001 - Docker API Exposed Over TCP Without TLS CRITICAL Low Effort
Remove tcp:// listeners and use the local Unix socket or SSH (docker context with ssh://). If remote access is unavoidable, enable tlsverify with client certificates and restrict the port in the firewall.
- HOST-SSH-003 - SSH Permits Empty Passwords CRITICAL Low Effort
Set PermitEmptyPasswords no in /etc/ssh/sshd_config, reload sshd, and give every account a password or lock it (passwd -l <user>).
- NET-DB-002 - Redis Authentication and Network Binding CRITICAL Low Effort
Set protected-mode yes, configure ACL users with strong secrets, bind to 127.0.0.1 and ::1, and restrict remote access with a firewall.
- NET-DB-003 - MongoDB Authorization and Network Binding CRITICAL Low Effort
Set security.authorization to enabled and net.bindIp to 127.0.0.1, then allow only approved clients through a controlled network path.
- NET-DB-004 - PostgreSQL Trust and Broad Client Access CRITICAL Low Effort
Bind PostgreSQL to required interfaces only and replace trust or unrestricted pg_hba.conf rules with narrow CIDRs and scram-sha-256. Caution: users whose passwords are stored as md5 cannot log in with scram-sha-256 until their password is set again with password_encryption = scram-sha-256, so reset them first and reload, not restart, to test.
- NET-DB-007 - Elasticsearch Security and Network Binding CRITICAL Low Effort
Set xpack.security.enabled true, bind network.host to loopback or an approved private interface, require TLS, and filter access.
- WEB-NODE-002 - Node.js Debugger (Inspector) Enabled in a Service CRITICAL Low Effort
Remove --inspect from the service and from NODE_OPTIONS, run systemctl daemon-reload and restart. Debug on a development machine, or temporarily over an SSH tunnel to 127.0.0.1:9229.
- WEB-PY-004 - Python Interactive Debugger Enabled in a Service CRITICAL Low Effort
Remove the debug switches, run the application under a production WSGI server (Gunicorn, uWSGI or mod_wsgi) behind nginx or Apache, run systemctl daemon-reload and restart the service.
- WEB-TOM-002 - Tomcat Administrative Users With Default or Weak Passwords CRITICAL Low Effort
Remove accounts you do not need. Give the remaining ones long random passwords and store them as digests: configure a CredentialHandler (for example SecretKeyCredentialHandler with PBKDF2) in the Realm and generate hashes with bin/digest.sh. Restart Tomcat.
- WEB-TOM-004 - Tomcat AJP Connector Unprotected (Ghostcat) CRITICAL Low Effort
If you do not use AJP (most sites proxy over HTTP), delete or comment out the AJP <Connector>. Otherwise set address="127.0.0.1", a long random secret="..." with secretRequired="true", and the same secret in the proxy (mod_proxy_ajp: ProxyPass ... secret=...). Upgrade Tomcat to a supported release.
- HOST-CRON-001 - Cron Jobs Run Programs Other Users Can Modify HIGH Low Effort
chmod o-w <program> and its folder; move scripts out of /tmp or user-writable folders into /usr/local/sbin owned by root; have cron run only files owned by root (chown root:root).
- HOST-CRON-002 - World-Writable Directory in Cron's PATH HIGH Low Effort
Remove the writable folder from PATH in /etc/crontab (or chmod o-w it), delete relative entries, and call programs in cron jobs by absolute path.
- HOST-CTR-008 - Docker Socket Accessible to Non-Administrators HIGH Low Effort
chmod 660 /var/run/docker.sock && chown root:docker /var/run/docker.sock (the daemon recreates it with these defaults). Remove users from the docker group (gpasswd -d <user> docker) and give administrators sudo docker, or move to rootless Docker.
- HOST-FS-001 - Sensitive Account Files Have Unsafe Permissions HIGH Low Effort
chown root:root /etc/passwd /etc/group && chmod 644 /etc/passwd /etc/group ; chown root:shadow /etc/shadow /etc/gshadow && chmod 640 /etc/shadow /etc/gshadow (use root:root and 000 on RHEL-family systems).
- HOST-FS-002 - Temporary Directory Missing the Sticky Bit HIGH Low Effort
chmod 1777 /tmp /var/tmp
- HOST-FS-005 - Cron Files Writable by Non-Root Users HIGH Low Effort
chown root:root <path> && chmod go-w <path> for each listed path (600 for /etc/crontab is a common hardening choice).
- HOST-FS-007 - Private TLS Keys Readable by Others HIGH Low Effort
chown root:root <key> && chmod 600 <key> (or 640 with a dedicated group the web server runs in). Rotate any key that was exposed.
- HOST-FS-022 - Account Database Files or Their Backups Not Owned and Locked by Root HIGH Low Effort
chown root:root /etc/passwd /etc/passwd- /etc/group /etc/group- && chmod 644 /etc/passwd /etc/group && chmod 600 /etc/passwd- /etc/group- ; chown root:shadow /etc/shadow /etc/shadow- /etc/gshadow /etc/gshadow- && chmod 640 /etc/shadow /etc/gshadow && chmod 600 /etc/shadow- /etc/gshadow- (use root:root and mode 000 on RHEL family systems).
- HOST-K8S-002 - Kubernetes Data Directory Accessible to Others HIGH Low Effort
chmod 700 /var/lib/etcd && chown etcd:etcd /var/lib/etcd (or root:root for kubeadm static pods). Enable encryption at rest for Secrets.
- HOST-K8S-003 - Kubernetes Credential Files Readable by Others HIGH Low Effort
chmod 600 /etc/kubernetes/*.conf /etc/kubernetes/pki/*.key /etc/kubernetes/pki/etcd/*.key && chown root:root on each.
- HOST-PKG-002 - Repository Signature Checks Disabled HIGH Low Effort
Remove trusted=yes (or Trusted: yes) from the listed source, install the repository's signing key under /etc/apt/keyrings and reference it with signed-by=; remove AllowUnauthenticated and AllowInsecureRepositories settings. On dnf and yum set gpgcheck=1 (and repo_gpgcheck=1 where supported) in each listed repository and import its key with rpm --import.
- HOST-SSH-001 - SSH Allows Direct Root Login HIGH Low Effort
In /etc/ssh/sshd_config set: PermitRootLogin no (or prohibit-password if key-based root login is truly required). Log in as a named user and use sudo. Then run: sshd -t && systemctl reload sshd
- HOST-SSH-009 - SSH Host Private Keys Readable by Others HIGH Low Effort
chown root:root /etc/ssh/ssh_host_*_key && chmod 600 /etc/ssh/ssh_host_*_key (0640 with group ssh_keys is acceptable on RHEL family).
- HOST-SSH-010 - SSH Server Configuration Writable by Non-Root Users HIGH Low Effort
chown root:root /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf && chmod 600 /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf
- HOST-SYSD-003 - Service Unit Files Writable by Non-Root Users HIGH Low Effort
chown root:root <file> && chmod 644 <file> for each listed file, then review its contents for changes you did not make (ExecStart=, User=, ExecStartPre=) and run systemctl daemon-reload.
- HOST-SYSD-004 - Service Programs in Writable Locations HIGH Low Effort
Install the program in a root-owned location (/usr/local/bin or /opt/<app>), chown root:root and chmod 755 it, point ExecStart= at it, then systemctl daemon-reload and restart the service.
- HOST-USR-002 - Accounts Without a Password HIGH Low Effort
For each listed user either set a password (passwd <user>) or lock the account (passwd -l <user>).
- HOST-USR-003 - Sudo Rules Without Password (NOPASSWD) HIGH Low Effort
Edit with visudo and remove NOPASSWD, or restrict it to one specific, harmless command for automation accounts.
- HOST-USR-007 - Insecure Trust Files in Home Directories HIGH Low Effort
Delete .rhosts and .shosts files. Replace .netrc credentials with a secret manager or key-based authentication, then delete the file and rotate the passwords it contained.
- NET-AI-001 - AI Model Server or Dashboard Reachable From the Network HIGH Low Effort
Bind each service to 127.0.0.1 (Ollama: OLLAMA_HOST=127.0.0.1:11434 in its service environment; Ray: --dashboard-host=127.0.0.1; Gradio: server_name="127.0.0.1"), and if others need it, publish it only through a reverse proxy with authentication and TLS.
- NET-AI-002 - Jupyter Configuration Weakens Authentication HIGH Low Effort
Remove the empty token line so Jupyter generates a random token, or set a password with jupyter server password . Remove disable_check_xsrf = True. Bind to 127.0.0.1 and reach it through an SSH tunnel.
- NET-APP-001 - Debugger or Application Control Ports Exposed HIGH Low Effort
Bind each to 127.0.0.1 or a Unix socket (node --inspect=127.0.0.1:9229; Tomcat Connector address="127.0.0.1" or remove the AJP connector; PHP-FPM listen = /run/php/php-fpm.sock; jupyter --ip=127.0.0.1) and never expose a debugger.
- NET-DB-001 - Database or Cache Service Exposed to the Network HIGH Low Effort
Bind the service to 127.0.0.1 (MySQL: bind-address = 127.0.0.1; Redis: bind 127.0.0.1 ::1 and protected-mode yes; MongoDB: net.bindIp: 127.0.0.1) and restart it. Caution: confirm first that no application on another machine connects to it, or that application loses its database. If remote access is needed, allow only specific source IPs in the firewall and require TLS and authentication.
- NET-DB-005 - MySQL or MariaDB Unsafe Network Options HIGH Low Effort
Disable local_infile and skip-grant-tables. Bind to 127.0.0.1 or enable skip-networking when TCP access is unnecessary.
- NET-DB-006 - Memcached UDP or Broad Listen Address HIGH Low Effort
Set UDP_PORT=0 or -U 0 and bind with -l 127.0.0.1. Use a firewall for any explicitly required clients.
- NET-DB-008 - Unsafe NFS Export Options HIGH Low Effort
Restrict every export to explicit client CIDRs, use root_squash, remove insecure, and reload exports.
- NET-DB-009 - Unsafe Samba Guest or SMB1 Configuration HIGH Low Effort
Set guest ok = no, map to guest = Never, and server min protocol = SMB2_02 or newer. Review each share ACL.
- NET-DB-010 - BIND Open Recursion HIGH Low Effort
Disable recursion on authoritative-only servers, or set allow-recursion and allow-query-cache to explicit trusted networks.
- NET-DB-011 - BIND Zone Transfers Allowed to Any HIGH Low Effort
Set allow-transfer to none or explicit secondary server addresses, preferably protected with TSIG.
- NET-DB-012 - Postfix Open Relay Controls HIGH Low Effort
Set smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination and narrow mynetworks.
- NET-FW-003 - Firewall Allows Sensitive Services From Anywhere HIGH Low Effort
Delete the rule or restrict it to the addresses that need it, for example: ufw delete allow 3306 && ufw allow from 203.0.113.10 to any port 3306 proto tcp . Better, bind the service to 127.0.0.1 and reach it through an SSH tunnel or VPN.
- NET-SVC-003 - Network Time Service Amplification Risk HIGH Low Effort
Bind the time daemon to required interfaces, restrict clients to explicit networks, disable monitoring, and use noquery or equivalent controls.
- WEB-APA-005 - Apache Allows TLS 1.0 or 1.1 HIGH Low Effort
Set SSLProtocol -all +TLSv1.2 +TLSv1.3 (Mozilla intermediate) in mods-enabled/ssl.conf or ssl.conf, then apachectl configtest and reload.
- WEB-APA-006 - Apache Cipher Suite Includes Weak Suites HIGH Low Effort
Use the Mozilla intermediate list for SSLCipherSuite and set SSLHonorCipherOrder off , as the Mozilla SSL Configuration Generator produces for Apache.
- WEB-APP-001 - Laravel Debug Mode On or Application Key Missing HIGH Low Effort
Set APP_DEBUG=false and APP_ENV=production in .env, run php artisan key:generate if APP_KEY is empty, then php artisan config:cache. Keep .env outside the web root (Laravel's public/ folder) and readable only by the application user.
- WEB-APP-003 - Symfony Running in the Development Environment HIGH Low Effort
Set APP_ENV=prod and APP_DEBUG=0 in .env (or .env.local), run composer dump-env prod, clear the cache (php bin/console cache:clear) and remove the web profiler bundle from production.
- WEB-APP-004 - Rails Master Key or Secrets File Exposed HIGH Low Effort
chmod 600 config/master.key config/credentials/*.key; keep them out of git (.gitignore) and out of public/; load the key from RAILS_MASTER_KEY in the environment on servers. Rotate the credentials if the key was ever exposed.
- WEB-APP-006 - Spring Boot Actuator Endpoints Fully Exposed HIGH Low Effort
Set management.endpoints.web.exposure.include=health,info (and exclude env,heapdump,configprops), move management.server.port to a port that is not published, and require authentication for every actuator endpoint with Spring Security.
- WEB-CMS-004 - CMS Configuration Readable by All Users HIGH Low Effort
chmod 640 <file> and chown it to the site owner with the web server's group (for example chown deploy:www-data wp-config.php); on PHP-FPM pools that run as the site user, 600 or 400 also works. Rotate the database password if other people have shell access.
- WEB-CMS-005 - CMS Configuration Writable by Other Users HIGH Low Effort
chmod 640 (or 440) <file>. Drupal also expects sites/default to be 555 after installation. Review the file for code you did not add.
- WEB-CMS-019 - Drupal update.php Open Without Authentication HIGH Low Effort
Set $settings['update_free_access'] = FALSE; in settings.php (the default) and run updates as user 1 or with drush updatedb.
- WEB-DOC-001 - Secrets or Backups Stored Inside a Web Root HIGH Low Effort
Move each listed file outside the document root (for example to a 700 folder in the account's home), delete what is not needed, and rotate any secret or key that was exposed. Keep backups in a dedicated location outside every web root.
- WEB-DOC-002 - Web Root Files Writable by Other Users HIGH Low Effort
chmod o-w <file> for each listed file (find <docroot> -type f -perm -0002 -exec chmod o-w {} +). Use 644 for files and 755 for folders, owned by the site account, and grant the web server write access only to upload folders.
- WEB-EXP-001 - Git Repository Exposed on the Website HIGH Low Effort
Block dot-folders in the web server (Apache: RedirectMatch 404 /\.git ; nginx: location ~ /\.(?!well-known) { deny all; }) and deploy without the .git folder in the web root. Rotate any secret that was ever committed.
- WEB-EXP-004 - Backup or Database Dump Files Downloadable HIGH Low Effort
Move backups outside the web root (for example /home/<user>/deploy-backups/ with mode 700), delete the exposed copies and treat their contents as leaked.
- WEB-EXP-007 - Other Version Control Metadata Exposed HIGH Low Effort
Block dot-folders at the web server and deploy without version control metadata in the web root. Rotate any secret ever committed.
- WEB-EXP-008 - Log Files Downloadable From the Website HIGH Low Effort
Move logs outside the web root, deny access to *.log at the web server, disable WP_DEBUG_LOG in production, and review the exposed logs for leaked secrets.
- WEB-EXP-012 - Framework Debug Pages Exposed HIGH Low Effort
Disable debug mode in production (APP_DEBUG=false, DEBUG = False, APP_ENV=prod), remove profiler routes, and show generic error pages.
- WEB-NGX-003 - nginx Allows TLS 1.0 or 1.1 HIGH Low Effort
Set ssl_protocols TLSv1.2 TLSv1.3; in the http block (the Mozilla intermediate profile), run nginx -t and reload.
- WEB-NGX-004 - nginx Cipher List Includes Weak Suites HIGH Low Effort
Use the Mozilla intermediate list, for example ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; and ssl_prefer_server_ciphers off;
- WEB-PHP-003 - PHP Allows Remote File Inclusion HIGH Low Effort
In php.ini set allow_url_include = Off (the default since PHP 5.2) and restart PHP.
- WEB-PY-001 - Django Debug Mode Enabled HIGH Low Effort
Set DEBUG = False in production, preferably from the environment (DEBUG = os.environ.get('DJANGO_DEBUG') == '1'), set ALLOWED_HOSTS, and restart the application. Run python manage.py check --deploy.
- WEB-PY-003 - Django Uses the Generated Development Secret Key HIGH Low Effort
Generate a new key (python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'), load it from the environment or a root-readable file (SECRET_KEY = os.environ['DJANGO_SECRET_KEY']), and restart. Changing the key logs all users out.
- WEB-TOM-001 - Tomcat Manager Reachable Without Address Restriction HIGH Low Effort
If you do not use them, delete the manager and host-manager folders (or apt remove tomcatN-admin). Otherwise keep the default valve in META-INF/context.xml: <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> and reach the Manager through an SSH tunnel.
- HOST-CVE-002 - Known Exploited Vulnerabilities Present CRITICAL Medium Effort
Install the vendor security update. For a source build, run 'make vulndb' to embed a snapshot generated from OSV and CISA KEV, then rebuild.
- HOST-K8S-001 - Kubelet Allows Anonymous or Unauthorised Access CRITICAL Medium Effort
Set authentication.anonymous.enabled: false, authorization.mode: Webhook and readOnlyPort: 0 in the kubelet configuration, then restart the kubelet.
- NET-SVC-002 - Control Plane or Remote Desktop Ports Network-Reachable CRITICAL Medium Effort
Bind control planes to loopback or a dedicated management address, require mutual TLS or strong authentication, and filter access to approved source networks or a VPN.
- WEB-EXP-002 - Environment or Secrets File Exposed CRITICAL Medium Effort
Move secrets out of the web root, block dot-files at the web server, delete backup copies, then rotate every secret in the file because it must be treated as leaked.
- HOST-CTR-003 - Privileged or Host-Namespace Containers HIGH Medium Effort
Recreate each container without --privileged, --pid=host, --net=host and --ipc=host; drop all capabilities and add back only the specific ones needed (--cap-drop=ALL --cap-add=...).
- HOST-CTR-004 - Containers Mount the Docker Socket or Host Root HIGH Medium Effort
Remove these mounts. If a tool genuinely needs the Docker API, use a restricted socket proxy that allows only the required read-only calls.
- HOST-CTR-011 - Seccomp or AppArmor Disabled for Containers HIGH Medium Effort
Remove --security-opt seccomp=unconfined and apparmor=unconfined from the container definitions and recreate them; if an application needs one extra system call, write a custom seccomp profile that adds only that call. Delete seccomp-profile from daemon.json.
- HOST-CTR-014 - containerd Remote API or Podman Unconfined Defaults HIGH Medium Effort
containerd: remove tcp_address or set tcp_tls_cert and tcp_tls_key, then restart containerd. Podman: delete seccomp_profile = "unconfined", set label = true and apparmor_profile = "container-default" in containers.conf.
- HOST-CVE-001 - Installed OS Packages With Known Vulnerabilities HIGH Medium Effort
Install the vendor security update. For a source build, run 'make vulndb' to embed a snapshot generated from OSV and CISA KEV, then rebuild.
- HOST-DKR-001 - Users With Root-Equivalent Docker Access HIGH Medium Effort
Remove users who do not need it from the docker group (gpasswd -d <user> docker); consider rootless Docker or Podman; keep docker.sock at 660 root:docker.
- HOST-FS-003 - World-Writable Files in System Configuration HIGH Medium Effort
For each listed file or directory: chmod o-w <path>. Then find out how it became writable (a deployment script or a careless chmod 777).
- HOST-FS-004 - Unexpected SUID or SGID Programs HIGH Medium Effort
Confirm whether each program is needed. Remove the bit with chmod u-s,g-s <file>, or delete the file if you did not put it there and investigate how it arrived.
- HOST-PKG-001 - Security Updates Waiting to Be Installed HIGH Medium Effort
Debian/Ubuntu: apt-get update && apt-get upgrade . RHEL family: dnf upgrade --security . Consider unattended-upgrades or dnf-automatic for security patches.
- HOST-SEC-001 - Secrets in World-Readable Files HIGH Medium Effort
chmod o-r each listed file (640 with the service's group, or 600). Move secrets into root-only files, systemd credentials or a secrets manager, and rotate every key or password that was readable.
- HOST-USR-001 - Extra Accounts With Root Privileges (UID 0) HIGH Medium Effort
Investigate who created each account. Remove it (userdel <name>) or give it a normal UID (usermod -u <new-uid> <name>). Grant admin rights through sudo instead.
- NET-FW-002 - IPv6 Listeners Without IPv6 Firewall HIGH Medium Effort
Apply equivalent default-deny filtering for IPv6 with nftables or ip6tables and explicitly allow required services. Caution: allow SSH and ICMPv6 neighbour discovery and router messages before applying the default deny, or remote IPv6 sessions and IPv6 connectivity are cut.
- NET-SVC-001 - Cleartext Legacy Services Listening HIGH Medium Effort
Replace with encrypted equivalents: SSH/SFTP instead of Telnet/FTP/rsh, IMAPS (993)/POP3S (995), LDAPS (636), SNMPv3. Disable the old service: systemctl disable --now <unit>.
- WEB-CVE-001 - Vulnerable Web Application Libraries HIGH Medium Effort
Update the affected library or WordPress core and deploy a refreshed lockfile or asset. For a source build, run 'make vulndb' to embed a generated snapshot.
- HOST-OS-001 - Operating System Past End of Security Support HIGH High Effort
Plan an upgrade to a supported release (for example do-release-upgrade on Ubuntu, or a fresh install and migration). Paid extended support (Ubuntu Pro, RHEL ELS) is an alternative while migrating.
- WEB-CMS-012 - Drupal Core Past End of Life HIGH High Effort
Upgrade to a supported Drupal major with composer (drupal/core-recommended), run drush updatedb and test the site; for Drupal 7, migrate with the Migrate module or commission a rebuild.
- WEB-CMS-014 - Joomla Core Past End of Life HIGH High Effort
Update to the current Joomla series through the Joomla Update component (back up first, check extension compatibility, then update), and keep the one-click updater enabled.
- WEB-NODE-001 - Node.js Version Past End of Life HIGH High Effort
Move to an Active or Maintenance LTS release (even-numbered majors), for example with the NodeSource or distribution packages, test the application, then restart its service.
- WEB-PHP-004 - PHP Version Past End of Security Support HIGH High Effort
Upgrade to a supported PHP branch (see php.net/supported-versions) and test the applications, or confirm your distribution still backports security fixes to this version.
- HOST-BOOT-003 - Uncommon Filesystem Modules Not Disabled MEDIUM Low Effort
Create /etc/modprobe.d/openvapt-filesystems.conf with, for each module: install <module> /bin/false and blacklist <module> then unload any loaded one with modprobe -r <module>. Caution: first confirm that no listed module is in use (lsmod, findmnt); blocking a filesystem a mount or package format needs (for example squashfs for snap packages, or vfat for the EFI system partition) breaks those mounts at the next boot.
- HOST-BOOT-004 - USB Storage Driver Not Disabled MEDIUM Low Effort
Create /etc/modprobe.d/openvapt-usb.conf containing install usb-storage /bin/false and blacklist usb-storage then modprobe -r usb-storage. Servers that need USB backups should record the exception instead.
- HOST-CTR-010 - Docker Daemon Allows Insecure Registries or Debug Features MEDIUM Low Effort
Remove insecure-registries (serve the registry over TLS with a trusted certificate, or add its CA to /etc/docker/certs.d/<registry>/ca.crt), set "debug": false and "experimental": false in daemon.json, and remove any --insecure-registry, --debug (-D) or --experimental flag from the dockerd ExecStart in docker.service drop-ins (then systemctl daemon-reload). Restart Docker in a maintenance window: running containers stop unless live-restore is on.
- HOST-FS-006 - Boot Loader Configuration Exposed MEDIUM Low Effort
chown root:root <grub.cfg> && chmod 600 <grub.cfg> (for example /boot/grub/grub.cfg or /boot/grub2/grub.cfg).
- HOST-FS-014 - World-Writable Files Outside Temporary Directories MEDIUM Low Effort
For each listed file: chmod o-w <path>. Then find the deployment step or chmod 777 habit that created it.
- HOST-FS-017 - World-Writable Directories Without the Sticky Bit MEDIUM Low Effort
chmod +t <dir> for directories that must stay shared, or chmod o-w <dir> for those that should not be writable by everyone.
- HOST-KRN-001 - Address Space Layout Randomisation Not Fully Enabled MEDIUM Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.randomize_va_space = 2 then apply with: sysctl --system
- HOST-KRN-009 - Unprivileged eBPF Allowed MEDIUM Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.unprivileged_bpf_disabled = 1 then apply with: sysctl --system
- HOST-PAM-008 - Root PATH Contains Unsafe Entries MEDIUM Low Effort
Edit the listed file so PATH holds only absolute, root-owned directories, for example PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" , remove any . or trailing colon, and chmod o-w any listed directory. Log out and in again.
- HOST-PWD-001 - Weak Password Hashing Algorithm Configured MEDIUM Low Effort
Set ENCRYPT_METHOD YESCRYPT (or SHA512 on older systems) in /etc/login.defs, and make sure pam_unix uses the same algorithm. Ask users to change passwords so existing hashes are upgraded.
- HOST-PWD-002 - Accounts With Obsolete Password Hashes MEDIUM Low Effort
Configure a modern algorithm (HOST-PWD-001), then force a password change for each listed account (chage -d 0 <user>) or lock unused accounts (passwd -l <user>).
- HOST-SSH-002 - SSH Password Authentication Enabled MEDIUM Low Effort
Install your public key for each admin user (ssh-copy-id), confirm key login works in a second session, then set PasswordAuthentication no and KbdInteractiveAuthentication no in /etc/ssh/sshd_config and reload sshd.
- HOST-SSH-004 - SSH Offers Weak Cryptography MEDIUM Low Effort
Remove the listed algorithms. On OpenSSH 8.x and later the defaults are already strong: delete any custom Ciphers/MACs/KexAlgorithms lines, or set explicit modern lists such as Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com then reload sshd.
- HOST-SSH-007 - SSH Forwarding Features Enabled MEDIUM Low Effort
Set AllowTcpForwarding no, AllowAgentForwarding no, PermitTunnel no and GatewayPorts no globally or in every applicable Match block, then reload sshd.
- HOST-SSH-011 - SSH Legacy Trust Options Enabled MEDIUM Low Effort
Set HostbasedAuthentication no , IgnoreRhosts yes and PermitUserEnvironment no in /etc/ssh/sshd_config, then reload sshd.
- HOST-SVC-002 - Telnet Server Installed or Enabled MEDIUM Low Effort
apt purge telnetd inetutils-telnetd or dnf remove telnet-server , and systemctl disable --now telnet.socket . Use SSH. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-003 - rsh, rlogin, rexec or finger Server Installed or Enabled MEDIUM Low Effort
apt purge rsh-server rsh-redone-server fingerd or dnf remove rsh-server finger-server , and systemctl disable --now rsh.socket rlogin.socket rexec.socket finger.socket . Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-004 - TFTP Server Installed or Enabled MEDIUM Low Effort
apt purge tftpd-hpa atftpd or dnf remove tftp-server , and systemctl disable --now tftpd-hpa.service tftp.socket . Where PXE is required, serve only that directory, read-only, from a dedicated host. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-005 - FTP Server Installed or Enabled MEDIUM Low Effort
Move users to SFTP (the OpenSSH internal-sftp subsystem), then apt purge vsftpd proftpd-core pure-ftpd or dnf remove vsftpd proftpd and systemctl disable --now vsftpd . If FTP must stay, enforce TLS (FTPS) and restrict it to named users. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-006 - NIS Server or Client Installed or Enabled MEDIUM Low Effort
Replace NIS with a modern directory (SSSD with LDAPS or FreeIPA), then apt purge nis or dnf remove ypserv ypbind and systemctl disable --now ypserv ypbind . Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SYSD-005 - Secrets Written Into Service Unit Files MEDIUM Low Effort
Move secrets to a root-owned file readable only by root (chmod 600) and load it with EnvironmentFile=, or better use LoadCredential=/SetCredentialEncrypted= so the secret is only visible to the service. Then rotate every secret that was exposed.
- HOST-USR-006 - Legacy NIS Entries in Account Files MEDIUM Low Effort
Remove the '+' lines (with vipw / vigr) and use a modern directory service such as SSSD with LDAPS if central accounts are needed.
- HOST-USR-009 - Password and Shadow Files Out of Step MEDIUM Low Effort
pwconv moves hashes into /etc/shadow and creates missing entries; userdel or vipw/vigr removes orphan lines; run pwck and grpck to confirm the files are consistent.
- NET-APP-002 - Application Server Ports Reachable Without a Reverse Proxy MEDIUM Low Effort
Bind the application to 127.0.0.1 (Node.js: app.listen(3000, '127.0.0.1'); Gunicorn: --bind 127.0.0.1:8000; Tomcat: address="127.0.0.1" on the Connector) and publish it only through nginx or Apache.
- NET-DB-013 - Mail Cleartext Authentication Allowed MEDIUM Low Effort
Set smtpd_tls_auth_only = yes and disable_plaintext_auth = yes. Use implicit TLS on ports 465, 993, and 995. STARTTLS assessment is out of scope.
- NET-DB-014 - MySQL Symbolic Links Allowed for Tables MEDIUM Low Effort
Add symbolic-links=0 (or skip-symbolic-links ) under [mysqld] and restart the service in a maintenance window.
- NET-DB-015 - MySQL secure_file_priv Not Restricted MEDIUM Low Effort
Add secure_file_priv = NULL (no file operations) or secure_file_priv = /var/lib/mysql-files under [mysqld] and restart in a maintenance window.
- NET-DB-016 - MySQL Does Not Require Encrypted Client Connections MEDIUM Low Effort
Provision a server certificate (MySQL creates one by default), then add require_secure_transport = ON under [mysqld] and restart in a maintenance window. Test every application connection string first.
- NET-DB-019 - PostgreSQL Uses md5 or password Authentication MEDIUM Low Effort
Set password_encryption = scram-sha-256 in postgresql.conf, have every role reset its password so a SCRAM verifier is stored, then change the pg_hba.conf methods to scram-sha-256 and reload.
- NET-DB-020 - PostgreSQL SSL Not Enabled MEDIUM Low Effort
Install a certificate and key readable only by the postgres user, set ssl = on , ssl_cert_file and ssl_key_file, reload, then change remote pg_hba.conf rules from host to hostssl.
- NET-DB-022 - PostgreSQL Password Encryption Not SCRAM MEDIUM Low Effort
Set password_encryption = scram-sha-256 , reload, and ask every role to reset its password so the verifier is regenerated. Then move pg_hba.conf to scram-sha-256 (NET-DB-019).
- NET-DB-023 - Redis Dangerous Commands Not Restricted MEDIUM Low Effort
Prefer ACLs on Redis 6 and newer: user app on >secret ~app:* -@all +@read +@write -@dangerous . Otherwise add rename-command FLUSHALL "" (and the same for FLUSHDB, CONFIG, DEBUG, KEYS) and restart.
- NET-DNS-002 - BIND DNSSEC Validation Disabled MEDIUM Low Effort
Set dnssec-validation auto; in options (remove any no ), run named-checkconf and rndc reconfig. Authoritative-only servers with recursion off may leave it unset.
- NET-MAIL-001 - Postfix SMTP TLS Not Offered or Has No Certificate MEDIUM Low Effort
Set smtpd_tls_security_level = may , smtpd_tls_chain_files = /etc/letsencrypt/live/<host>/privkey.pem, /etc/letsencrypt/live/<host>/fullchain.pem (or smtpd_tls_cert_file and smtpd_tls_key_file), then postfix reload.
- NET-MAIL-002 - Postfix Allows TLS 1.0 or 1.1 MEDIUM Low Effort
Add smtpd_tls_protocols = >=TLSv1.2 and smtpd_tls_mandatory_protocols = >=TLSv1.2 (Postfix 3.6 and newer; on older releases use !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 ), then postfix reload.
- NET-MAIL-004 - Dovecot Does Not Require TLS MEDIUM Low Effort
Set ssl = required and ssl_min_protocol = TLSv1.2 in conf.d/10-ssl.conf, then doveadm reload. Prefer implicit TLS ports 993 and 995 for clients. Caution: clients set to plaintext stop connecting, so confirm every mail client uses TLS first.
- NET-SVC-004 - Management Panel or Monitoring Ports Network-Reachable MEDIUM Low Effort
Bind the panel or exporter to 127.0.0.1 or a management address, put it behind a reverse proxy with authentication, or restrict the port to monitoring hosts in the firewall.
- NET-TLS-001 - Deprecated TLS 1.0 or 1.1 Accepted MEDIUM Low Effort
Apache: SSLProtocol -all +TLSv1.2 +TLSv1.3 . nginx: ssl_protocols TLSv1.2 TLSv1.3; . Postfix/Dovecot: set the minimum protocol to TLSv1.2. Reload the service afterwards.
- NET-TLS-002 - TLS Certificate Expired or Expiring Soon MEDIUM Low Effort
Renew the certificate (certbot renew, or your provider's process) and make sure renewal is automated (systemctl list-timers | grep certbot).
- NET-TLS-003 - Self-Signed or Mismatched TLS Certificate MEDIUM Low Effort
Issue a certificate from a public CA covering every site name, for example with certbot --apache or certbot --nginx -d example.com -d www.example.com.
- NET-TLS-004 - Weak TLS 1.2 Cipher Suites Accepted MEDIUM Low Effort
Allow only modern AEAD suites for TLS 1.2 and prefer TLS 1.3. Remove RC4, 3DES, NULL, EXPORT, anonymous, and CBC with SHA-1 suites. Caution: very old clients and devices that support only those suites stop connecting; check the access logs for them first.
- WEB-APA-003 - Apache Directory Indexes Enabled in Configuration MEDIUM Low Effort
Change the block to Options -Indexes +FollowSymLinks (or remove Indexes). Where a listing is wanted, protect that Directory with Require.
- WEB-APA-011 - Apache Has No Slow Request Protection MEDIUM Low Effort
Enable the module (Debian and Ubuntu: a2enmod reqtimeout; other systems: LoadModule reqtimeout_module modules/mod_reqtimeout.so) and keep or set RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 , then reload.
- WEB-APP-002 - Application .env File Readable by All Users MEDIUM Low Effort
chmod 640 .env && chown <app-user>:<web-group> .env (or 600 when the application runs as its own user). Rotate the secrets if other people have had shell access.
- WEB-APP-005 - Rails Production Does Not Force HTTPS MEDIUM Low Effort
Set config.force_ssl = true in config/environments/production.rb (and config.assume_ssl = true behind a TLS-terminating proxy), then restart the application.
- WEB-APP-009 - Git Repository Stored Inside a Web Root MEDIUM Low Effort
Deploy from a build step that copies only the needed files (git archive, rsync --exclude .git, or a CI artefact), or point the document root at a public/ sub-folder as Laravel, Symfony and Rails expect. Remove the .git folder from the web root and rotate any secret ever committed.
- WEB-APP-010 - Framework Writable Folders Open to All Users MEDIUM Low Effort
chmod -R o-w storage bootstrap/cache var and give the web server group write access instead: chgrp -R www-data storage bootstrap/cache && chmod -R g+w storage bootstrap/cache.
- WEB-CMS-006 - WordPress Shows Debug Output to Visitors MEDIUM Low Effort
In production set define('WP_DEBUG', false);. If you need logs, use define('WP_DEBUG_LOG', '/path/outside/webroot/wp-debug.log'); together with define('WP_DEBUG_DISPLAY', false);.
- WEB-CMS-008 - WordPress Automatic Updates Disabled MEDIUM Low Effort
Remove those lines, or set define('WP_AUTO_UPDATE_CORE', 'minor'); so at least security releases install automatically. Keep backups and enable plugin auto-updates where practical.
- WEB-CMS-009 - Joomla Debug or Verbose Error Reporting Enabled MEDIUM Low Effort
In System, Global Configuration set Debug System to No and Error Reporting to None (or System Default), or set public $debug = false; and public $error_reporting = 'none'; in configuration.php.
- WEB-CMS-013 - Drupal Trusted Host Patterns Not Set MEDIUM Low Effort
Add to settings.php: $settings['trusted_host_patterns'] = ['^www\.example\.com$', '^example\.com$']; then clear caches (drush cr). The status report page should no longer warn about trusted hosts.
- WEB-CMS-015 - Magento Not in Production Mode MEDIUM Low Effort
bin/magento deploy:mode:set production (which also deploys static content and compiles DI), then clear caches. Keep developer mode for staging only.
- WEB-CMS-016 - Ghost Configured With a Plain HTTP Site URL MEDIUM Low Effort
ghost config url https://<your-domain> (or edit config.production.json), set up TLS with ghost setup ssl or your reverse proxy, then ghost restart.
- WEB-COR-001 - Cross-Origin Resource Sharing Allows Any Origin With Credentials MEDIUM Low Effort
Return Access-Control-Allow-Origin only for an explicit allow-list of trusted origins, never '*' or 'null' together with credentials, and add Vary: Origin.
- WEB-DOC-003 - Archives or Certificates Inside a Web Root MEDIUM Low Effort
Confirm each file is meant to be public. Move backups and anything holding a private key outside the document root, rotate any exposed key, and keep published downloads in a dedicated folder such as /downloads/.
- WEB-EXP-003 - PHP Information Page Exposed MEDIUM Low Effort
Delete the file. Never leave diagnostic pages on a production server.
- WEB-EXP-005 - Directory Listing Enabled MEDIUM Low Effort
Apache: Options -Indexes . nginx: autoindex off; (the default). Add an empty index.html to folders that must stay browsable-free.
- WEB-EXP-006 - Web Server Status Page Exposed MEDIUM Low Effort
Restrict to administrators: <Location /server-status> Require local </Location> (Apache), or allow 127.0.0.1; deny all; (nginx). Remove the module if unused.
- WEB-EXP-011 - Database Administration Tool Exposed MEDIUM Low Effort
Remove the tool, or restrict it to administrators by IP allow-list, VPN or an extra authentication layer, and keep it updated.
- WEB-HDR-001 - Missing HTTP Strict Transport Security (HSTS) MEDIUM Low Effort
Apache: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" . nginx: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; . Only add 'preload' once every subdomain supports HTTPS.
- WEB-HDR-003 - Site Can Be Framed (Clickjacking) MEDIUM Low Effort
Send Content-Security-Policy: frame-ancestors 'self' (modern) and X-Frame-Options: SAMEORIGIN (older browsers).
- WEB-NGX-002 - nginx Directory Listing Enabled in Configuration MEDIUM Low Effort
Remove autoindex on; or set autoindex off; in that block. Where a listing is really needed, protect the location with auth_basic or an allow list.
- WEB-NGX-007 - nginx Serves Hidden Files and Folders MEDIUM Low Effort
Add to every server block: location ~ /\. { deny all; access_log off; log_not_found off; } and keep .well-known reachable with a more specific location ^~ /.well-known/ block before it.
- WEB-PHP-001 - PHP Displays Errors to Visitors MEDIUM Low Effort
In php.ini set display_errors = Off and log_errors = On , then restart PHP-FPM or the web server.
- WEB-PHP-005 - PHP Session Cookies Not Hardened MEDIUM Low Effort
In php.ini set session.cookie_httponly = 1 , session.use_strict_mode = 1 , session.cookie_samesite = Lax and, for HTTPS sites, session.cookie_secure = 1 , then restart PHP-FPM.
- WEB-PY-002 - Django Accepts Any Host Header MEDIUM Low Effort
List the real domain names: ALLOWED_HOSTS = ['example.com', 'www.example.com'], and restart the application.
- WEB-TLS-001 - Site Available Over Plain HTTP Without Redirect MEDIUM Low Effort
Apache: in the port 80 vhost add Redirect permanent / https://<site>/ . nginx: return 301 https://$host$request_uri; . Get a free certificate with certbot if HTTPS is not set up yet.
- WEB-TOM-003 - Tomcat Shutdown Port Uses the Default Command MEDIUM Low Effort
Disable the port with <Server port="-1" ...> and stop Tomcat through systemd, or set shutdown to a long random string. Restart Tomcat.
- WEB-TOM-005 - Tomcat Example and Documentation Applications Deployed MEDIUM Low Effort
Delete the examples and docs folders from webapps (or apt remove tomcatN-examples tomcatN-docs) and restart Tomcat.
- HOST-BOOT-001 - Boot Loader Has No Password MEDIUM Medium Effort
Run grub-mkpasswd-pbkdf2 (grub2-setpassword on RHEL family), add set superusers="admin" and password_pbkdf2 admin <hash> to /etc/grub.d/40_custom (RHEL family writes /boot/grub2/user.cfg), then regenerate with update-grub or grub2-mkconfig -o /boot/grub2/grub.cfg. Add --unrestricted to the normal menu entry so unattended reboots still work.
- HOST-BOOT-006 - No File Integrity Monitoring MEDIUM Medium Effort
Install AIDE (apt install aide / dnf install aide), initialise the database with aideinit or aide --init, move the new database into place, and enable the daily check (dailyaidecheck.timer on Debian family, or a cron.daily entry) that mails or logs the differences.
- HOST-CTR-002 - Docker Daemon Not Hardened MEDIUM Medium Effort
Add to /etc/docker/daemon.json: "no-new-privileges": true, "icc": false, "userns-remap": "default", "live-restore": true then restart Docker after testing your containers.
- HOST-CTR-012 - Containers Run Without Memory or Process Limits MEDIUM Medium Effort
Recreate each container with --memory (for example 512m) and --pids-limit (for example 256), or set them in the compose file under deploy.resources.limits / pids_limit.
- HOST-CTR-013 - Containers Run as Root With a Writable Root Filesystem MEDIUM Medium Effort
Add USER <uid> to the image or run with --user 1000:1000, and start the container with --read-only plus --tmpfs /tmp for scratch space; recreate the container.
- HOST-FS-016 - SUID or SGID Programs Outside the Known Baseline MEDIUM Medium Effort
For each listed program decide whether the bit is needed. Remove it with chmod u-s,g-s <path> or uninstall the package. Record the ones you keep so the next review is quick. Caution: programs such as passwd, sudo, su, mount and ping need their bit to work for normal users; removing it from those breaks password changes and administrator access.
- HOST-PKG-005 - Running Kernel Older Than Installed Kernel MEDIUM Medium Effort
Schedule a maintenance window and reboot into the newest kernel. Where downtime is a problem, use the distribution's live patching service and still plan regular reboots.
- HOST-PWD-004 - No Account Lockout After Failed Logins MEDIUM Medium Effort
Enable pam_faillock (authselect enable-feature with-faillock on RHEL family; pam-auth-update or a faillock profile on Debian/Ubuntu) with settings such as deny=5 unlock_time=900 in /etc/security/faillock.conf. Keep a root session open and test a login in a second session before closing it: a wrong PAM line can lock every user out, including administrators. Do not lock root (no even_deny_root) unless console access is assured.
- HOST-SYSD-001 - Custom Services Run as Root MEDIUM Medium Effort
Create a dedicated account (useradd --system --no-create-home --shell /usr/sbin/nologin <app>), give it ownership of only the folders the app writes to, then add User=<app> and Group=<app> to the [Service] section (or DynamicUser=yes). Run systemctl daemon-reload and restart the service. Ports below 1024 can be allowed with AmbientCapabilities=CAP_NET_BIND_SERVICE instead of root.
- HOST-UPD-002 - Reboot Required to Apply Updates MEDIUM Medium Effort
Schedule a maintenance window and reboot (or use live patching where supported).
- HOST-USR-004 - Duplicate User IDs MEDIUM Medium Effort
Give each account a unique UID (usermod -u <new-uid> <user>) and fix file ownership (find / -xdev -uid <old-uid>).
- HOST-USR-008 - Duplicate Group IDs or Account Names MEDIUM Medium Effort
groupmod -g <new-gid> <group> for one of each duplicate pair, then fix file ownership (find / -xdev -gid <old-gid>); remove or rename the duplicate name entries with vigr and vipw, which lock the files while editing.
- NET-FW-001 - No Active Host Firewall MEDIUM Medium Effort
Ubuntu: ufw default deny incoming && ufw allow OpenSSH && ufw allow 80,443/tcp && ufw enable . RHEL family: systemctl enable --now firewalld . Always allow SSH before enabling, or you will lock yourself out.
- NET-FW-005 - Container Ports Bypass the Host Firewall MEDIUM Medium Effort
Publish container ports on loopback only (-p 127.0.0.1:8080:80) and put a reverse proxy in front, or add filtering to DOCKER-USER, for example: iptables -I DOCKER-USER -i eth0 ! -s 203.0.113.0/24 -j DROP (persist it with your firewall tooling). Caution: test from an allowed address first; a wrong interface name or source range cuts access to every published container.
- NET-TLS-005 - TLS Certificate Public Key Too Small MEDIUM Medium Effort
Replace the certificate and private key with RSA 2048 bits or stronger, or an approved EC key of at least 256 bits.
- NET-TLS-006 - SHA-1 Signed TLS Leaf Certificate MEDIUM Medium Effort
Reissue the certificate with SHA-256 or stronger and deploy the complete updated chain.
- WEB-CK-001 - Cookies Missing Secure, HttpOnly or SameSite MEDIUM Medium Effort
PHP: session.cookie_secure=1, session.cookie_httponly=1, session.cookie_samesite=Lax in php.ini . Frameworks have equivalent settings (e.g. Laravel config/session.php). Use HttpOnly for every cookie JavaScript does not need to read.
- WEB-HDR-002 - Missing Content Security Policy MEDIUM Medium Effort
Start with a report-only policy to find what the site loads, then enforce, for example: Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
- WEB-PY-005 - Python Development Server Used in a Service MEDIUM Medium Effort
Serve the application with a production server (Gunicorn or uWSGI for WSGI, Uvicorn without --reload or Hypercorn for ASGI) bound to 127.0.0.1, behind nginx or Apache. Serve static files from the web server.
- HOST-BOOT-002 - UEFI Secure Boot Disabled MEDIUM High Effort
Enable Secure Boot in the firmware set-up and boot a signed shim and kernel (every mainstream distribution ships them). Custom kernels and out-of-tree modules then need signing with a Machine Owner Key. Where the platform cannot do Secure Boot, record the exception. Caution: unsigned kernels and modules (for example DKMS drivers such as NVIDIA or ZFS) stop loading once it is on, so sign or replace them first and keep console access for the first boot.
- HOST-AUD-001 - Audit Daemon Not Enabled at Boot LOW Low Effort
systemctl enable auditd (on some distributions: systemctl enable --now auditd). Then confirm the rules in /etc/audit/rules.d load at boot with augenrules --check.
- HOST-AUD-002 - Identity Files Not Audited LOW Low Effort
Add to /etc/audit/rules.d/50-identity.rules: -w /etc/passwd -p wa -k identity and the same for /etc/group, /etc/shadow, /etc/gshadow, /etc/sudoers and /etc/sudoers.d/ , then run augenrules --load.
- HOST-AUD-003 - Login and Logout Events Not Audited LOW Low Effort
Add to /etc/audit/rules.d/50-login.rules: -w /var/log/lastlog -p wa -k logins , -w /var/run/faillock -p wa -k logins , -w /var/log/wtmp -p wa -k session , -w /var/log/btmp -p wa -k session , then augenrules --load.
- HOST-AUD-004 - System Time Changes Not Audited LOW Low Effort
Add to /etc/audit/rules.d/50-time.rules: -a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change (and the same with arch=b32), plus -w /etc/localtime -p wa -k time-change , then augenrules --load.
- HOST-AUD-005 - Kernel Module Loading Not Audited LOW Low Effort
Add to /etc/audit/rules.d/50-modules.rules: -a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k modules (and arch=b32), or -a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset -k modules , then augenrules --load.
- HOST-AUD-006 - Privileged Command Use Not Audited LOW Low Effort
Generate rules for every setuid and setgid program: find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=unset -k privileged"}' > /etc/audit/rules.d/50-privileged.rules then augenrules --load.
- HOST-AUD-007 - Audit Configuration Not Immutable LOW Low Effort
Add -e 2 as the last line of the last file in /etc/audit/rules.d (for example 99-finalize.rules), then augenrules --load and reboot. Plan rule changes before enabling it: every later change needs a reboot.
- HOST-AUD-008 - Audit Log Files Readable by Others LOW Low Effort
chmod 0750 /var/log/audit && chmod 0600 /var/log/audit/* && chown -R root:root /var/log/audit , and set log_group = root in /etc/audit/auditd.conf so new files keep these modes.
- HOST-AUD-009 - Audit Daemon Ignores a Full Log Disk LOW Low Effort
In /etc/audit/auditd.conf set max_log_file_action = keep_logs (or rotate with enough num_logs), space_left_action = email (or syslog or exec), and admin_space_left_action = halt or single as policy requires, then systemctl restart auditd. Caution: admin_space_left_action = halt or single stops the server or drops it to single-user mode when the audit disk fills; choose it only where losing audit records is worse than downtime, and give /var/log/audit room and monitoring first.
- HOST-AUD-010 - Journal Not Persistent or Not Compressed LOW Low Effort
In /etc/systemd/journald.conf set Storage=persistent and Compress=yes , create the directory with mkdir -p /var/log/journal && systemd-tmpfiles --create --prefix /var/log/journal , then systemctl restart systemd-journald.
- HOST-BOOT-007 - Prelink Installed LOW Low Effort
Undo and remove it: prelink -ua && apt purge prelink (or dnf remove prelink). Then re-initialise the integrity database (aide --init).
- HOST-BOOT-008 - Core Dumps Not Restricted LOW Low Effort
Add * hard core 0 to /etc/security/limits.conf (or a file in limits.d), set Storage=none and ProcessSizeMax=0 in the [Coredump] section of /etc/systemd/coredump.conf, and keep fs.suid_dumpable = 0.
- HOST-CTR-005 - Docker Container Logs Have No Size Limit LOW Low Effort
Add to /etc/docker/daemon.json: "log-driver": "json-file", "log-opts": {"max-size": "10m", "max-file": "3"} (or use journald) and restart Docker; recreate containers that set their own LogConfig.
- HOST-CTR-006 - Docker Userland Proxy Enabled LOW Low Effort
Add "userland-proxy": false to /etc/docker/daemon.json and restart Docker; test that published ports still answer from the host itself.
- HOST-CTR-007 - Docker Default Ulimits Not Set LOW Low Effort
Add to /etc/docker/daemon.json: "default-ulimits": {"nofile": {"Name": "nofile", "Hard": 65536, "Soft": 32768}, "nproc": {"Name": "nproc", "Hard": 4096, "Soft": 2048}} and restart Docker; tune the numbers to your workloads.
- HOST-FS-009 - Default File Creation Mask Too Permissive LOW Low Effort
Set UMASK 027 in /etc/login.defs (and, if used, in /etc/profile or /etc/bash.bashrc).
- HOST-FS-015 - Files With No Known Owner or Group LOW Low Effort
Decide who should own each listed file and apply chown <user>:<group> <path>, or remove files that belonged to a deleted account after checking their contents.
- HOST-FS-018 - Kernel Symbol Map or Initial RAM Disk Readable by Others LOW Low Effort
chmod 600 /boot/System.map-* /boot/initrd* /boot/initramfs* and, on Debian family systems, set UMASK=0077 in /etc/initramfs-tools/initramfs.conf so new images are created private.
- HOST-FS-019 - Cron and At Not Restricted to Allowed Users LOW Low Effort
Create the allow lists: touch /etc/cron.allow /etc/at.allow && chmod 600 /etc/cron.allow /etc/at.allow && chown root:root /etc/cron.allow /etc/at.allow then add one user name per line for the accounts that need scheduling, and remove /etc/cron.deny and /etc/at.deny. Caution: once cron.allow exists, crontabs of users not listed stop running, so list every service and user account that has a crontab (ls /var/spool/cron/crontabs or /var/spool/cron) before creating it.
- HOST-FS-020 - Cron Configuration Readable by Other Users LOW Low Effort
chown root:root /etc/crontab /etc/cron.* && chmod 600 /etc/crontab && chmod 700 /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly
- HOST-FS-021 - Shell Profile Sets a Permissive File Creation Mask LOW Low Effort
Change every umask 022 line in the listed files to umask 027, or remove the line so the login.defs value applies. Users start a new login shell to pick it up.
- HOST-IDS-001 - No Brute-Force Protection Service LOW Low Effort
Install and enable one, for example: apt install fail2ban && systemctl enable --now fail2ban , with an sshd jail enabled.
- HOST-KRN-002 - Kernel Pointers Exposed to Unprivileged Users LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.kptr_restrict = 1 then apply with: sysctl --system
- HOST-KRN-003 - Kernel Log Readable by Unprivileged Users LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.dmesg_restrict = 1 then apply with: sysctl --system
- HOST-KRN-004 - Setuid Programs May Dump Core LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.suid_dumpable = 0 then apply with: sysctl --system
- HOST-KRN-005 - IP Forwarding Enabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.ip_forward = 0 then apply with: sysctl --system
- HOST-KRN-006 - ICMP Redirects Accepted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.accept_redirects = 0 then apply with: sysctl --system
- HOST-KRN-007 - Source-Routed Packets Accepted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.accept_source_route = 0 then apply with: sysctl --system
- HOST-KRN-008 - TCP SYN Cookies Disabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.tcp_syncookies = 1 then apply with: sysctl --system
- HOST-KRN-010 - Process Tracing Not Restricted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.yama.ptrace_scope = 1 then apply with: sysctl --system
- HOST-KRN-011 - Symlink Protection Disabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_symlinks = 1 then apply with: sysctl --system
- HOST-KRN-012 - Hardlink Protection Disabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_hardlinks = 1 then apply with: sysctl --system
- HOST-KRN-013 - Reverse Path Filtering Disabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.rp_filter = 1 then apply with: sysctl --system
- HOST-KRN-014 - Martian Packets Not Logged LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.log_martians = 1 then apply with: sysctl --system
- HOST-KRN-015 - Server Sends ICMP Redirects LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.send_redirects = 0 then apply with: sysctl --system
- HOST-KRN-016 - Broadcast ICMP Echo Answered LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.icmp_echo_ignore_broadcasts = 1 then apply with: sysctl --system
- HOST-KRN-017 - IPv6 ICMP Redirects Accepted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv6.conf.all.accept_redirects = 0 then apply with: sysctl --system
- HOST-KRN-018 - Performance Events Open to Unprivileged Users LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.perf_event_paranoid = 2 then apply with: sysctl --system
- HOST-KRN-019 - Magic SysRq Key Enabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.sysrq = 0 then apply with: sysctl --system
- HOST-KRN-020 - FIFO Protection in Shared Directories Disabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_fifos = 1 then apply with: sysctl --system
- HOST-KRN-021 - Regular File Protection in Shared Directories Disabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_regular = 1 then apply with: sysctl --system
- HOST-KRN-022 - Unprivileged User Namespaces Allowed LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing kernel.unprivileged_userns_clone = 0 (Debian family) or user.max_user_namespaces = 0 (other kernels), then apply with: sysctl --system. Rootless Docker, Podman, Flatpak and some browsers need user namespaces, so test first.
- HOST-KRN-023 - IPv6 Source-Routed Packets Accepted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv6.conf.all.accept_source_route = 0 then apply with: sysctl --system
- HOST-KRN-024 - Secure ICMP Redirects Accepted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.secure_redirects = 0 then apply with: sysctl --system
- HOST-KRN-025 - IPv6 Router Advertisements Accepted LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv6.conf.all.accept_ra = 0 then apply with: sysctl --system. Caution: on a host that gets its IPv6 address or default route from router advertisements (SLAAC, most cloud dual-stack VMs), accept_ra = 0 removes the IPv6 default route and cuts IPv6 connectivity. Use it only with static IPv6 addressing; otherwise keep accept_ra = 1 and rely on RA Guard on the switch or a host firewall rule for RA sources.
- HOST-KRN-026 - Bogus ICMP Error Responses Logged LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.icmp_ignore_bogus_error_responses = 1 then apply with: sysctl --system
- HOST-KRN-027 - Kexec Kernel Replacement Allowed LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.kexec_load_disabled = 1 then apply with: sysctl --system. Caution: kexec_load_disabled = 1 also stops kdump from loading its crash kernel (kdump.service on the RHEL family, kdump-tools on Debian and Ubuntu), so crash dumps are lost. Keep it 0 where kdump is used, or accept that trade-off deliberately. The setting cannot be turned back off without a reboot.
- HOST-KRN-028 - Unprivileged userfaultfd Allowed LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: vm.unprivileged_userfaultfd = 0 then apply with: sysctl --system. Caution: unprivileged live migration tools (for example QEMU post-copy migration or CRIU run as a normal user) need userfaultfd; test those first.
- HOST-KRN-029 - TTY Line Discipline Autoloading Enabled LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: dev.tty.ldisc_autoload = 0 then apply with: sysctl --system
- HOST-KRN-030 - BPF JIT Hardening Off LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.core.bpf_jit_harden = 2 then apply with: sysctl --system
- HOST-KRN-031 - io_uring Open to Unprivileged Users LOW Low Effort
Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.io_uring_disabled = 2 then apply with: sysctl --system. Caution: applications that use io_uring for fast I/O (some databases, proxies and runtimes) fall back or fail to start when it is disabled; test them first, or use 1 to allow only a chosen group.
- HOST-LOG-001 - System Logging Not Persistent LOW Low Effort
Either install and enable rsyslog, or make the journal persistent: mkdir -p /var/log/journal && systemd-tmpfiles --create --prefix /var/log/journal && systemctl restart systemd-journald
- HOST-LOG-003 - Security Logs Readable by All Users LOW Low Effort
chmod o-rwx /var/log/auth.log /var/log/secure /var/log/syslog /var/log/messages and set the matching create mode in /etc/logrotate.d.
- HOST-LOG-004 - Log Rotation Not Configured LOW Low Effort
Install logrotate (apt install logrotate / dnf install logrotate) and keep its daily timer enabled, or set SystemMaxUse= in journald.conf.
- HOST-PAM-001 - Password Quality Module Not Enforced LOW Low Effort
Install libpam-pwquality (Debian/Ubuntu) or libpwquality (RHEL family). Make sure the password stack has password requisite pam_pwquality.so retry=3 before pam_unix (pam-auth-update or authselect enable-feature with-pwquality), and in /etc/security/pwquality.conf keep dictcheck = 1 and usercheck = 1 . Pair it with a breached-password blocklist where possible. Keep a root session open and test a login and a password change in a second session before closing it: a wrong PAM line can lock every user out.
- HOST-PAM-002 - Account Lockout Releases Too Quickly LOW Low Effort
In /etc/security/faillock.conf set unlock_time = 900 (or 0 to require an administrator to run faillock --reset), keeping deny between 3 and 10. Keep a root session open and test in a second session before closing the first: a wrong PAM line can lock every user out, and unlock_time = 0 means locked accounts, administrators included, wait for faillock --reset.
- HOST-PAM-003 - su Not Restricted to an Administrative Group LOW Low Effort
In /etc/pam.d/su uncomment or add auth required pam_wheel.so use_uid group=sudo (group=wheel on the RHEL family), and make sure the group contains only administrators. Caution: add every administrator who uses su to that group first and test from a second session, or they lose su access.
- HOST-PAM-004 - Password History Not Enforced LOW Low Effort
Add password required pam_pwhistory.so remember=5 use_authtok before pam_unix in the password stack (pam-auth-update on Debian/Ubuntu, authselect enable-feature with-pwhistory on the RHEL family), or set remember = 5 in /etc/security/pwhistory.conf. Keep a root session open and test a password change in a second session before closing it: a wrong PAM line can block password changes or logins.
- HOST-PAM-005 - Minimum Password Age Not Set LOW Low Effort
Set PASS_MIN_DAYS 1 in /etc/login.defs, and for existing accounts chage --mindays 1 <user> .
- HOST-PAM-007 - Inactive Accounts Never Locked LOW Low Effort
useradd -D -f 30 (writes INACTIVE=30 to /etc/default/useradd), and for existing accounts chage --inactive 30 <user> . Caution: this locks accounts whose password has expired for 30 days, so exempt break-glass and rarely used administrator accounts or keep their passwords current.
- HOST-PAM-009 - No Shell Idle Timeout LOW Low Effort
Create /etc/profile.d/99-tmout.sh with TMOUT=900 ; readonly TMOUT ; export TMOUT (mode 644, owned by root). Sessions that must stay open should use a multiplexer such as tmux with its own lock, not a longer TMOUT. Caution: a readonly TMOUT ends idle interactive shells, including foreground jobs left waiting in them; run long jobs under nohup, systemd-run or a multiplexer.
- HOST-PKG-004 - Many Old Kernels Retained LOW Low Effort
Debian/Ubuntu: apt-get autoremove --purge removes kernels outside the keep list. RHEL family: set installonly_limit=3 in /etc/dnf/dnf.conf and run dnf remove --oldinstallonly . Never remove the running kernel (uname -r).
- HOST-PKG-006 - Package Lists Not Refreshed Automatically LOW Low Effort
Debian/Ubuntu: create /etc/apt/apt.conf.d/20auto-upgrades with APT::Periodic::Update-Package-Lists "1"; (dpkg-reconfigure unattended-upgrades writes it) and systemctl enable apt-daily.timer . RHEL family: systemctl enable --now dnf-makecache.timer .
- HOST-PWD-003 - Short Minimum Password Length LOW Low Effort
Install libpam-pwquality (Debian/Ubuntu) or libpwquality (RHEL family) and set minlen = 15 (or more) in /etc/security/pwquality.conf.
- HOST-SSH-005 - SSH X11 Forwarding Enabled LOW Low Effort
Set X11Forwarding no in /etc/ssh/sshd_config and reload sshd.
- HOST-SSH-006 - SSH Allows Many Authentication Attempts LOW Low Effort
Set MaxAuthTries 4 (or lower) in /etc/ssh/sshd_config and reload sshd. Consider fail2ban or sshguard for rate limiting.
- HOST-SSH-008 - SSH Authentication Controls Too Permissive LOW Low Effort
Set LoginGraceTime 60 or lower and choose AuthenticationMethods appropriate to the server, such as publickey, then restrict access with AllowUsers or AllowGroups where practical.
- HOST-SSH-012 - SSH Logging Level Too Low LOW Low Effort
Set LogLevel VERBOSE (or INFO) in /etc/ssh/sshd_config and reload sshd.
- HOST-SSH-013 - SSH Authorized Keys Without Restrictions or Protection LOW Low Effort
Prefix each root key with options, for example from="203.0.113.0/24",no-port-forwarding,no-agent-forwarding or command="/usr/local/bin/backup",restrict ; chmod 600 ~/.ssh/authorized_keys and 700 ~/.ssh for every account. Prefer sudo from a personal account over direct root keys.
- HOST-SUDO-001 - Sudo Commands Not Logged to a Dedicated File LOW Low Effort
With visudo add: Defaults use_pty and Defaults logfile="/var/log/sudo.log"
- HOST-SVC-001 - Unnecessary Legacy Services Running LOW Low Effort
systemctl disable --now <service> for each listed service you do not need, or remove its package. Caution: check first that nothing depends on it (systemctl list-dependencies --reverse <service>) and keep console access when disabling network or remote-access services.
- HOST-SVC-007 - Avahi or CUPS Installed or Enabled LOW Low Effort
apt purge avahi-daemon cups cups-daemon or dnf remove avahi cups , and systemctl disable --now avahi-daemon.socket avahi-daemon.service cups.socket cups.service . Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-008 - NFS Server or rpcbind Installed or Enabled LOW Low Effort
apt purge nfs-kernel-server rpcbind or dnf remove nfs-utils rpcbind where NFS is not served, and systemctl disable --now nfs-server rpcbind.socket rpcbind.service . Where NFS is required, export read-only with root_squash to named hosts and firewall port 2049 and 111. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-009 - DHCP or DNS Server Installed or Enabled LOW Low Effort
apt purge isc-dhcp-server bind9 or dnf remove dhcp-server bind , and systemctl disable --now isc-dhcp-server named . If this machine is meant to be a DNS or DHCP server, record that in the suppression file and review NET-SVC findings for its configuration. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-010 - Samba File Server Installed or Enabled LOW Low Effort
apt purge samba or dnf remove samba , and systemctl disable --now smbd nmbd (smb nmb on the RHEL family). Where it is required, disable SMB1, require signing and restrict shares to named users. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-011 - SNMP Agent or Squid Proxy Installed or Enabled LOW Low Effort
apt purge snmpd squid or dnf remove net-snmp squid , and systemctl disable --now snmpd squid . If monitoring needs SNMP, use version 3 with authPriv and bind the agent to the management network. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-SVC-012 - inetd Super-Server Installed or Enabled LOW Low Effort
apt purge xinetd openbsd-inetd or dnf remove xinetd , and systemctl disable --now xinetd . Review /etc/inetd.conf and /etc/xinetd.d first so nothing needed disappears. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- HOST-TIME-001 - Time Synchronisation Not Active LOW Low Effort
Enable one time service, for example: systemctl enable --now systemd-timesyncd (or install chrony).
- HOST-UPD-001 - Automatic Security Updates Not Configured LOW Low Effort
Debian/Ubuntu: apt install unattended-upgrades && dpkg-reconfigure -plow unattended-upgrades . RHEL family: dnf install dnf-automatic, set apply_updates = yes and upgrade_type = security, then systemctl enable --now dnf-automatic.timer .
- HOST-USR-005 - System Accounts With Login Shells LOW Low Effort
usermod -s /usr/sbin/nologin <account> for each listed account (use /sbin/nologin on RHEL family).
- HOST-USR-010 - Home Directories Accessible to Other Users LOW Low Effort
chmod 750 /home/<user> for each listed account (700 if group access is not needed), and set HOME_MODE 0750 in /etc/login.defs or DIR_MODE=0750 in /etc/adduser.conf so new accounts start that way.
- NET-DB-017 - MySQL Error Log Not Configured LOW Low Effort
Add log_error = /var/log/mysql/error.log under [mysqld], make the folder writable by the mysql user, and add a logrotate rule.
- NET-DB-018 - MySQL Resolves Client Host Names LOW Low Effort
Rewrite grants that use host names to IP addresses or '%', then add skip-name-resolve under [mysqld] and restart in a maintenance window.
- NET-DB-021 - PostgreSQL Connection Logging Off LOW Low Effort
Set log_connections = on and log_disconnections = on in postgresql.conf and reload. On PostgreSQL 18 and newer, log_connections accepts a list such as receipt,authentication,authorization .
- NET-DNS-001 - BIND Version String Disclosed LOW Low Effort
Add version "not disclosed"; inside the options block and run named-checkconf, then rndc reconfig.
- NET-FW-004 - Firewall Rules Open Ports With No Service LOW Low Effort
Remove rules for services that no longer exist (ufw status numbered, then ufw delete <n>), or note why a rule must stay. Review the firewall whenever a service is retired.
- NET-MAIL-003 - Postfix VRFY Command Enabled LOW Low Effort
Add disable_vrfy_command = yes to main.cf and postfix reload.
- WEB-APA-001 - Apache Reveals Version in Header and Footer LOW Low Effort
Set ServerTokens Prod and ServerSignature Off in apache2.conf or conf-enabled/security.conf (Debian) or httpd.conf (RHEL), then apachectl configtest and reload.
- WEB-APA-002 - Apache TRACE Method Enabled LOW Low Effort
Add TraceEnable Off to the server configuration and reload.
- WEB-APA-004 - Apache AllowOverride All Permits .htaccess Control LOW Low Effort
Set AllowOverride None and move needed rules into the vhost, or allow only what the application needs, for example AllowOverride FileInfo Indexes Limit for WordPress permalinks.
- WEB-APA-007 - Apache OCSP Stapling Not Enabled LOW Low Effort
Add SSLUseStapling On inside the vhost and SSLStaplingCache "shmcb:logs/ssl_stapling(32768)" outside it, as the Mozilla generator produces.
- WEB-APA-009 - Apache ETag Reveals Inode Numbers LOW Low Effort
Set FileETag MTime Size or FileETag None and reload.
- WEB-APA-010 - Apache Serves Repository and Environment Files LOW Low Effort
Add to the server configuration: <DirectoryMatch "/\.(git|svn|hg)"> Require all denied </DirectoryMatch> and <FilesMatch "^\.(env|git|svn)"> Require all denied </FilesMatch> , then reload.
- WEB-APP-007 - Flask Debug Mode Enabled in Application Code LOW Low Effort
Remove debug=True from app.run() and read it from the environment for local work only (app.run(debug=os.environ.get('FLASK_DEBUG') == '1')); serve production with Gunicorn or uWSGI, which never call app.run().
- WEB-CMS-001 - WordPress Version Disclosed LOW Low Effort
Keep WordPress updated (automatic minor updates on). Remove the generator tag (remove_action('wp_head','wp_generator')) and delete readme.html after each update, or block it at the web server.
- WEB-CMS-002 - WordPress XML-RPC Interface Enabled LOW Low Effort
Block it at the web server (<Files xmlrpc.php> Require all denied </Files>) or disable it with a security plugin, unless Jetpack or the mobile app needs it.
- WEB-CMS-003 - WordPress User Accounts Enumerable LOW Low Effort
Restrict the users endpoint to authenticated requests with a security plugin or a small rest_endpoints filter, and use login names that differ from public display names.
- WEB-CMS-007 - WordPress Dashboard File Editor Enabled LOW Low Effort
Add define('DISALLOW_FILE_EDIT', true); to wp-config.php above the line that says to stop editing.
- WEB-CMS-010 - Joomla Version Disclosed LOW Low Effort
Block the folder at the web server (Apache: <Directory "/path/administrator/manifests"> Require all denied </Directory>; nginx: location ^~ /administrator/manifests/ { deny all; }) and keep Joomla updated.
- WEB-CMS-011 - Drupal Version Disclosed by Changelog LOW Low Effort
Delete the changelog files after each update, or deny *.txt files in the Drupal root and core folders at the web server, and keep Drupal updated.
- WEB-CMS-018 - WordPress Author Archive Reveals Login Names LOW Low Effort
Return 404 for author queries by id (a small redirect rule or a security plugin's user enumeration protection), and give administrators a nickname and display name that differ from the login name.
- WEB-EXP-009 - Dependency Manifests Exposed LOW Low Effort
Keep manifests outside the public web root (for example serve only a public/ subfolder), or deny them at the web server.
- WEB-EXP-010 - Default Web Server Page Served LOW Low Effort
Remove the default site or replace its index page, and disable unused virtual hosts.
- WEB-HDR-004 - Missing X-Content-Type-Options LOW Low Effort
Send X-Content-Type-Options: nosniff on every response (Apache: Header always set X-Content-Type-Options nosniff; nginx: add_header X-Content-Type-Options nosniff always;).
- WEB-HDR-005 - Missing Referrer-Policy LOW Low Effort
Send Referrer-Policy: strict-origin-when-cross-origin (or no-referrer). Never use unsafe-url.
- WEB-HDR-006 - Missing Permissions-Policy LOW Low Effort
Send, for example, Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=() adjusted to the features the site really uses.
- WEB-HDR-007 - Server Software Version Disclosed LOW Low Effort
Apache: ServerTokens Prod and ServerSignature Off . nginx: server_tokens off; . PHP: expose_php = Off in php.ini . Remove X-Powered-By in the application or proxy.
- WEB-NGX-001 - nginx Version Shown in Server Header LOW Low Effort
In the http block of nginx.conf add server_tokens off; then run nginx -t and reload.
- WEB-NGX-005 - nginx OCSP Stapling Off or Session Tickets On LOW Low Effort
Add ssl_stapling on; ssl_stapling_verify on; ssl_session_tickets off; and a resolver directive, as the Mozilla generator produces.
- WEB-NODE-003 - Node.js Service Not Running in Production Mode LOW Low Effort
Add Environment=NODE_ENV=production to the [Service] section (systemctl edit <unit>), run systemctl daemon-reload and restart the service.
- WEB-PHP-002 - PHP Version Exposed in Headers LOW Low Effort
In php.ini set expose_php = Off and restart PHP.
- HOST-AUD-011 - Logs Not Forwarded to a Remote Collector LOW Medium Effort
rsyslog: create /etc/rsyslog.d/90-remote.conf with *.* action(type="omfwd" target="logs.example.internal" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="x509/name") and restart rsyslog. Or configure systemd-journal-upload with URL= pointing at a journal-remote collector. Prefer TLS so logs are not readable in transit.
- HOST-BOOT-005 - Kernel Module Loading Unrestricted LOW Medium Effort
Boot with module.sig_enforce=1 (or lockdown=integrity) on the kernel command line and sign any out-of-tree modules, or set kernel.modules_disabled = 1 from a late boot service once every needed module is loaded (it cannot be turned back on without a reboot).
- HOST-CTR-015 - Docker Content Trust Not Enabled LOW Medium Effort
Add DOCKER_CONTENT_TRUST=1 to /etc/environment (or a file in /etc/profile.d) and sign your own images with docker trust sign; images without signatures then need an explicit --disable-content-trust for a deliberate exception.
- HOST-CVE-003 - Vulnerability Snapshot Outdated or Test Data LOW Medium Effort
Install the vendor security update. For a source build, run 'make vulndb' to embed a snapshot generated from OSV and CISA KEV, then rebuild.
- HOST-FS-008 - Temporary Filesystems Allow Executables or Devices LOW Medium Effort
Mount the path as tmpfs or a separate filesystem with options nodev,nosuid (and noexec where software allows), for example via systemd tmp.mount or /etc/fstab, then remount.
- HOST-FS-010 - /var/tmp Not a Separate Filesystem LOW Medium Effort
Mount /var/tmp as a separate filesystem, or bind-mount it onto /tmp: /tmp /var/tmp none bind,nodev,nosuid,noexec 0 0 in /etc/fstab, then reboot or remount. Caution: /var/tmp is meant to survive reboots and some installers and databases run programs from it, so check what uses it before binding it to /tmp with noexec, and keep console access when editing /etc/fstab (a wrong line can stop the boot).
- HOST-FS-011 - /home Not a Separate Filesystem With nodev LOW Medium Effort
Place /home on its own partition or logical volume and add nodev,nosuid to its options in /etc/fstab; remount with: mount -o remount /home . Caution: moving /home to a new volume needs a backup, a maintenance window and console access; a wrong /etc/fstab line can stop the boot.
- HOST-FS-012 - Log Directories on the Root Filesystem LOW Medium Effort
Place /var/log (and ideally /var/log/audit) on its own partition or logical volume, listed in /etc/fstab with nodev,nosuid,noexec. Caution: moving log directories needs a backup, a maintenance window and console access; stop the logging services while copying, and a wrong /etc/fstab line can stop the boot.
- HOST-FS-013 - Temporary Filesystems Allow Executables LOW Medium Effort
Add noexec to the mount options of each temporary filesystem (systemd tmp.mount drop-in or /etc/fstab) and remount. Some package managers need exec on /tmp during installs; set TMPDIR for them rather than removing noexec.
- HOST-LOG-002 - Security Audit Daemon Not Running LOW Medium Effort
Install the audit package (apt install auditd, or dnf install audit), enable it (systemctl enable --now auditd) and load a rule set appropriate to your policy.
- HOST-SYSD-002 - Custom Services Lack Sandboxing LOW Medium Effort
Add the missing lines with systemctl edit <unit> (a drop-in), for example NoNewPrivileges=yes, ProtectSystem=strict, ReadWritePaths=/var/lib/<app>, PrivateTmp=yes, ProtectHome=yes. Restart the service and test it; add ReadWritePaths= for every folder the app must write. systemd-analyze security <unit> suggests further options.
- HOST-MAC-001 - No Mandatory Access Control Enforced LOW High Effort
Ubuntu/Debian: keep AppArmor enabled (systemctl enable --now apparmor) and its profiles in enforce mode. RHEL family: set SELINUX=enforcing in /etc/selinux/config and relabel. Test applications in permissive or complain mode first.
- HOST-PAM-006 - Password Expiry Warning Too Short INFO Low Effort
Set PASS_WARN_AGE 7 in /etc/login.defs, and for existing accounts chage --warndays 7 <user> .
- HOST-PWD-005 - Forced Periodic Password Rotation Configured INFO Low Effort
Prefer long passphrases, a breached-password blocklist and multi-factor authentication over forced rotation. If policy allows, set PASS_MAX_DAYS 365 or 99999 in /etc/login.defs and change passwords when compromise is suspected.
- WEB-APA-008 - Apache Has No Request Filtering Module INFO Low Effort
Consider ModSecurity with the OWASP Core Rule Set in detection-only mode first, or mod_evasive for simple rate limiting, and tune before blocking.
- WEB-CMS-017 - WordPress Cron Reachable by Visitors INFO Low Effort
Add define('DISABLE_WP_CRON', true); to wp-config.php, run */5 * * * * www-data php /var/www/<site>/wp-cron.php from the system cron (or curl the URL from cron), and deny direct requests to wp-cron.php at the web server.
- WEB-NGX-006 - nginx Request Limits Not Configured INFO Low Effort
Set client_max_body_size to what the application needs (the default is 1m) and add limit_req_zone for login and API locations with a sensible rate. See the nginx limit_req and limit_conn module documentation.
- WEB-SEC-001 - No security.txt Contact File INFO Low Effort
Publish /.well-known/security.txt with at least Contact: and Expires: fields (see securitytxt.org).
- HOST-PKG-003 - Third-Party Package Repositories Present INFO Medium Effort
For each listed repository, record who runs it and why it is needed; remove the ones nobody can justify (delete the file under /etc/apt/sources.list.d or /etc/yum.repos.d and apt-get update or dnf clean all). Keep the rest pinned to the packages they are for (apt preferences, dnf includepkgs).
- WEB-APP-008 - Dependency Lock Files Older Than a Year INFO Medium Effort
Run composer update / npm update / bundle update / poetry update in a test environment, run the audit command of each ecosystem (composer audit, npm audit, bundle audit, pip-audit) and deploy. Schedule dependency updates at least quarterly.
- HOST-CTR-009 - Docker Not Running in Rootless Mode INFO High Effort
Where the workloads allow it, install rootless Docker (dockerd-rootless-setuptool.sh install) for the service account and disable the system daemon; otherwise keep userns-remap (HOST-CTR-002) as the fallback.
Findings
CRITICALDocker API Exposed Over TCP Without TLS
HOST-CTR-001
Checks whether the Docker daemon is configured to listen on a TCP socket without TLS client verification.
Why it matters. The Docker API is equivalent to root on the host. Exposed over TCP without mutual TLS, anyone who can reach the port can start a privileged container and take over the machine; this is a common cause of cryptomining infections.
docker: Docker API listens on TCP without TLS verification
daemon.json hosts: tcp://0.0.0.0:2375
- Fix
- Remove tcp:// listeners and use the local Unix socket or SSH (docker context with ssh://). If remote access is unavoidable, enable tlsverify with client certificates and restrict the port in the firewall.
- Verify
ss -tlnp | grep -E ':(2375|2376)' and grep -r 'tcp://' /etc/docker /etc/systemd/system/docker.service.d
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-319, OWASP A05:2021, A07:2021, NIST 800-53 AC-3, SC-8
- References
- Docker documentation, Protect the Docker daemon socket
OWASP Docker Security Cheat Sheet
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/containers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALKnown Exploited Vulnerabilities Present
HOST-CVE-002
Checks installed packages against an offline vulnerability snapshot.
Why it matters. Known vulnerable package versions can expose a server to documented attacks.
sudo: sudo 1.8.21p2-3ubuntu1.4: LAB-CVE-2021-3156 (CVE-2021-3156), fixed in 1.8.21p2-3ubuntu1.5, severity high
matcher: range
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
policykit-1: policykit-1 0.105-20ubuntu0.18.04.5: LAB-CVE-2021-4034 (CVE-2021-4034), fixed in 0.105-20ubuntu0.18.04.6, severity high
matcher: range
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
- Fix
- Install the vendor security update. For a source build, run 'make vulndb' to embed a snapshot generated from OSV and CISA KEV, then rebuild.
- Verify
Re-run OpenVAPT after patching and confirm the finding is absent.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, RA-5
- References
- OSV vulnerability database
NVD
CISA KEV
- Learn
- P10: Vulnerability Management: CVE, OSV and Known Exploited Vulnerabilities (offline:
openvapt learn P10)
- Source
internal/checks/host/cve.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALKubelet Allows Anonymous or Unauthorised Access
HOST-K8S-001
Checks the kubelet configuration for anonymous authentication, AlwaysAllow authorisation or the unauthenticated read-only port.
Why it matters. The kubelet API can run commands in every pod on the node. With anonymous access or AlwaysAllow, anyone who can reach port 10250 controls the node's workloads; the read-only port 10255 leaks pod and environment details.
/var/lib/kubelet/config.yaml: Kubelet allows unauthenticated or unauthorised access
authentication.anonymous.enabled: true
authorization.mode: AlwaysAllow
readOnlyPort: 10255
- Fix
- Set authentication.anonymous.enabled: false, authorization.mode: Webhook and readOnlyPort: 0 in the kubelet configuration, then restart the kubelet.
- Verify
grep -A2 -E 'anonymous|authorization|readOnlyPort' /var/lib/kubelet/config.yaml
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-306, CWE-862, OWASP A01:2021, A07:2021, NIST 800-53 AC-3, IA-2
- References
- Kubernetes documentation, Kubelet authentication and authorization
Kubernetes documentation, Securing a cluster
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/containers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALSSH Permits Empty Passwords
HOST-SSH-003
Checks whether SSH lets accounts with an empty password log in.
Why it matters. Any account without a password becomes an open door to anyone on the network.
sshd: Empty passwords are accepted
permitemptypasswords yes
- Fix
- Set PermitEmptyPasswords no in /etc/ssh/sshd_config, reload sshd, and give every account a password or lock it (passwd -l <user>).
- Verify
sshd -T | grep -i permitemptypasswords should print 'no'.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-258, NIST 800-53 IA-5(1)
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/ssh_empty_passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALRedis Authentication and Network Binding
NET-DB-002
Redis lacks protected mode, authentication, or a loopback-only bind.
Why it matters. An unauthenticated network-reachable Redis instance can disclose or alter data and may permit dangerous administrative operations.
/etc/redis/redis.conf: Redis lacks protected mode, authentication, or a loopback-only bind.
/etc/redis/redis.conf: protected-mode = no
/etc/redis/redis.conf: bind = 0.0.0.0
- Fix
- Set protected-mode yes, configure ACL users with strong secrets, bind to 127.0.0.1 and ::1, and restrict remote access with a firewall.
- Verify
Review redis-server --test-memory only for health, then inspect the effective configuration and listening socket after reload.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1188, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- Redis Security
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/data_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALMongoDB Authorization and Network Binding
NET-DB-003
MongoDB authorization is disabled or it binds beyond loopback.
Why it matters. MongoDB without authorization or with broad exposure can permit unauthenticated database access.
/etc/mongod.conf: MongoDB authorization is disabled or it binds beyond loopback.
/etc/mongod.conf: authorization = disabled
/etc/mongod.conf: bindip = 0.0.0.0
- Fix
- Set security.authorization to enabled and net.bindIp to 127.0.0.1, then allow only approved clients through a controlled network path.
- Verify
Run mongod --config <file> --configExpand none in a maintenance workflow and confirm port 27017 is loopback-only.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1188, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- MongoDB Security Checklist
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/data_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALPostgreSQL Trust and Broad Client Access
NET-DB-004
PostgreSQL accepts trust authentication or unrestricted client networks.
Why it matters. Trust authentication and all-address client rules can allow database access without a password from untrusted networks.
/etc/postgresql/16/main/postgresql.conf: PostgreSQL accepts trust authentication or unrestricted client networks.
/etc/postgresql/16/main/postgresql.conf: broad or trust rule detected
/etc/postgresql/16/main/pg_hba.conf: broad or trust rule detected
- Fix
- Bind PostgreSQL to required interfaces only and replace trust or unrestricted pg_hba.conf rules with narrow CIDRs and scram-sha-256. Caution: users whose passwords are stored as md5 cannot log in with scram-sha-256 until their password is set again with password_encryption = scram-sha-256, so reset them first and reload, not restart, to test.
- Verify
Run pg_ctl reload through normal operations, then use pg_hba_file_rules and ss -tlnp to verify the effective rules.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1188, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- PostgreSQL Client Authentication
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/data_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALElasticsearch Security and Network Binding
NET-DB-007
Elasticsearch security is disabled or network.host is broadly reachable.
Why it matters. An exposed Elasticsearch cluster without authentication can disclose, alter, or delete indexed data.
/etc/elasticsearch/elasticsearch.yml: Elasticsearch security is disabled or network.host is broadly reachable.
/etc/elasticsearch/elasticsearch.yml: xpack.security.enabled = false
/etc/elasticsearch/elasticsearch.yml: network.host = 0.0.0.0
- Fix
- Set xpack.security.enabled true, bind network.host to loopback or an approved private interface, require TLS, and filter access.
- Verify
Use the local node configuration API with approved credentials and confirm port 9200 is not broadly exposed.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1188, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- Elastic Security Minimal Setup
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/data_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALControl Plane or Remote Desktop Ports Network-Reachable
NET-SVC-002
Docker API, Kubernetes API, kubelet, etcd, VNC or RDP listen on network-reachable addresses.
Why it matters. These services hand out administrative control of the host or the cluster. The unauthenticated Docker API and etcd give code execution or every cluster secret to whoever connects; RDP and VNC are the most attacked remote access services.
sockets: Control plane or remote desktop ports are network-reachable
tcp 0.0.0.0:2375 Docker API without TLS, bound to all interfaces
tcp 0.0.0.0:6443 Kubernetes API, bound to all interfaces
- Fix
- Bind control planes to loopback or a dedicated management address, require mutual TLS or strong authentication, and filter access to approved source networks or a VPN.
- Verify
Review ss -tulpn and the host firewall from a trusted administrative session.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Network Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1327, CWE-923, OWASP A05:2021, NIST 800-53 AC-17, CM-7, SC-7
- References
- Docker Protect the Daemon Socket
Kubernetes Ports and Protocols
IANA Service Name and Transport Protocol Port Number Registry
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALEnvironment or Secrets File Exposed
WEB-EXP-002
Checks whether .env and similar configuration files can be downloaded.
Why it matters. Framework .env files hold database passwords, mail credentials, encryption keys and API tokens. Downloading one usually means full compromise of the application and its data.
shop.example.test: Exposed: /.env (HTTP 200)
/.env (HTTP 200)
- Fix
- Move secrets out of the web root, block dot-files at the web server, delete backup copies, then rotate every secret in the file because it must be treated as leaked.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/.env should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Information Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-538, CWE-260, OWASP A05:2021, ASVS 14.3.2, 2.10.4, NIST 800-53 CM-7, SC-28
- References
- OWASP Secrets Management Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALNode.js Debugger (Inspector) Enabled in a Service
WEB-NODE-002
Checks whether a Node.js service is started with --inspect, which opens the V8 debugger.
Why it matters. The inspector has no authentication: anyone who can connect to it can run any JavaScript inside the application, as the service's user. Bound to 0.0.0.0 that is remote code execution; even on 127.0.0.1 any local user or server-side request forgery bug can reach it.
systemd units: Node.js services start the debugger
shop-api.service: starts the inspector on a network address (--inspect=0.0.0.0:9229 )
- Fix
- Remove --inspect from the service and from NODE_OPTIONS, run systemctl daemon-reload and restart. Debug on a development machine, or temporarily over an SSH tunnel to 127.0.0.1:9229.
- Verify
systemctl show -p ExecStart,Environment <unit> | grep -c inspect prints 0, and nothing listens on 9229.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-306, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-7, CM-6
- References
- Node.js documentation, Debugging guide (security implications)
OWASP Node.js Security Cheat Sheet
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALPython Interactive Debugger Enabled in a Service
WEB-PY-004
Checks whether a service runs Flask or Werkzeug with the interactive debugger enabled.
Why it matters. The Werkzeug debugger lets a visitor run Python code from an error page. Its PIN has been bypassed and brute-forced in practice, and with WERKZEUG_DEBUG_PIN=off there is no protection at all: this is remote code execution.
systemd units: Services enable the Python interactive debugger
shop-reports.service: enables the debugger (FLASK_DEBUG=1)
- Fix
- Remove the debug switches, run the application under a production WSGI server (Gunicorn, uWSGI or mod_wsgi) behind nginx or Apache, run systemctl daemon-reload and restart the service.
- Verify
systemctl show -p ExecStart,Environment <unit> shows no debug switches.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-94, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-7, CM-6
- References
- Werkzeug documentation, Debugging Applications
Flask documentation, Debug mode
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALTomcat Administrative Users With Default or Weak Passwords
WEB-TOM-002
Checks tomcat-users.xml for manager or admin accounts with well-known default passwords, passwords equal to the user name, or short passwords.
Why it matters. Default Tomcat credentials (tomcat/tomcat, admin/admin, tomcat/s3cret) are in every attack tool's word list. A Manager account with such a password lets anyone deploy code on the server.
/etc/tomcat9: Tomcat administrative users have weak credentials
user "tomcat" (roles manager-gui,admin-gui) uses a documented default password
- Fix
- Remove accounts you do not need. Give the remaining ones long random passwords and store them as digests: configure a CredentialHandler (for example SecretKeyCredentialHandler with PBKDF2) in the Realm and generate hashes with bin/digest.sh. Restart Tomcat.
- Verify
Re-run this check; no administrative user should be listed.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1392, CWE-521, CWE-256, OWASP A07:2021, ASVS 2.1.1, 2.5.4, NIST 800-53 IA-5
- References
- Apache Tomcat 10.1, Security Considerations
Apache Tomcat 10.1, Realm Configuration How-To (digested passwords)
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/tomcat.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
CRITICALTomcat AJP Connector Unprotected (Ghostcat)
WEB-TOM-004
Checks for an active AJP connector that has no shared secret and is not bound to loopback, or that disables the secret requirement.
Why it matters. AJP is a trusted, unauthenticated protocol between a web server and Tomcat. CVE-2020-1938 (Ghostcat) showed that a reachable AJP port lets an attacker read any file in the web applications and, where uploads exist, execute code. It is listed in the CISA Known Exploited Vulnerabilities catalogue.
/etc/tomcat9: AJP connector is reachable without protection
AJP connector on port 8009 is not bound to loopback and does not require a secret
- Fix
- If you do not use AJP (most sites proxy over HTTP), delete or comment out the AJP <Connector>. Otherwise set address="127.0.0.1", a long random secret="..." with secretRequired="true", and the same secret in the proxy (mod_proxy_ajp: ProxyPass ... secret=...). Upgrade Tomcat to a supported release.
- Verify
grep -i ajp <conf>/server.xml and ss -tlnp | grep 8009 shows nothing or 127.0.0.1 only.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1327, OWASP A05:2021, A06:2021, NIST 800-53 SC-7, AC-3, CM-7
- References
- Apache Tomcat 10.1, Security Considerations
Apache Tomcat 10.1 Configuration Reference, The AJP Connector
NVD, CVE-2020-1938
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/tomcat.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHCron Jobs Run Programs Other Users Can Modify
HOST-CRON-001
Resolves the programs and scripts that system and root cron jobs run and checks whether any is world-writable or sits in a world-writable folder.
Why it matters. HOST-FS-005 protects the cron tables themselves, but a root job that runs /usr/local/bin/backup.sh is only as trustworthy as that file. If any user can edit the script, or replace it in a writable folder, their code runs as root at the next scheduled minute.
cron: Cron jobs run programs that other users can modify
0777 /usr/local/bin/backup.sh is world-writable
- Fix
- chmod o-w <program> and its folder; move scripts out of /tmp or user-writable folders into /usr/local/sbin owned by root; have cron run only files owned by root (chown root:root).
- Verify
for p in $(awk '/^[^#]/ && NF>6 {print $7}' /etc/crontab /etc/cron.d/*); do stat -c '%a %U %n' $p; done
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-426, NIST 800-53 AC-3, AC-6, CM-5
- References
- crontab(5), Linux man-pages
MITRE ATT&CK T1053.003, Scheduled Task/Job: Cron
- Learn
- P20: Secrets, Cron and Account Hygiene (offline:
openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHWorld-Writable Directory in Cron's PATH
HOST-CRON-002
Checks the PATH that system cron jobs search for commands for world-writable or relative entries.
Why it matters. A cron job that calls backup-db rather than /usr/local/sbin/backup-db runs whichever file of that name PATH finds first. If a folder on that PATH is world-writable, or the PATH contains an empty or relative entry, any user can plant a program that root runs on schedule (PATH interception).
cron PATH: Cron's PATH can be hijacked
/etc/crontab: 0777 /opt/scripts is world-writable without the sticky bit
- Fix
- Remove the writable folder from PATH in /etc/crontab (or chmod o-w it), delete relative entries, and call programs in cron jobs by absolute path.
- Verify
grep ^PATH /etc/crontab /etc/cron.d/* ; for d in $(grep ^PATH /etc/crontab | cut -d= -f2 | tr : ' '); do stat -c '%a %n' $d; done
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-426, CWE-427, NIST 800-53 CM-6, AC-6, CM-7
- References
- MITRE ATT&CK T1574.007, Hijack Execution Flow: Path Interception by PATH Environment Variable
crontab(5), Linux man-pages
- Learn
- P20: Secrets, Cron and Account Hygiene (offline:
openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHPrivileged or Host-Namespace Containers
HOST-CTR-003
Looks for containers running privileged, sharing the host's PID, network or IPC namespace, or with dangerous added capabilities.
Why it matters. A privileged container, or one with CAP_SYS_ADMIN or host namespaces, has almost no isolation: a compromise of the application inside is a compromise of the host.
containers: Containers with weak isolation
3f2a9c1d8e7b: privileged, pid=host, network=host, cap-add SYS_ADMIN
- Fix
- Recreate each container without --privileged, --pid=host, --net=host and --ipc=host; drop all capabilities and add back only the specific ones needed (--cap-drop=ALL --cap-add=...).
- Verify
docker inspect --format '{{.Name}} {{.HostConfig.Privileged}} {{.HostConfig.PidMode}} {{.HostConfig.NetworkMode}} {{.HostConfig.CapAdd}}' $(docker ps -aq)
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-653, NIST 800-53 AC-6, SC-39
- References
- NIST SP 800-190, Application Container Security Guide
OWASP Docker Security Cheat Sheet
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/containers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHContainers Mount the Docker Socket or Host Root
HOST-CTR-004
Looks for containers that bind-mount the Docker socket, the host root filesystem or sensitive host paths.
Why it matters. A container with /var/run/docker.sock can control Docker and therefore the host. Mounting / or /etc gives direct write access to host configuration.
containers: Containers mount the Docker socket or sensitive host paths
3f2a9c1d8e7b: /var/run/docker.sock:/var/run/docker.sock
3f2a9c1d8e7b: /:/host
- Fix
- Remove these mounts. If a tool genuinely needs the Docker API, use a restricted socket proxy that allows only the required read-only calls.
- Verify
docker inspect --format '{{.Name}} {{.HostConfig.Binds}}' $(docker ps -aq)
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-732, NIST 800-53 AC-6, SC-39
- References
- Docker documentation, Protect the Docker daemon socket
NIST SP 800-190, Application Container Security Guide
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/containers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDocker Socket Accessible to Non-Administrators
HOST-CTR-008
Checks the Docker socket's permissions and who belongs to the docker group.
Why it matters. Whoever can write to /var/run/docker.sock is root: one command starts a privileged container with the host's disk mounted. Members of the docker group have that power without sudo, logging or a password prompt, so the group should be empty or hold only administrators.
/var/run/docker.sock: Docker socket is reachable by non-administrators
/var/run/docker.sock mode 0666 is accessible to all users
docker group members (root-equivalent): deploy
- Fix
- chmod 660 /var/run/docker.sock && chown root:docker /var/run/docker.sock (the daemon recreates it with these defaults). Remove users from the docker group (gpasswd -d <user> docker) and give administrators sudo docker, or move to rootless Docker.
- Verify
stat -c '%a %U:%G %n' /var/run/docker.sock ; getent group docker
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-250, NIST 800-53 AC-3, AC-6, CM-6
- References
- Docker documentation, Protect the Docker daemon socket
OWASP Docker Security Cheat Sheet
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSeccomp or AppArmor Disabled for Containers
HOST-CTR-011
Looks for the daemon or individual containers turning off the default seccomp profile, AppArmor or SELinux labelling.
Why it matters. Docker's default seccomp profile blocks around 40 dangerous system calls and AppArmor or SELinux confines what a container's root can touch on the host. Running unconfined removes the main barriers between a compromised container and the kernel.
containers: Containers run without seccomp, AppArmor or SELinux confinement
daemon.json seccomp-profile is unconfined
3f2a9c1d8e7b: seccomp=unconfined, apparmor=unconfined
- Fix
- Remove --security-opt seccomp=unconfined and apparmor=unconfined from the container definitions and recreate them; if an application needs one extra system call, write a custom seccomp profile that adds only that call. Delete seccomp-profile from daemon.json.
- Verify
docker inspect --format '{{.Name}} {{.HostConfig.SecurityOpt}}' $(docker ps -aq)
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-653, CWE-250, NIST 800-53 AC-6, SC-39, CM-7
- References
- Docker documentation, Seccomp security profiles
Docker documentation, AppArmor security profiles
NIST SP 800-190, Application Container Security Guide
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHcontainerd Remote API or Podman Unconfined Defaults
HOST-CTR-014
Checks the containerd and Podman configuration files for a TCP API without TLS and for unconfined seccomp or disabled labelling defaults.
Why it matters. containerd's gRPC API is root on the host, like the Docker API; a tcp_address without TLS exposes it to the network. Podman's containers.conf sets the defaults every container inherits: an unconfined seccomp profile or disabled SELinux labelling removes the isolation for all of them.
/etc/containerd/config.toml: containerd listens on TCP without TLS
grpc tcp_address = 0.0.0.0:8888
- Fix
- containerd: remove tcp_address or set tcp_tls_cert and tcp_tls_key, then restart containerd. Podman: delete seccomp_profile = "unconfined", set label = true and apparmor_profile = "container-default" in containers.conf.
- Verify
grep -E 'tcp_address|tcp_tls' /etc/containerd/config.toml ; grep -E 'seccomp_profile|^label|apparmor_profile' /etc/containers/containers.conf
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-306, CWE-1188, NIST 800-53 AC-3, SC-8, CM-6
- References
- containerd documentation, Operations (configuration)
containers.conf(5), Podman configuration
NIST SP 800-190, Application Container Security Guide
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHInstalled OS Packages With Known Vulnerabilities
HOST-CVE-001
Checks installed packages against an offline vulnerability snapshot.
Why it matters. Known vulnerable package versions can expose a server to documented attacks.
sudo: sudo 1.8.21p2-3ubuntu1.4: LAB-CVE-2021-3156 (CVE-2021-3156), fixed in 1.8.21p2-3ubuntu1.5, severity high
matcher: range
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
policykit-1: policykit-1 0.105-20ubuntu0.18.04.5: LAB-CVE-2021-4034 (CVE-2021-4034), fixed in 0.105-20ubuntu0.18.04.6, severity high
matcher: range
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
- Fix
- Install the vendor security update. For a source build, run 'make vulndb' to embed a snapshot generated from OSV and CISA KEV, then rebuild.
- Verify
Re-run OpenVAPT after patching and confirm the finding is absent.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, RA-5
- References
- OSV vulnerability database
NVD
CISA KEV
- Learn
- P10: Vulnerability Management: CVE, OSV and Known Exploited Vulnerabilities (offline:
openvapt learn P10)
- Source
internal/checks/host/cve.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHUsers With Root-Equivalent Docker Access
HOST-DKR-001
Checks whether non-root users can control Docker, which is equivalent to root access.
Why it matters. Members of the docker group, or anyone who can write to the Docker socket, can start a container that mounts the host filesystem and become root.
docker: Non-root users can control Docker (root equivalent)
docker group members: deploy
/var/run/docker.sock is world-writable (0666)
- Fix
- Remove users who do not need it from the docker group (gpasswd -d <user> docker); consider rootless Docker or Podman; keep docker.sock at 660 root:docker.
- Verify
getent group docker ; stat -c '%a %U:%G' /var/run/docker.sock
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-266, NIST 800-53 AC-6
- References
- Docker documentation, Docker daemon attack surface
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P9: Containers and Kubernetes (offline: openvapt learn P9)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSensitive Account Files Have Unsafe Permissions
HOST-FS-001
Checks that /etc/shadow and /etc/gshadow are not readable by others, and /etc/passwd and /etc/group are not writable by others.
Why it matters. Readable shadow files let any local user (or a compromised web app) copy password hashes and crack them offline. Writable passwd/group files let them create a root account.
/etc/shadow: /etc/shadow is readable or writable by others
mode 0644
/etc/passwd: /etc/passwd is writable by group or others
mode 0666
- Fix
- chown root:root /etc/passwd /etc/group && chmod 644 /etc/passwd /etc/group ; chown root:shadow /etc/shadow /etc/gshadow && chmod 640 /etc/shadow /etc/gshadow (use root:root and 000 on RHEL-family systems).
- Verify
stat -c '%a %U:%G %n' /etc/passwd /etc/group /etc/shadow /etc/gshadow
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- shadow(5), Linux man-pages
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/files.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHTemporary Directory Missing the Sticky Bit
HOST-FS-002
Checks that world-writable temp directories have the sticky bit set.
Why it matters. Without the sticky bit any user can delete or replace other users' files in /tmp, enabling symlink attacks against root-run scripts.
/tmp: /tmp is world-writable without the sticky bit
mode 0777
- Fix
- chmod 1777 /tmp /var/tmp
- Verify
stat -c '%a %n' /tmp /var/tmp should print 1777 for both.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-377, CWE-732, NIST 800-53 AC-3
- References
- chmod(1), Linux man-pages (restricted deletion flag)
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/files.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHWorld-Writable Files in System Configuration
HOST-FS-003
Looks for files under /etc and in cron directories that any user can modify.
Why it matters. A world-writable config or cron file lets any local user change how a root-owned service behaves, often leading straight to root.
/etc: World-writable files found
0666 /etc/passwd
0666 /etc/app/db.conf
0666 /etc/crontab
0666 /etc/ssh/sshd_config
0666 /etc/systemd/system/shop-api.service
- Fix
- For each listed file or directory: chmod o-w <path>. Then find out how it became writable (a deployment script or a careless chmod 777).
- Verify
find /etc -xdev \( -type f -perm -0002 \) -o \( -type d -perm -0002 ! -perm -1000 \) should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, CM-6
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/files.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHUnexpected SUID or SGID Programs
HOST-FS-004
Looks for set-user-ID or set-group-ID programs in places where packages do not normally install them.
Why it matters. A SUID program runs with its owner's rights (usually root). One placed in /tmp, /home, /var/www or /opt is a common persistence and privilege-escalation trick.
filesystem: SUID/SGID programs outside standard system paths
4755 /home/deploy/.cache/sh
- Fix
- Confirm whether each program is needed. Remove the bit with chmod u-s,g-s <file>, or delete the file if you did not put it there and investigate how it arrived.
- Verify
find /tmp /home /var/www /opt /usr/local -xdev -perm /6000 -type f should print nothing unexpected.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 CM-7, AC-6
- References
- MITRE ATT&CK T1548.001, Setuid and Setgid
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/files.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHCron Files Writable by Non-Root Users
HOST-FS-005
Checks that system cron files and directories are owned by root and not writable by others.
Why it matters. Cron runs these jobs as root. Anyone who can edit them can run any command as root at the next scheduled minute.
cron: Cron paths can be modified by non-root users
0666 uid=0 /etc/crontab
- Fix
- chown root:root <path> && chmod go-w <path> for each listed path (600 for /etc/crontab is a common hardening choice).
- Verify
stat -c '%a %U %n' /etc/crontab /etc/cron.*
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, CM-6
- References
- crontab(5), Linux man-pages
MITRE ATT&CK T1053.003, Cron
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/files.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHPrivate TLS Keys Readable by Others
HOST-FS-007
Checks that TLS private keys under the standard key directories are not readable by other users.
Why it matters. A stolen private key lets an attacker impersonate your websites and, with older key exchange, decrypt recorded traffic.
/etc/ssl/private/*: 1 file(s) are readable or writable by others
0644 /etc/ssl/private/shop.key
- Fix
- chown root:root <key> && chmod 600 <key> (or 640 with a dedicated group the web server runs in). Rotate any key that was exposed.
- Verify
stat -c '%a %U:%G %n' /etc/ssl/private/* /etc/pki/tls/private/* /etc/letsencrypt/archive/*/privkey*.pem
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- OWASP Key Management Cheat Sheet
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHAccount Database Files or Their Backups Not Owned and Locked by Root
HOST-FS-022
Checks the owner and permissions of /etc/passwd, /etc/group, /etc/shadow, /etc/gshadow and their dash-suffixed backup copies.
Why it matters. The tools that edit accounts leave a backup copy (passwd-, shadow-) next to the live file. A readable shadow- backup leaks the same password hashes as shadow itself, and a file not owned by root can be rewritten by whoever owns it. HOST-FS-001 checks the mode of the live files; this check adds ownership and the backups.
/etc/passwd: 3 account file(s) have an unsafe owner or mode
0666 /etc/passwd (writable by group or others)
0644 /etc/shadow (accessible by others)
0644 /etc/shadow- (accessible by others)
- Fix
- chown root:root /etc/passwd /etc/passwd- /etc/group /etc/group- && chmod 644 /etc/passwd /etc/group && chmod 600 /etc/passwd- /etc/group- ; chown root:shadow /etc/shadow /etc/shadow- /etc/gshadow /etc/gshadow- && chmod 640 /etc/shadow /etc/gshadow && chmod 600 /etc/shadow- /etc/gshadow- (use root:root and mode 000 on RHEL family systems).
- Verify
stat -c '%a %U:%G %n' /etc/passwd* /etc/group* /etc/shadow* /etc/gshadow*
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-522, NIST 800-53 AC-3, AC-6, IA-5
- References
- shadow(5), Linux man-pages
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHKubernetes Data Directory Accessible to Others
HOST-K8S-002
Checks that the etcd data directory is accessible only by its owner.
Why it matters. etcd stores every Kubernetes object, including Secrets, usually unencrypted at rest. Read access to its data directory exposes all cluster credentials.
/var/lib/etcd: etcd data directory is accessible by group or others
mode 0755
- Fix
- chmod 700 /var/lib/etcd && chown etcd:etcd /var/lib/etcd (or root:root for kubeadm static pods). Enable encryption at rest for Secrets.
- Verify
stat -c '%a %U:%G %n' /var/lib/etcd
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, SC-28
- References
- Kubernetes documentation, Operating etcd clusters for Kubernetes
Kubernetes documentation, Securing a cluster
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/containers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHKubernetes Credential Files Readable by Others
HOST-K8S-003
Checks that kubeconfig files and Kubernetes PKI private keys are not readable by other users.
Why it matters. admin.conf and the cluster CA key grant full control of the cluster; any local user who can read them becomes a cluster administrator.
/etc/kubernetes/admin.conf: 1 file(s) are readable or writable by group or others
0644 /etc/kubernetes/admin.conf
- Fix
- chmod 600 /etc/kubernetes/*.conf /etc/kubernetes/pki/*.key /etc/kubernetes/pki/etcd/*.key && chown root:root on each.
- Verify
stat -c '%a %n' /etc/kubernetes/*.conf /etc/kubernetes/pki/*.key
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- Kubernetes documentation, Securing a cluster
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHOperating System Past End of Security Support
HOST-OS-001
Checks whether the Linux distribution release still receives free security updates.
Why it matters. Once a release reaches end of life, newly discovered vulnerabilities are never fixed. Every later CVE in the kernel, OpenSSL or the web server stays open forever.
Ubuntu 18.04.6 LTS: Security support ended on 2023-05-31
- Fix
- Plan an upgrade to a supported release (for example do-release-upgrade on Ubuntu, or a fresh install and migration). Paid extended support (Ubuntu Pro, RHEL ELS) is an alternative while migrating.
- Verify
cat /etc/os-release and compare with the vendor lifecycle page.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- High
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SA-22, SI-2
- References
- Ubuntu release cycle
Debian releases and LTS
Red Hat Enterprise Linux life cycle
endoflife.date (community-maintained lifecycle data)
- Learn
- F3: Vulnerabilities, CVE, CWE and CVSS (offline:
openvapt learn F3)
P1: Linux Server Hardening (offline: openvapt learn P1)
- Source
internal/checks/host/os_patch.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSecurity Updates Waiting to Be Installed
HOST-PKG-001
Checks the package manager for published security updates that are not installed yet.
Why it matters. Most real-world compromises use vulnerabilities for which a fix was already available. Pending security updates are known, public weaknesses.
apt: 2 security updates pending
openssl
sudo
- Fix
- Debian/Ubuntu: apt-get update && apt-get upgrade . RHEL family: dnf upgrade --security . Consider unattended-upgrades or dnf-automatic for security patches.
- Verify
Re-run openvapt; this check should pass.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, RA-5
- References
- NIST SP 800-40 Rev. 4, Guide to Enterprise Patch Management Planning
Debian, UnattendedUpgrades
- Learn
- F3: Vulnerabilities, CVE, CWE and CVSS (offline:
openvapt learn F3)
P1: Linux Server Hardening (offline: openvapt learn P1)
- Source
internal/checks/host/os_patch.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHRepository Signature Checks Disabled
HOST-PKG-002
Checks that the package manager verifies repository signatures, so a tampered mirror or intercepted download cannot install code as root.
Why it matters. Package installation runs as root. apt and dnf verify a signature over the repository index before trusting any package in it; an entry marked trusted=yes, AllowUnauthenticated or gpgcheck=0 switches that off, and a mirror operator or anyone on the network path can then deliver a modified package at the next update.
package repositories: Repository signature verification is disabled
/etc/apt/sources.list.d/lab-ppa.list: ppa.launchpadcontent.net marked trusted=yes (signature check off)
- Fix
- Remove trusted=yes (or Trusted: yes) from the listed source, install the repository's signing key under /etc/apt/keyrings and reference it with signed-by=; remove AllowUnauthenticated and AllowInsecureRepositories settings. On dnf and yum set gpgcheck=1 (and repo_gpgcheck=1 where supported) in each listed repository and import its key with rpm --import.
- Verify
grep -r 'trusted=yes' /etc/apt/ ; grep -r 'gpgcheck=0' /etc/yum.repos.d/ /etc/dnf/dnf.conf 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- Low
- Confidence
- High
- Standards
- CWE-494, CWE-347, OWASP A08:2021, NIST 800-53 SI-7, CM-14, SR-3, SR-11
- References
- apt-secure(8), Debian manual pages
dnf.conf(5), Ubuntu noble manual pages (gpgcheck)
NIST SP 800-40 Rev. 4, Guide to Enterprise Patch Management Planning
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/pkg_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSecrets in World-Readable Files
HOST-SEC-001
Looks inside world-readable configuration files under /etc and the web roots for private keys, cloud access keys and password assignments.
Why it matters. A password or key in a file every local account can read is available to every website, service account and compromised process on the machine. Secrets found this way are the usual first step from a small web compromise to the database, the cloud account or root.
filesystem: 3 world-readable file(s) contain secrets
/etc/app/db.conf (mode 0666): credential assignment
/etc/backup/backup-key.pem (mode 0644): private key
/var/www/shop/.env (mode 0644): AWS access key id, credential assignment
- Fix
- chmod o-r each listed file (640 with the service's group, or 600). Move secrets into root-only files, systemd credentials or a secrets manager, and rotate every key or password that was readable.
- Verify
find /etc /var/www -type f -perm -0004 -name '.env*' -o -type f -perm -0004 -name '*.key' then re-run this check.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
- Category
- Information Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-312, CWE-732, CWE-798, OWASP A02:2021, A05:2021, NIST 800-53 IA-5, SC-28, AC-3
- References
- OWASP Secrets Management Cheat Sheet
NIST SP 800-53 Rev. 5, IA-5 Authenticator Management
NIST SP 800-123, Guide to General Server Security
- Learn
- P20: Secrets, Cron and Account Hygiene (offline:
openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSSH Allows Direct Root Login
HOST-SSH-001
Checks whether the SSH daemon accepts logins as root with a password.
Why it matters. Root is the one account name every attacker knows. Allowing it over SSH turns any password guess into full control of the server, and removes the audit trail of which person used root.
sshd: Root may log in over SSH with a password
permitrootlogin yes
- Fix
- In /etc/ssh/sshd_config set: PermitRootLogin no (or prohibit-password if key-based root login is truly required). Log in as a named user and use sudo. Then run: sshd -t && systemctl reload sshd
- Verify
sshd -T | grep -i permitrootlogin should print 'permitrootlogin no'.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 AC-6(2), IA-2
- References
- OpenBSD, sshd_config(5) manual page
NIST SP 800-123, Guide to General Server Security
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
P23: Test Design for Security Checks (offline: openvapt learn P23)
A2: Remediation and Verification (offline: openvapt learn A2)
- Source
internal/checks/host/ssh_root_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSSH Host Private Keys Readable by Others
HOST-SSH-009
Checks that SSH host private keys are readable only by root.
Why it matters. Anyone who can read a host private key can impersonate the server and intercept SSH sessions from users who trust it.
/etc/ssh/ssh_host_*_key: 1 file(s) are readable or writable by others
0644 /etc/ssh/ssh_host_ed25519_key
- Fix
- chown root:root /etc/ssh/ssh_host_*_key && chmod 600 /etc/ssh/ssh_host_*_key (0640 with group ssh_keys is acceptable on RHEL family).
- Verify
stat -c '%a %U:%G %n' /etc/ssh/ssh_host_*_key
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSSH Server Configuration Writable by Non-Root Users
HOST-SSH-010
Checks that the SSH daemon configuration cannot be modified by group or other users.
Why it matters. Whoever can edit sshd_config can enable root login, add their own keys file location or weaken authentication.
/etc/ssh/sshd_config: 1 file(s) are writable by group or others
0666 /etc/ssh/sshd_config
- Fix
- chown root:root /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf && chmod 600 /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf
- Verify
stat -c '%a %U %n' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHService Unit Files Writable by Non-Root Users
HOST-SYSD-003
Checks whether any systemd service unit or drop-in file can be changed by a user other than root.
Why it matters. systemd starts services as root by default. Whoever can edit a unit file can change ExecStart= or User= and have their own program run as root at the next restart or reboot, a well-known privilege escalation and persistence technique.
systemd units: Service unit files can be changed by non-root users
/etc/systemd/system/shop-api.service mode 0666 uid 0
- Fix
- chown root:root <file> && chmod 644 <file> for each listed file, then review its contents for changes you did not make (ExecStart=, User=, ExecStartPre=) and run systemctl daemon-reload.
- Verify
stat -c '%U %a %n' /etc/systemd/system/*.service shows root and 644 (or stricter).
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, CM-5
- References
- systemd.unit(5), unit configuration
MITRE ATT&CK T1543.002, Create or Modify System Process: Systemd Service
- Learn
- P11: Service Hardening With systemd (offline:
openvapt learn P11)
- Source
internal/checks/host/systemd.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHService Programs in Writable Locations
HOST-SYSD-004
Checks whether a service starts a program from a temporary folder, or a program file that other users can replace.
Why it matters. If the program a root service starts lives in /tmp or is writable by other users, any local user (or a compromised web application) can replace it and gain root the next time the service restarts.
systemd units: Services start programs that other users can replace
shop-worker.service: starts /tmp/shop-worker from a temporary folder
- Fix
- Install the program in a root-owned location (/usr/local/bin or /opt/<app>), chown root:root and chmod 755 it, point ExecStart= at it, then systemctl daemon-reload and restart the service.
- Verify
stat -c '%U %a %n' $(systemctl show -p ExecStart --value <unit> | awk '{print $2}' | sed 's/path=//;s/;//')
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-427, NIST 800-53 AC-3, CM-5
- References
- systemd.exec(5), execution environment configuration
MITRE ATT&CK T1574.010, Hijack Execution Flow: Services File Permissions Weakness
- Learn
- P11: Service Hardening With systemd (offline:
openvapt learn P11)
- Source
internal/checks/host/systemd.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHExtra Accounts With Root Privileges (UID 0)
HOST-USR-001
Checks /etc/passwd for accounts other than root that have user id 0.
Why it matters. Any account with UID 0 is root, whatever its name. Extra UID 0 accounts are a classic backdoor and bypass sudo logging.
/etc/passwd: Accounts other than root have UID 0
toor:x:0:0
- Fix
- Investigate who created each account. Remove it (userdel <name>) or give it a normal UID (usermod -u <new-uid> <name>). Grant admin rights through sudo instead.
- Verify
awk -F: '$3==0' /etc/passwd should print only the root line.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-266, NIST 800-53 AC-2, AC-6
- References
- passwd(5), Linux man-pages
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/accounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHAccounts Without a Password
HOST-USR-002
Checks /etc/shadow for accounts whose password field is empty.
Why it matters. An empty password field means the account can log in with no password at all on any service that allows password logins. The score uses a local attack vector: any local user can switch to the account (su) without a password, while the SSH daemon refuses empty passwords unless PermitEmptyPasswords is yes. If HOST-SSH-003 also fails, the same account is open from the network and should be treated as Critical.
/etc/shadow: Accounts have an empty password
deploy
- Fix
- For each listed user either set a password (passwd <user>) or lock the account (passwd -l <user>).
- Verify
awk -F: '$2==""' /etc/shadow should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-258, CWE-521, NIST 800-53 IA-5
- References
- shadow(5), Linux man-pages
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/accounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSudo Rules Without Password (NOPASSWD)
HOST-USR-003
Checks sudoers files for rules that grant root without asking for a password.
Why it matters. NOPASSWD means anyone who takes over that user (a stolen SSH key, a hijacked session, a web shell running as that user) becomes root instantly.
/etc/sudoers: Sudo rules grant root without a password
/etc/sudoers: deploy ALL=(ALL) NOPASSWD: ALL
- Fix
- Edit with visudo and remove NOPASSWD, or restrict it to one specific, harmless command for automation accounts.
- Verify
grep -r NOPASSWD /etc/sudoers /etc/sudoers.d should print nothing, or only narrowly scoped commands.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, NIST 800-53 AC-6, IA-11
- References
- sudoers(5) manual
- Learn
- F1: Security Basics (offline:
openvapt learn F1)
P7: Identity, Passwords and Privilege (offline: openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/accounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHInsecure Trust Files in Home Directories
HOST-USR-007
Looks for .rhosts, .shosts and .netrc files in user home directories.
Why it matters. .rhosts and .shosts grant password-less trust to other hosts. .netrc files usually hold plain-text passwords for FTP or other services.
home directories: Insecure trust or credential files found
/home/deploy/.netrc
- Fix
- Delete .rhosts and .shosts files. Replace .netrc credentials with a secret manager or key-based authentication, then delete the file and rotate the passwords it contained.
- Verify
Re-run this check; no files should be listed.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-256, CWE-290, NIST 800-53 IA-5, CM-6
- References
- MITRE ATT&CK T1552.001, Unsecured Credentials: Credentials In Files
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHAI Model Server or Dashboard Reachable From the Network
NET-AI-001
Checks whether a self-hosted AI model server, AI web interface, AI cluster dashboard or vector database listens on a network-reachable address.
Why it matters. Many self-hosted AI tools have no login enabled by default. Reached from the network, anyone can use the models and the computing power, read stored documents and embeddings, pull or delete models, and on some dashboards submit jobs that run code.
sockets: AI services are network-reachable
tcp6 [::]:11434 Ollama model API, bound to all interfaces
a web server listens on port 80 or 443 on this machine: bind the application to 127.0.0.1 and publish it through that proxy
- Fix
- Bind each service to 127.0.0.1 (Ollama: OLLAMA_HOST=127.0.0.1:11434 in its service environment; Ray: --dashboard-host=127.0.0.1; Gradio: server_name="127.0.0.1"), and if others need it, publish it only through a reverse proxy with authentication and TLS.
- Verify
ss -tlnp shows these ports on 127.0.0.1 or ::1 only.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:L
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1327, OWASP A05:2021, A07:2021, NIST 800-53 SC-7, CM-7, AC-3
- References
- Ollama FAQ, How do I configure Ollama server?
Ray documentation, Security
OWASP Top 10 for Large Language Model Applications
- Learn
- P24: Securing Self-Hosted AI Services (offline:
openvapt learn P24)
- Source
internal/checks/network/ai_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHJupyter Configuration Weakens Authentication
NET-AI-002
Checks whether a Jupyter configuration blanks the login token without setting a password, or turns off cross-site request protection.
Why it matters. Jupyter runs any code typed into it with the rights of the account that started it. With the token blanked and no password, anyone who can reach the port, or any local user, gets that account. With XSRF checks off, a web page a user visits can send it commands.
/etc/jupyter/jupyter_server_config.py: Jupyter configuration weakens authentication or request forgery protection
token is an empty string and no login password is set, so anyone who reaches the server can run code
disable_check_xsrf = True: other websites can send requests to the server through a visitor's browser
- Fix
- Remove the empty token line so Jupyter generates a random token, or set a password with jupyter server password . Remove disable_check_xsrf = True. Bind to 127.0.0.1 and reach it through an SSH tunnel.
- Verify
grep -nE 'token|password|disable_check_xsrf' <config file> shows no empty token and no disabled XSRF check, and the server log prints a URL with a token at start-up.
- CVSS v3.1
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-352, OWASP A07:2021, A05:2021, NIST 800-53 IA-2, AC-3
- References
- Jupyter Server documentation, Security in the Jupyter Server
- Learn
- P24: Securing Self-Hosted AI Services (offline:
openvapt learn P24)
- Source
internal/checks/network/ai_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDebugger or Application Control Ports Exposed
NET-APP-001
Checks whether the Node.js inspector, Tomcat AJP or shutdown port, PHP-FPM FastCGI or Jupyter listen on network-reachable addresses.
Why it matters. These ports are not web pages: the Node.js inspector and Jupyter run code for whoever connects, Tomcat AJP has been abused for file read and code execution (Ghostcat), the shutdown port stops the server, and PHP-FPM executes scripts handed to it. None of them is designed to face a network.
sockets: Debugger or application control ports are network-reachable
tcp 0.0.0.0:8009 Tomcat AJP connector, bound to all interfaces
tcp 0.0.0.0:9229 Node.js inspector (debugger), bound to all interfaces
a web server listens on port 80 or 443 on this machine: bind the application to 127.0.0.1 and publish it through that proxy
- Fix
- Bind each to 127.0.0.1 or a Unix socket (node --inspect=127.0.0.1:9229; Tomcat Connector address="127.0.0.1" or remove the AJP connector; PHP-FPM listen = /run/php/php-fpm.sock; jupyter --ip=127.0.0.1) and never expose a debugger.
- Verify
ss -tlnp shows these ports on 127.0.0.1 or ::1 only.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:L
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-1327, OWASP A05:2021, NIST 800-53 SC-7, CM-7
- References
- Node.js, Inspector security implications
Apache Tomcat 9, AJP Connector
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/network/firewall_exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDatabase or Cache Service Exposed to the Network
NET-DB-001
Checks whether databases, caches, search engines or the Docker API listen on a network-reachable address.
Why it matters. Exposed databases and caches (Redis, MongoDB, Elasticsearch, Memcached) are among the most common causes of mass data breaches and ransom wipes, often because they ship without authentication.
sockets: Data services listen on network-reachable addresses
tcp 0.0.0.0:3306 MySQL/MariaDB
tcp 0.0.0.0:6379 Redis
- Fix
- Bind the service to 127.0.0.1 (MySQL: bind-address = 127.0.0.1; Redis: bind 127.0.0.1 ::1 and protected-mode yes; MongoDB: net.bindIp: 127.0.0.1) and restart it. Caution: confirm first that no application on another machine connects to it, or that application loses its database. If remote access is needed, allow only specific source IPs in the firewall and require TLS and authentication.
- Verify
ss -tlnp | grep -E ':(3306|5432|6379|27017|9200|11211)' should show only 127.0.0.1 or ::1.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1327, CWE-306, OWASP A05:2021, NIST 800-53 SC-7, CM-7
- References
- OWASP Database Security Cheat Sheet
Redis security
- Learn
- F1: Security Basics (offline:
openvapt learn F1)
P3: Network Exposure and Firewalls (offline: openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/listeners.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHMySQL or MariaDB Unsafe Network Options
NET-DB-005
MySQL or MariaDB enables local file loading, skips grants, or listens broadly with networking enabled.
Why it matters. These options can bypass authorization, expand file access, or expose the database to untrusted networks.
/etc/mysql/mysql.conf.d/mysqld.cnf: MySQL or MariaDB enables local file loading, skips grants, or listens broadly with networking enabled.
/etc/mysql/mysql.conf.d/mysqld.cnf: local_infile = ON
/etc/mysql/mysql.conf.d/mysqld.cnf: skip-grant-tables =
/etc/mysql/mysql.conf.d/mysqld.cnf: skip-networking = OFF
/etc/mysql/mysql.conf.d/mysqld.cnf: bind-address = 0.0.0.0
- Fix
- Disable local_infile and skip-grant-tables. Bind to 127.0.0.1 or enable skip-networking when TCP access is unnecessary.
- Verify
Inspect SHOW VARIABLES through an approved administrator session and confirm the listening address locally.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1188, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- MySQL Server Security Guidelines
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/data_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHMemcached UDP or Broad Listen Address
NET-DB-006
Memcached enables UDP or listens on a non-loopback address.
Why it matters. Unauthenticated Memcached exposure can disclose cached data and UDP mode has been abused for amplification attacks.
/etc/memcached.conf: Memcached enables UDP or listens on a non-loopback address.
/etc/memcached.conf: -l 0.0.0.0
/etc/memcached.conf: -U 11211
- Fix
- Set UDP_PORT=0 or -U 0 and bind with -l 127.0.0.1. Use a firewall for any explicitly required clients.
- Verify
Confirm ss -ltnup shows Memcached only on loopback and no UDP port 11211.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-406, CWE-1188, OWASP A05:2021, NIST 800-53 SC-5, CM-6, SC-7
- References
- memcached Configuration
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/data_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHUnsafe NFS Export Options
NET-DB-008
NFS exports are world-accessible or use no_root_squash or insecure.
Why it matters. These export options can grant untrusted clients filesystem access or preserve remote root privileges.
/etc/exports: NFS exports are world-accessible or use no_root_squash or insecure.
/srv/share *(rw,no_root_squash,insecure)
- Fix
- Restrict every export to explicit client CIDRs, use root_squash, remove insecure, and reload exports.
- Verify
Run exportfs -v during approved administration and confirm only intended networks and safe options appear.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-306, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- Linux exports(5)
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHUnsafe Samba Guest or SMB1 Configuration
NET-DB-009
Samba permits guest access, maps unknown users to guest, or allows SMB1.
Why it matters. Guest shares weaken accountability, while SMB1 lacks modern protocol protections and has a long history of severe flaws.
/etc/samba/smb.conf: Samba permits guest access, maps unknown users to guest, or allows SMB1.
guest ok enabled
unknown users map to guest
SMB1 NT1 enabled
- Fix
- Set guest ok = no, map to guest = Never, and server min protocol = SMB2_02 or newer. Review each share ACL.
- Verify
Run testparm -s during approved administration and confirm the effective values.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-306, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- Samba smb.conf Manual
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHBIND Open Recursion
NET-DB-010
BIND enables recursion without restricting recursive clients.
Why it matters. An open recursive resolver can be abused for reflection attacks and permits outsiders to consume resolver resources.
/etc/bind/named.conf.options: BIND enables recursion without restricting recursive clients.
recursion yes without a client ACL
- Fix
- Disable recursion on authoritative-only servers, or set allow-recursion and allow-query-cache to explicit trusted networks.
- Verify
Run named-checkconf and query recursion from an untrusted test network under an approved test plan.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-406, OWASP A05:2021, NIST 800-53 SC-5, CM-6, SC-7
- References
- BIND 9 Administrator Reference Manual - Access Control
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHBIND Zone Transfers Allowed to Any
NET-DB-011
BIND permits zone transfers to any client.
Why it matters. Unrestricted transfers disclose the complete DNS namespace and provide attackers with a detailed target inventory.
/etc/bind/named.conf.options: BIND permits zone transfers to any client.
allow-transfer includes any
- Fix
- Set allow-transfer to none or explicit secondary server addresses, preferably protected with TSIG.
- Verify
Run named-checkconf and verify AXFR is refused from an unauthorized test host.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- BIND 9 Administrator Reference Manual - allow-transfer
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHPostfix Open Relay Controls
NET-DB-012
Postfix relay restrictions are missing or mynetworks trusts overly broad ranges.
Why it matters. An open relay enables spam and phishing, damages domain reputation, and can expose the host to blocklisting.
/etc/postfix/main.cf: Postfix relay restrictions are missing or mynetworks trusts overly broad ranges.
reject_unauth_destination missing
mynetworks trusts all addresses
- Fix
- Set smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination and narrow mynetworks.
- Verify
Run postconf -n during approved administration and perform only an authorized relay test.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-441, OWASP A05:2021, NIST 800-53 AC-3, CM-6, SC-7
- References
- Postfix SMTP Relay and Access Control
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHIPv6 Listeners Without IPv6 Firewall
NET-FW-002
Network-reachable IPv6 listeners exist without a default-deny IPv6 firewall policy.
Why it matters. An IPv4-only firewall does not protect IPv6 services, creating an alternate path that bypasses intended filtering.
IPv6 firewall: IPv6 listeners exist but ip6tables input policy is not deny
- Fix
- Apply equivalent default-deny filtering for IPv6 with nftables or ip6tables and explicitly allow required services. Caution: allow SSH and ICMPv6 neighbour discovery and router messages before applying the default deny, or remote IPv6 sessions and IPv6 connectivity are cut.
- Verify
Run ip6tables -S and nft list ruleset, then confirm the input chain has a default drop or reject policy.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Network Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-923, NIST 800-53 SC-7
- References
- NIST SP 800-119, Guidelines for the Secure Deployment of IPv6
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
- Source
internal/checks/network/network_controls.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHFirewall Allows Sensitive Services From Anywhere
NET-FW-003
Checks whether the host firewall explicitly opens a listening database, administrative or application server port to every address on the internet.
Why it matters. A default-deny firewall only protects what it does not allow. A single "allow 3306 from anywhere" rule, often added while debugging, makes a database or admin panel as exposed as if there were no firewall at all.
firewall: Sensitive services are open to every address
tcp 0.0.0.0:3306 (MySQL/MariaDB) allowed from anywhere by iptables rule: -A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
- Fix
- Delete the rule or restrict it to the addresses that need it, for example: ufw delete allow 3306 && ufw allow from 203.0.113.10 to any port 3306 proto tcp . Better, bind the service to 127.0.0.1 and reach it through an SSH tunnel or VPN.
- Verify
ufw status numbered or nft list ruleset shows no rule opening that port to Anywhere.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-923, CWE-1327, OWASP A05:2021, NIST 800-53 SC-7, AC-4, CM-7
- References
- NIST SP 800-41 Rev. 1, Guidelines on Firewalls and Firewall Policy
ufw(8) manual (Ubuntu)
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P12: Firewall Policy Versus What Is Listening (offline: openvapt learn P12)
- Source
internal/checks/network/firewall_exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHCleartext Legacy Services Listening
NET-SVC-001
Checks for Telnet, FTP, rsh/rlogin, TFTP, plain POP3/IMAP/LDAP, SNMP v1/v2c and rsync daemons on network-reachable addresses.
Why it matters. These protocols send passwords and data unencrypted, so anyone on the path can read or alter them. Most also have weak or no authentication.
sockets: Cleartext services are network-reachable
tcp 0.0.0.0:21 FTP
udp 0.0.0.0:161 SNMP (v1/v2c community strings)
- Fix
- Replace with encrypted equivalents: SSH/SFTP instead of Telnet/FTP/rsh, IMAPS (993)/POP3S (995), LDAPS (636), SNMPv3. Disable the old service: systemctl disable --now <unit>.
- Verify
ss -tulpn should not show ports 21, 23, 69, 110, 143, 161, 389, 512-514 or 873 on public addresses.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Network Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, NIST 800-53 SC-8, CM-7
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
- Source
internal/checks/network/listeners.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHNetwork Time Service Amplification Risk
NET-SVC-003
NTP or chrony serves broad clients or permits legacy monitoring commands that can amplify traffic.
Why it matters. Internet-reachable time services with broad client access or legacy mode 6 or 7 controls can be abused for reflection and amplification.
/etc/ntp.conf: Time service access controls allow amplification-prone queries
- Fix
- Bind the time daemon to required interfaces, restrict clients to explicit networks, disable monitoring, and use noquery or equivalent controls.
- Verify
Confirm UDP port 123 is filtered from untrusted networks and review the daemon's effective access restrictions.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-406, NIST 800-53 SC-5, SC-7
- References
- CISA Alert TA14-013A, NTP Amplification Attacks Using CVE-2013-5211
chrony Documentation - Access Control
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/network_controls.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHApache Allows TLS 1.0 or 1.1
WEB-APA-005
SSLProtocol permits SSLv3, TLSv1 or TLSv1.1, or is not set on a TLS-enabled server (the default all -SSLv3 allows TLS 1.0 and 1.1).
Why it matters. TLS 1.0 and 1.1 are deprecated by RFC 8996 and lack the protections of TLS 1.2 and 1.3. Apache's default still allows them, so an explicit SSLProtocol is required. The directive is not the last word: mod_ssl uses the system OpenSSL, and when its configuration already sets a floor of TLS 1.2 (MinProtocol in openssl.cnf on Debian 12 and Ubuntu 22.04 and later, or a crypto policy of DEFAULT, FUTURE or FIPS on the RHEL family) the old versions cannot be negotiated whatever the directive lists. In that case the check reports Pass and names the floor, because rating a server High for a line that has no effect would contradict the live handshake checks (WEB-TLS). The directive is still worth tidying so the configuration says what it does.
/etc/apache2/apache2.conf: SSLProtocol permits SSLv3, TLSv1 or TLSv1.1, or is not set on a TLS-enabled server (the default all -SSLv3 allows TLS 1.0 and 1.1).
/etc/apache2/mods-enabled/ssl.conf: SSLProtocol all -SSLv2 (allows sslv3, tlsv1, tlsv1.1)
- Fix
- Set SSLProtocol -all +TLSv1.2 +TLSv1.3 (Mozilla intermediate) in mods-enabled/ssl.conf or ssl.conf, then apachectl configtest and reload.
- Verify
openssl s_client -connect 127.0.0.1:443 -servername <site> -tls1_1 should fail to connect.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-326, CWE-327, OWASP A02:2021, ASVS 9.1.3, NIST 800-53 SC-8, SC-13
- References
- Apache HTTP Server, SSLProtocol directive
Mozilla, Server Side TLS guidelines
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
OpenSSL, config(5): system default TLS settings (MinProtocol)
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHApache Cipher Suite Includes Weak Suites
WEB-APA-006
SSLCipherSuite includes NULL, export, DES or 3DES, RC4, MD5, anonymous or other legacy suites, or SSLHonorCipherOrder forces a legacy order.
Why it matters. Weak suites allow recorded traffic to be decrypted or sessions to be hijacked. The Mozilla guidelines give a short explicit list that modern clients all support.
/etc/apache2/apache2.conf: SSLCipherSuite includes NULL, export, DES or 3DES, RC4, MD5, anonymous or other legacy suites, or SSLHonorCipherOrder forces a legacy order.
/etc/apache2/mods-enabled/ssl.conf: weak tokens all, rc4-sha
SSLHonorCipherOrder on (Mozilla recommends off for modern and intermediate profiles)
- Fix
- Use the Mozilla intermediate list for SSLCipherSuite and set SSLHonorCipherOrder off , as the Mozilla SSL Configuration Generator produces for Apache.
- Verify
Run the nmap ssl-enum-ciphers script against 127.0.0.1 port 443 under your own test plan; it should list only grade A suites.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-327, OWASP A02:2021, ASVS 9.1.2, NIST 800-53 SC-8, SC-13
- References
- Mozilla SSL Configuration Generator
Apache HTTP Server, SSLCipherSuite directive
RFC 7525, Recommendations for Secure Use of TLS and DTLS
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHLaravel Debug Mode On or Application Key Missing
WEB-APP-001
Checks Laravel .env files for APP_DEBUG=true or an empty APP_KEY.
Why it matters. With APP_DEBUG on, Laravel's error page prints the environment, including database and mail passwords, to any visitor who triggers an error. APP_KEY encrypts sessions and cookies; with it empty or default the application refuses to run or signs nothing.
/srv/shop-laravel/.env: Laravel runs in debug mode or without an application key
APP_DEBUG is true
APP_KEY is empty
- Fix
- Set APP_DEBUG=false and APP_ENV=production in .env, run php artisan key:generate if APP_KEY is empty, then php artisan config:cache. Keep .env outside the web root (Laravel's public/ folder) and readable only by the application user.
- Verify
grep -E '^APP_(DEBUG|KEY)=' .env shows APP_DEBUG=false and a base64 key.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-209, CWE-321, OWASP A05:2021, ASVS 14.3.2, 2.10.4, NIST 800-53 CM-6, SI-11, IA-5
- References
- Laravel documentation, Deployment
Laravel documentation, Configuration (debug mode, environment files)
OWASP ASVS 4.0.3, V14 Configuration
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSymfony Running in the Development Environment
WEB-APP-003
Checks Symfony .env files for APP_ENV=dev or APP_DEBUG=1.
Why it matters. The dev environment enables the web profiler and debug toolbar, which show requests, queries, configuration, the container and sometimes credentials to any visitor, and it skips the caches that production relies on.
/srv/shop-crm/.env: Symfony runs in the development environment
APP_ENV is dev
APP_DEBUG is on
- Fix
- Set APP_ENV=prod and APP_DEBUG=0 in .env (or .env.local), run composer dump-env prod, clear the cache (php bin/console cache:clear) and remove the web profiler bundle from production.
- Verify
php bin/console about shows Environment prod and Debug false.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-215, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-6, SI-11
- References
- Symfony documentation, Configuring Symfony (environments)
Symfony documentation, How to Deploy a Symfony Application
OWASP ASVS 4.0.3, V14 Configuration
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHRails Master Key or Secrets File Exposed
WEB-APP-004
Checks Rails config/master.key, credentials key files and secrets.yml for world-read permissions or a location inside a web root.
Why it matters. master.key decrypts credentials.yml.enc, which holds every production secret, and secrets.yml holds the secret_key_base that signs sessions. Anyone who reads them can forge sessions and read the database password. Both are meant to stay out of version control and out of any public folder.
/srv/shop-rails/config/master.key: Rails key or secrets file is exposed
mode 0644 is readable by all users
- Fix
- chmod 600 config/master.key config/credentials/*.key; keep them out of git (.gitignore) and out of public/; load the key from RAILS_MASTER_KEY in the environment on servers. Rotate the credentials if the key was ever exposed.
- Verify
stat -c '%a %n' config/master.key shows 600, and git ls-files config/master.key prints nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-312, CWE-321, OWASP A02:2021, A05:2021, ASVS 2.10.4, 14.1.3, NIST 800-53 AC-3, SC-28, IA-5
- References
- Ruby on Rails Guides, Securing Rails Applications
Ruby on Rails Guides, Custom Credentials
OWASP Secrets Management Cheat Sheet
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSpring Boot Actuator Endpoints Fully Exposed
WEB-APP-006
Checks Spring Boot application properties for management.endpoints.web.exposure.include=* and probes the local site for an open /actuator/env.
Why it matters. Actuator's env, configprops, heapdump and threaddump endpoints print environment variables, configuration (including credentials) and process memory. Exposing them all over HTTP without authentication is one of the most common Java application leaks.
/opt/shop-api/application.properties: Spring Boot actuator endpoints are fully exposed
management.endpoints.web.exposure.include exposes sensitive actuator endpoints on the application port
- Fix
- Set management.endpoints.web.exposure.include=health,info (and exclude env,heapdump,configprops), move management.server.port to a port that is not published, and require authentication for every actuator endpoint with Spring Security.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/actuator/env prints 401, 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-497, OWASP A05:2021, A01:2021, ASVS 14.3.2, 4.3.2, NIST 800-53 CM-7, AC-3, SI-11
- References
- Spring Boot documentation, Actuator endpoints
Spring Boot documentation, Securing HTTP endpoints
OWASP WSTG-CONF-02, Test Application Platform Configuration
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHCMS Configuration Readable by All Users
WEB-CMS-004
Checks whether wp-config.php, Joomla configuration.php or Drupal settings.php can be read by every local user.
Why it matters. These files hold the database password and the keys that sign logins. If every account on the machine can read them, any other site, user or compromised process on the server can take over the CMS and its data.
/var/www/shop/wp-config.php: CMS configuration is readable by all users
WordPress configuration has mode 0666 (readable by all users)
/var/www/shop/configuration.php: CMS configuration is readable by all users
Joomla configuration has mode 0644 (readable by all users)
/var/www/shop/sites/default/settings.php: CMS configuration is readable by all users
Drupal configuration has mode 0664 (readable by all users)
- Fix
- chmod 640 <file> and chown it to the site owner with the web server's group (for example chown deploy:www-data wp-config.php); on PHP-FPM pools that run as the site user, 600 or 400 also works. Rotate the database password if other people have shell access.
- Verify
stat -c '%a %U:%G %n' <file> shows 640, 600 or 400.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-260, OWASP A05:2021, NIST 800-53 AC-3, SC-28
- References
- WordPress Developer Resources, Hardening WordPress
Drupal.org, Securing file permissions and ownership
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHCMS Configuration Writable by Other Users
WEB-CMS-005
Checks whether wp-config.php, Joomla configuration.php or Drupal settings.php is group- or world-writable.
Why it matters. These files are PHP code that runs on every request. Whoever can write them can add a backdoor that runs as the web server, which is how many shared-hosting compromises spread from one site to the next.
/var/www/shop/wp-config.php: CMS configuration is writable by other users
WordPress configuration has mode 0666 (writable by group or others)
/var/www/shop/sites/default/settings.php: CMS configuration is writable by other users
Drupal configuration has mode 0664 (writable by group or others)
- Fix
- chmod 640 (or 440) <file>. Drupal also expects sites/default to be 555 after installation. Review the file for code you did not add.
- Verify
stat -c '%a %n' <file> shows no write bit for group or others.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, OWASP A05:2021, NIST 800-53 AC-3, CM-5
- References
- WordPress Developer Resources, Hardening WordPress
Drupal.org, Securing file permissions and ownership
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDrupal Core Past End of Life
WEB-CMS-012
Reads the installed Drupal core version from disk and compares its major release with the Drupal security coverage dates.
Why it matters. Drupal 7, 8 and 9 no longer receive security advisories from the Drupal Security Team. Drupalgeddon (CVE-2014-3704) and Drupalgeddon 2 (CVE-2018-7600) showed how quickly unpatched Drupal sites are taken over at scale.
/var/www/shop: Drupal 8 reached end of life on 2020-11-02
- Fix
- Upgrade to a supported Drupal major with composer (drupal/core-recommended), run drush updatedb and test the site; for Drupal 7, migrate with the Migrate module or commission a rebuild.
- Verify
drush status --field=drupal-version or grep VERSION core/lib/Drupal.php
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- High
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2, SA-22
- References
- Drupal.org, Drupal core release cycle and end of life
NVD, CVE-2018-7600
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHJoomla Core Past End of Life
WEB-CMS-014
Reads the installed Joomla version from administrator/manifests/files/joomla.xml on disk and compares it with the Joomla support dates.
Why it matters. Joomla 3 left security support in August 2023 and Joomla 4 in October 2025. Sites on those series receive no fixes for new core vulnerabilities, while the exact version remains easy to fingerprint.
/var/www/shop: Joomla 3.9 left security support on 2023-08-17
- Fix
- Update to the current Joomla series through the Joomla Update component (back up first, check extension compatibility, then update), and keep the one-click updater enabled.
- Verify
grep '<version>' administrator/manifests/files/joomla.xml
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- High
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2, SA-22
- References
- Joomla Documentation, Joomla Release and Support Cycle
Joomla Documentation, Security Checklist
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDrupal update.php Open Without Authentication
WEB-CMS-019
Checks Drupal settings.php for $settings['update_free_access'] = TRUE.
Why it matters. update_free_access lets anyone run update.php, which executes database update hooks as the site. It exists for one-off maintenance and Drupal's own status report warns when it is left on.
/var/www/shop/sites/intranet/settings.php: Drupal update.php runs without authentication
$settings['update_free_access'] is TRUE
- Fix
- Set $settings['update_free_access'] = FALSE; in settings.php (the default) and run updates as user 1 or with drush updatedb.
- Verify
grep update_free_access sites/default/settings.php shows FALSE.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:H
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, OWASP A01:2021, A05:2021, ASVS 4.3.2, NIST 800-53 AC-3, CM-6
- References
- Drupal.org, Running update.php (update_free_access)
Drupal.org, Securing file permissions and ownership
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHVulnerable Web Application Libraries
WEB-CVE-001
Matches local web library versions against offline OSV advisories; WordPress core is inventoried and reported Incomplete because OSV publishes no WordPress feed.
Why it matters. Unpatched web libraries can expose users and server data to known vulnerabilities.
jquery: jquery 3.4.1: LAB-CVE-2020-11022 (CVE-2020-11022), severity high
matcher: range
source: /var/www/shop/package-lock.json
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
rack: rack 2.2.3: LAB-CVE-2022-30123 (CVE-2022-30123), severity critical
matcher: range
source: /var/www/shop/admin/Gemfile.lock
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
wordpress: wordpress 5.2.1: LAB-CVE-2019-17671 (CVE-2019-17671), severity high
matcher: range
source: /var/www/shop/wp-includes/version.php
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
flask: flask 2.0.1: LAB-CVE-2023-30861 (CVE-2023-30861), severity high
matcher: range
source: /var/www/shop/api/requirements.txt
Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
- Fix
- Update the affected library or WordPress core and deploy a refreshed lockfile or asset. For a source build, run 'make vulndb' to embed a generated snapshot.
- Verify
Re-run OpenVAPT and verify that the vulnerable version is no longer deployed.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2, RA-5
- References
- OSV
OSV schema, defined ecosystems (WordPress)
NVD
- Learn
- P10: Vulnerability Management: CVE, OSV and Known Exploited Vulnerabilities (offline:
openvapt learn P10)
A7: Security Testing in Agile Teams and CI (offline: openvapt learn A7)
- Source
internal/checks/web/cve.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHSecrets or Backups Stored Inside a Web Root
WEB-DOC-001
Looks on disk inside each web document root for environment files, database dumps, backups, archives and private keys.
Why it matters. Anything inside a document root may be downloadable, now or after a configuration change. Dumps, backups and keys there are a leading cause of data breaches; finding them on disk catches files the URL checks cannot guess.
/var/www/shop: 2 sensitive file(s) inside the web root
/var/www/shop/backup.sql (database dump)
/var/www/shop/.env (environment secrets)
- Fix
- Move each listed file outside the document root (for example to a 700 folder in the account's home), delete what is not needed, and rotate any secret or key that was exposed. Keep backups in a dedicated location outside every web root.
- Verify
Re-run this check; no files should be listed.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-530, CWE-538, CWE-312, OWASP A05:2021, ASVS 12.5.1, NIST 800-53 SC-28, CM-6
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files for Sensitive Information
OWASP Secrets Management Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/docroot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHWeb Root Files Writable by Other Users
WEB-DOC-002
Looks for world-writable files inside web document roots.
Why it matters. A world-writable PHP or HTML file lets any local user, or any other compromised site on the same server, plant a web shell or inject malware into pages served to visitors.
/var/www/shop: 2 world-writable file(s) in the web root
0666 /var/www/shop/wp-config.php
0666 /var/www/shop/index.php
- Fix
- chmod o-w <file> for each listed file (find <docroot> -type f -perm -0002 -exec chmod o-w {} +). Use 644 for files and 755 for folders, owned by the site account, and grant the web server write access only to upload folders.
- Verify
find <docroot> -type f -perm -0002 should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, OWASP A05:2021, NIST 800-53 AC-3, AC-6
- References
- OWASP WSTG-CONF-09, Test File Permission
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/docroot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHGit Repository Exposed on the Website
WEB-EXP-001
Checks whether the .git folder can be downloaded from each site.
Why it matters. An exposed .git folder lets anyone rebuild the full source code and history, often including passwords, API keys and database credentials committed by mistake.
shop.example.test: Exposed: /.git/HEAD (HTTP 200)
/.git/HEAD (HTTP 200)
- Fix
- Block dot-folders in the web server (Apache: RedirectMatch 404 /\.git ; nginx: location ~ /\.(?!well-known) { deny all; }) and deploy without the .git folder in the web root. Rotate any secret that was ever committed.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/.git/HEAD should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-527, CWE-538, OWASP A05:2021, ASVS 12.5.1, NIST 800-53 CM-7, SC-28
- References
- OWASP WSTG, Review Old Backup and Unreferenced Files (WSTG-CONF-04)
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHBackup or Database Dump Files Downloadable
WEB-EXP-004
Checks for common backup archives and SQL dumps left in the web root.
Why it matters. Backups contain the whole site and often the whole database, including customer data and password hashes.
shop.example.test: Exposed: /db.sql (HTTP 200)
/db.sql (HTTP 200)
- Fix
- Move backups outside the web root (for example /home/<user>/deploy-backups/ with mode 700), delete the exposed copies and treat their contents as leaked.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/backup.zip should print 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-530, OWASP A05:2021, ASVS 12.5.1, NIST 800-53 CM-7, SC-28
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHOther Version Control Metadata Exposed
WEB-EXP-007
Checks for exposed Subversion, Mercurial and Bazaar metadata folders.
Why it matters. Like .git, these folders let anyone reconstruct source code and history, including secrets that were committed by mistake.
shop.example.test: Exposed: /.svn/entries (HTTP 200)
/.svn/entries (HTTP 200)
- Fix
- Block dot-folders at the web server and deploy without version control metadata in the web root. Rotate any secret ever committed.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/.svn/entries should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-527, OWASP A05:2021, ASVS 12.5.1, NIST 800-53 CM-7, SC-28
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files for Sensitive Information
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHLog Files Downloadable From the Website
WEB-EXP-008
Checks for application and debug logs published under the web root.
Why it matters. Logs expose file paths, SQL queries, user data, session identifiers and sometimes credentials or API keys.
shop.example.test: Exposed: /wp-content/debug.log (HTTP 200)
/wp-content/debug.log (HTTP 200)
- Fix
- Move logs outside the web root, deny access to *.log at the web server, disable WP_DEBUG_LOG in production, and review the exposed logs for leaked secrets.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/wp-content/debug.log should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-532, CWE-538, OWASP A09:2021, A05:2021, ASVS 12.5.1, NIST 800-53 CM-7, SC-28
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files for Sensitive Information
OWASP Logging Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHFramework Debug Pages Exposed
WEB-EXP-012
Checks for development debug tools and verbose error pages left enabled in production.
Why it matters. Debug pages such as the Symfony profiler, Laravel's Whoops/Ignition pages or Django's debug 404 reveal source code, configuration, environment variables and sometimes allow code execution.
shop.example.test: Exposed: /_profiler/ (HTTP 200)
/_profiler/ (HTTP 200)
- Fix
- Disable debug mode in production (APP_DEBUG=false, DEBUG = False, APP_ENV=prod), remove profiler routes, and show generic error pages.
- Verify
Re-run this check; no debug pages should be detected.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-209, OWASP A05:2021, ASVS 14.3.2, 7.4.1, NIST 800-53 CM-7, SI-11
- References
- OWASP WSTG-ERRH-01, Testing for Improper Error Handling
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHnginx Allows TLS 1.0 or 1.1
WEB-NGX-003
ssl_protocols lists SSLv3, TLSv1 or TLSv1.1, or is not set on a TLS-enabled server, so the allowed version depends on the nginx build.
Why it matters. TLS 1.0 and 1.1 are deprecated by RFC 8996 and lack the protections of TLS 1.2 and 1.3. Clients that negotiate them are exposed to downgrade and known cipher weaknesses. The directive is not the last word: nginx uses the system OpenSSL, and when its configuration already sets a floor of TLS 1.2 (MinProtocol in openssl.cnf on Debian 12 and Ubuntu 22.04 and later, or a crypto policy of DEFAULT, FUTURE or FIPS on the RHEL family) the old versions cannot be negotiated whatever the directive lists. In that case the check reports Pass and names the floor, because rating a server High for a line that has no effect would contradict the live handshake checks (WEB-TLS). The directive is still worth tidying so the configuration says what it does.
/etc/nginx/nginx.conf: ssl_protocols lists SSLv3, TLSv1 or TLSv1.1, or is not set on a TLS-enabled server, so the allowed version depends on the nginx build.
/etc/nginx/nginx.conf: ssl_protocols TLSv1 TLSv1.1 TLSv1.2 (allows tlsv1, tlsv1.1)
- Fix
- Set ssl_protocols TLSv1.2 TLSv1.3; in the http block (the Mozilla intermediate profile), run nginx -t and reload.
- Verify
openssl s_client -connect 127.0.0.1:443 -servername <site> -tls1_1 should fail to connect.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-326, CWE-327, OWASP A02:2021, ASVS 9.1.3, NIST 800-53 SC-8, SC-13
- References
- nginx documentation, ngx_http_ssl_module
Mozilla, Server Side TLS guidelines
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
RFC 8996, Deprecating TLS 1.0 and TLS 1.1
OpenSSL, config(5): system default TLS settings (MinProtocol)
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHnginx Cipher List Includes Weak Suites
WEB-NGX-004
ssl_ciphers includes NULL, export, DES or 3DES, RC4, MD5, anonymous or other legacy suites, or ssl_prefer_server_ciphers forces a legacy order.
Why it matters. Weak suites allow recorded traffic to be decrypted or sessions to be hijacked. Modern clients already prefer strong suites, so the Mozilla guidelines recommend a short explicit list and ssl_prefer_server_ciphers off.
/etc/nginx/nginx.conf: ssl_ciphers includes NULL, export, DES or 3DES, RC4, MD5, anonymous or other legacy suites, or ssl_prefer_server_ciphers forces a legacy order.
/etc/nginx/nginx.conf: weak tokens all, rc4-sha, des-cbc3-sha
ssl_prefer_server_ciphers on (Mozilla recommends off for modern and intermediate profiles)
- Fix
- Use the Mozilla intermediate list, for example ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; and ssl_prefer_server_ciphers off;
- Verify
Run the nmap ssl-enum-ciphers script against 127.0.0.1 port 443 under your own test plan; it should list only grade A suites.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-327, OWASP A02:2021, ASVS 9.1.2, NIST 800-53 SC-8, SC-13
- References
- Mozilla SSL Configuration Generator
Mozilla, Server Side TLS guidelines
RFC 7525, Recommendations for Secure Use of TLS and DTLS
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHNode.js Version Past End of Life
WEB-NODE-001
Checks whether the installed Node.js runtime is a release line that no longer receives security fixes.
Why it matters. After end of life the Node.js project publishes no more security releases, so every later vulnerability in the runtime, its bundled OpenSSL or its HTTP parser stays open for good.
node: Node.js v18.19.1 reached end of life on 2025-04-30
- Fix
- Move to an Active or Maintenance LTS release (even-numbered majors), for example with the NodeSource or distribution packages, test the application, then restart its service.
- Verify
node --version shows a supported LTS major.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- High
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2, SA-22
- References
- Node.js Release Working Group, release schedule
endoflife.date, Node.js (community-maintained lifecycle data)
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHPHP Allows Remote File Inclusion
WEB-PHP-003
Checks whether include() and require() may load code from URLs.
Why it matters. With allow_url_include on, a single file-inclusion bug lets an attacker run their own PHP code from their own server (remote file inclusion).
php: allow_url_include = 1
- Fix
- In php.ini set allow_url_include = Off (the default since PHP 5.2) and restart PHP.
- Verify
php -r "echo ini_get('allow_url_include');" and check the FPM pool's php.ini or php_admin_value settings.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-98, OWASP A03:2021, A05:2021, ASVS 12.3.3, NIST 800-53 CM-6, CM-7
- References
- PHP manual, php.ini directives
OWASP PHP Configuration Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/php.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHPHP Version Past End of Security Support
WEB-PHP-004
Checks whether the installed PHP branch still receives security fixes from the PHP project.
Why it matters. Unsupported PHP versions never get fixes for newly found vulnerabilities, some of which allow remote code execution.
php: PHP 7.2 security support ended on 2020-11-30
Check whether your distribution backports security fixes to this version
- Fix
- Upgrade to a supported PHP branch (see php.net/supported-versions) and test the applications, or confirm your distribution still backports security fixes to this version.
- Verify
php -v
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Patch and Vulnerability Management
- Effort
- High
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2
- References
- PHP, Supported Versions
- Learn
- F3: Vulnerabilities, CVE, CWE and CVSS (offline:
openvapt learn F3)
P6: Information Exposure and Misconfiguration (offline: openvapt learn P6)
- Source
internal/checks/web/php.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDjango Debug Mode Enabled
WEB-PY-001
Checks Django settings files for DEBUG = True with no production override.
Why it matters. With DEBUG on, every error page shows source code, local variables, SQL queries and most settings, and Django keeps every SQL query in memory. Attackers trigger errors on purpose to read them.
/srv/shopadmin/shopadmin: Django debug mode is on
/srv/shopadmin/shopadmin/settings.py: DEBUG = True
- Fix
- Set DEBUG = False in production, preferably from the environment (DEBUG = os.environ.get('DJANGO_DEBUG') == '1'), set ALLOWED_HOSTS, and restart the application. Run python manage.py check --deploy.
- Verify
python manage.py check --deploy reports no DEBUG warning.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-215, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-6
- References
- Django documentation, Deployment checklist
Django settings reference, DEBUG
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHDjango Uses the Generated Development Secret Key
WEB-PY-003
Checks Django settings for a SECRET_KEY that starts with django-insecure-, the marker of the key generated by startproject.
Why it matters. SECRET_KEY signs sessions, password-reset tokens and other data. The generated key sits in source files that are usually copied into repositories and backups; anyone who has it can forge signed data and, with some session backends, take over accounts.
/srv/shopadmin/shopadmin: Django uses the generated development SECRET_KEY
/srv/shopadmin/shopadmin/settings.py: uses the generated django-insecure SECRET_KEY
- Fix
- Generate a new key (python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'), load it from the environment or a root-readable file (SECRET_KEY = os.environ['DJANGO_SECRET_KEY']), and restart. Changing the key logs all users out.
- Verify
python manage.py check --deploy reports no SECRET_KEY warning.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-798, CWE-321, OWASP A02:2021, A05:2021, ASVS 2.10.4, NIST 800-53 IA-5, SC-12
- References
- Django documentation, Deployment checklist
Django settings reference, SECRET_KEY
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
HIGHTomcat Manager Reachable Without Address Restriction
WEB-TOM-001
Checks whether the Tomcat Manager or Host Manager application is deployed without an address filter limiting it to localhost.
Why it matters. The Manager deploys WAR files, which means it runs any code it is given. Exposed to the network it is one stolen or guessed password away from full compromise, and it is a standard target of automated attacks.
/etc/tomcat9: Tomcat Manager is deployed without an address restriction
/usr/share/tomcat9-admin/manager is deployed with no RemoteAddrValve or RemoteCIDRValve restriction
- Fix
- If you do not use them, delete the manager and host-manager folders (or apt remove tomcatN-admin). Otherwise keep the default valve in META-INF/context.xml: <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> and reach the Manager through an SSH tunnel.
- Verify
grep -A2 RemoteAddrValve <webapps>/manager/META-INF/context.xml
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-923, OWASP A01:2021, A05:2021, NIST 800-53 AC-3, CM-7
- References
- Apache Tomcat 10.1, Security Considerations
Apache Tomcat 10.1, Manager App How-To
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/tomcat.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMBoot Loader Has No Password
HOST-BOOT-001
Checks that GRUB is configured with a superuser and a hashed password so the boot entries cannot be edited at the console.
Why it matters. Without a boot loader password anyone at the console or virtual console can edit the kernel command line (for example add init=/bin/bash) and get a root shell without any credentials, bypassing every control on the running system.
/boot/grub: No superuser or password directive in 1 GRUB file(s)
- Fix
- Run grub-mkpasswd-pbkdf2 (grub2-setpassword on RHEL family), add set superusers="admin" and password_pbkdf2 admin <hash> to /etc/grub.d/40_custom (RHEL family writes /boot/grub2/user.cfg), then regenerate with update-grub or grub2-mkconfig -o /boot/grub2/grub.cfg. Add --unrestricted to the normal menu entry so unattended reboots still work.
- Verify
grep -E 'set superusers|password_pbkdf2' /boot/grub/grub.cfg /boot/grub2/grub.cfg /boot/grub2/user.cfg /etc/grub.d/* 2>/dev/null | sed 's/grub.pbkdf2.*/<hash>/'
- CVSS v3.1
CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-306, NIST 800-53 AC-3, AC-6, CM-6
- References
- GNU GRUB Manual, Security
NIST SP 800-123, Guide to General Server Security
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMUEFI Secure Boot Disabled
HOST-BOOT-002
Checks the firmware's SecureBoot variable to see whether the boot chain is verified.
Why it matters. Secure Boot makes the firmware refuse unsigned boot loaders and kernels, which blocks boot kits and unsigned kernels planted by an attacker with disk or console access. Without it, anything written to the boot partition runs at the next reboot.
/sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c: Secure Boot is disabled
SecureBoot = 0
- Fix
- Enable Secure Boot in the firmware set-up and boot a signed shim and kernel (every mainstream distribution ships them). Custom kernels and out-of-tree modules then need signing with a Machine Owner Key. Where the platform cannot do Secure Boot, record the exception. Caution: unsigned kernels and modules (for example DKMS drivers such as NVIDIA or ZFS) stop loading once it is on, so sign or replace them first and keep console access for the first boot.
- Verify
mokutil --sb-state or od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-* (the fifth byte is 1 when enabled).
- CVSS v3.1
CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Category
- Secure Configuration
- Effort
- High
- Confidence
- High
- Standards
- CWE-1326, NIST 800-53 SI-7, CM-6
- References
- UEFI Specification, Secure Boot and Driver Signing
NIST SP 800-123, Guide to General Server Security
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMUncommon Filesystem Modules Not Disabled
HOST-BOOT-003
Checks that the cramfs, freevxfs, jffs2, hfs, hfsplus, udf and squashfs kernel modules are disabled in modprobe.d.
Why it matters. Each filesystem driver is kernel code that parses untrusted data. A local user who can mount removable media or a loop device gets the kernel to parse a crafted image with one of these rarely maintained drivers, and several have had memory-corruption bugs. Removing drivers nobody uses removes that attack surface.
/etc/modprobe.d: Filesystem modules not disabled: cramfs, freevxfs, jffs2, hfs, hfsplus, udf, squashfs
- Fix
- Create /etc/modprobe.d/openvapt-filesystems.conf with, for each module: install <module> /bin/false and blacklist <module> then unload any loaded one with modprobe -r <module>. Caution: first confirm that no listed module is in use (lsmod, findmnt); blocking a filesystem a mount or package format needs (for example squashfs for snap packages, or vfat for the EFI system partition) breaks those mounts at the next boot.
- Verify
for m in cramfs freevxfs jffs2 hfs hfsplus udf squashfs; do modprobe -n -v $m; lsmod | grep -w $m; done
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7, CM-6
- References
- modprobe.d(5), Linux man-pages
Kernel Self Protection Project, Recommended Settings
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMUSB Storage Driver Not Disabled
HOST-BOOT-004
Checks that the usb-storage kernel module is disabled in modprobe.d on servers that do not need removable media.
Why it matters. A USB stick plugged into a server is the simplest way to copy data out or bring malware in without touching the network. Disabling the driver makes the device invisible to the kernel.
/etc/modprobe.d: usb-storage is not disabled in modprobe.d
- Fix
- Create /etc/modprobe.d/openvapt-usb.conf containing install usb-storage /bin/false and blacklist usb-storage then modprobe -r usb-storage. Servers that need USB backups should record the exception instead.
- Verify
modprobe -n -v usb-storage should print install /bin/false; lsmod | grep usb_storage should print nothing.
- CVSS v3.1
CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 MP-7, CM-7
- References
- modprobe.d(5), Linux man-pages
MITRE ATT&CK T1091, Replication Through Removable Media
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMNo File Integrity Monitoring
HOST-BOOT-006
Checks that a file integrity tool (AIDE, Tripwire, Samhain or equivalent) is installed and scheduled to run.
Why it matters. After a compromise the first question is which files changed. Without a baseline and a scheduled comparison, a replaced binary, an added SUID file or an edited PAM stack stays invisible for months.
integrity: No file integrity tool found (AIDE, Tripwire, Samhain, osquery or OSSEC)
- Fix
- Install AIDE (apt install aide / dnf install aide), initialise the database with aideinit or aide --init, move the new database into place, and enable the daily check (dailyaidecheck.timer on Debian family, or a cron.daily entry) that mails or logs the differences.
- Verify
aide --check (or your tool's check command) runs and reports; systemctl list-timers | grep -i aide or ls /etc/cron.daily | grep -i aide
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:H/A:N
- Category
- Logging and Monitoring
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-778, NIST 800-53 SI-7, CM-3
- References
- AIDE, Advanced Intrusion Detection Environment
NIST SP 800-53 Rev. 5, Security and Privacy Controls
NIST SP 800-123, Guide to General Server Security
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDocker Daemon Not Hardened
HOST-CTR-002
Checks the Docker daemon defaults: no-new-privileges, inter-container communication, user namespace remapping and live restore.
Why it matters. Hardened daemon defaults limit what a compromised container can do: no-new-privileges blocks setuid escalation, disabling icc isolates containers, and user namespaces map container root to an unprivileged host user.
/etc/docker/daemon.json: Docker daemon hardening options are missing
no-new-privileges is not true
icc is not false
userns-remap is not set
live-restore is not true
- Fix
- Add to /etc/docker/daemon.json: "no-new-privileges": true, "icc": false, "userns-remap": "default", "live-restore": true then restart Docker after testing your containers.
- Verify
cat /etc/docker/daemon.json ; docker info | grep -Ei 'security|userns'
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-1188, NIST 800-53 CM-6, AC-6
- References
- Docker documentation, Docker Engine security
NIST SP 800-190, Application Container Security Guide
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
- Source
internal/checks/host/containers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDocker Daemon Allows Insecure Registries or Debug Features
HOST-CTR-010
Checks daemon.json for insecure-registries, debug mode and experimental features.
Why it matters. An insecure registry is pulled over plain HTTP or with an unverified certificate, so anyone on the path can swap the image for a malicious one. Debug logging and experimental features widen the daemon's attack surface and leak internal detail into logs.
docker daemon: Docker daemon allows insecure registries or debug features
daemon.json insecure-registries: registry.example.test:5000
daemon.json debug is true
daemon.json experimental is true
- Fix
- Remove insecure-registries (serve the registry over TLS with a trusted certificate, or add its CA to /etc/docker/certs.d/<registry>/ca.crt), set "debug": false and "experimental": false in daemon.json, and remove any --insecure-registry, --debug (-D) or --experimental flag from the dockerd ExecStart in docker.service drop-ins (then systemctl daemon-reload). Restart Docker in a maintenance window: running containers stop unless live-restore is on.
- Verify
docker info | grep -Ei 'insecure|debug|experimental'
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-494, CWE-1188, NIST 800-53 SI-7, CM-7
- References
- Docker documentation, dockerd daemon reference
NIST SP 800-190, Application Container Security Guide
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMContainers Run Without Memory or Process Limits
HOST-CTR-012
Looks for containers with no memory limit and no PID limit.
Why it matters. A container with no limits can use all the host's memory or fork until the kernel runs out of process slots, taking the host and every neighbour down (a fork bomb or a memory leak is enough). Limits turn that into a problem for one container.
containers: Containers have neither a memory nor a PID limit
3f2a9c1d8e7b: no memory limit, no PID limit
- Fix
- Recreate each container with --memory (for example 512m) and --pids-limit (for example 256), or set them in the compose file under deploy.resources.limits / pids_limit.
- Verify
docker inspect --format '{{.Name}} mem={{.HostConfig.Memory}} pids={{.HostConfig.PidsLimit}}' $(docker ps -aq)
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-770, NIST 800-53 SC-6, SC-5
- References
- Docker documentation, Resource constraints
NIST SP 800-190, Application Container Security Guide
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMContainers Run as Root With a Writable Root Filesystem
HOST-CTR-013
Looks for containers whose process runs as root and whose root filesystem is writable.
Why it matters. Root inside the container is the first half of most container escapes, and a writable root filesystem lets an attacker install tools and persist. A non-root user plus --read-only with a few tmpfs mounts removes both at once for most services.
containers: Containers run as root on a writable root filesystem
3f2a9c1d8e7b: runs as root with a writable root filesystem
- Fix
- Add USER <uid> to the image or run with --user 1000:1000, and start the container with --read-only plus --tmpfs /tmp for scratch space; recreate the container.
- Verify
docker inspect --format '{{.Name}} user={{.Config.User}} ro={{.HostConfig.ReadonlyRootfs}}' $(docker ps -aq)
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-732, NIST 800-53 AC-6, CM-7
- References
- OWASP Docker Security Cheat Sheet
NIST SP 800-190, Application Container Security Guide
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMBoot Loader Configuration Exposed
HOST-FS-006
Checks that the GRUB configuration is not readable or writable by normal users.
Why it matters. The boot loader configuration controls kernel parameters at boot. If writable, it allows boot-time privilege escalation; if readable, it may expose a boot password hash.
/boot/grub/grub.cfg: 1 file(s) are accessible by group or others
0644 /boot/grub/grub.cfg
- Fix
- chown root:root <grub.cfg> && chmod 600 <grub.cfg> (for example /boot/grub/grub.cfg or /boot/grub2/grub.cfg).
- Verify
stat -c '%a %U %n' /boot/grub/grub.cfg /boot/grub2/grub.cfg
- CVSS v3.1
CVSS:3.1/AV:P/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- GNU GRUB Manual, Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWorld-Writable Files Outside Temporary Directories
HOST-FS-014
Looks for files that any user can modify in program, service and home locations other than /etc (which HOST-FS-003 covers).
Why it matters. A world-writable script, binary or data file lets any local account, including a compromised web application, change what other users and services run or read.
filesystem: 4 world-writable file(s) found
0666 /srv/app/upload.sh
0666 /var/www/shop/index.php
0666 /var/www/shop/wp-config.php
0777 /usr/local/bin/backup.sh
- Fix
- For each listed file: chmod o-w <path>. Then find the deployment step or chmod 777 habit that created it.
- Verify
find /usr/local /opt /srv /var/www /home /usr/bin /usr/sbin -xdev -type f -perm -0002 should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6, CM-6
- References
- NIST SP 800-123, Guide to General Server Security
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSUID or SGID Programs Outside the Known Baseline
HOST-FS-016
Lists set-user-ID and set-group-ID programs in the system binary directories that are not on the documented baseline of what distributions ship.
Why it matters. Every SUID program is a door into another account, usually root. Programs such as nmap, vim, find, python or a custom helper with the SUID bit are a known route to instant root; the fewer unexplained SUID programs, the smaller that door.
filesystem: 1 SUID/SGID program(s) are not on the baseline
4755 /usr/bin/nmap
- Fix
- For each listed program decide whether the bit is needed. Remove it with chmod u-s,g-s <path> or uninstall the package. Record the ones you keep so the next review is quick. Caution: programs such as passwd, sudo, su, mount and ping need their bit to work for normal users; removing it from those breaks password changes and administrator access.
- Verify
find /bin /sbin /usr/bin /usr/sbin /usr/libexec /usr/lib -xdev -type f -perm /6000 and compare with your record.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N
- Category
- Access Control
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 AC-6, CM-7
- References
- MITRE ATT&CK T1548.001, Setuid and Setgid
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWorld-Writable Directories Without the Sticky Bit
HOST-FS-017
Looks for shared writable directories outside /tmp and /etc that let any user delete or replace other users' files.
Why it matters. In a world-writable directory without the sticky bit, any user can remove or swap a file placed there by another user or by a service, which turns upload folders and spool directories into file-replacement attacks.
filesystem: 4 shared directory(ies) lack the sticky bit
0777 /opt/scripts/ (directory, no sticky bit)
0777 /srv/shop-laravel/bootstrap/cache/ (directory, no sticky bit)
0777 /srv/shop-laravel/storage/ (directory, no sticky bit)
0777 /var/www/uploads/ (directory, no sticky bit)
- Fix
- chmod +t <dir> for directories that must stay shared, or chmod o-w <dir> for those that should not be writable by everyone.
- Verify
find /var /home /opt /srv /usr/local -xdev -type d -perm -0002 ! -perm -1000 should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-377, NIST 800-53 AC-3, CM-6
- References
- chmod(1), Linux man-pages (restricted deletion flag)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMAddress Space Layout Randomisation Not Fully Enabled
HOST-KRN-001
Checks that the kernel randomises memory layout for stack, libraries, heap and VDSO.
Why it matters. ASLR makes memory-corruption exploits much harder because attackers cannot predict where code lives.
kernel.randomize_va_space: kernel.randomize_va_space = 0 (hardened value: 2)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.randomize_va_space = 2 then apply with: sysctl --system
- Verify
sysctl kernel.randomize_va_space should print 2.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-344, NIST 800-53 CM-6, SI-16
- References
- Linux kernel documentation, /proc/sys/kernel
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMUnprivileged eBPF Allowed
HOST-KRN-009
Checks that normal users cannot load eBPF programs into the kernel.
Why it matters. Unprivileged eBPF has been the entry point for many local privilege-escalation bugs.
kernel.unprivileged_bpf_disabled: kernel.unprivileged_bpf_disabled = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.unprivileged_bpf_disabled = 1 then apply with: sysctl --system
- Verify
sysctl kernel.unprivileged_bpf_disabled should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 CM-6, SI-16
- References
- Linux kernel documentation, /proc/sys/kernel
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMRoot PATH Contains Unsafe Entries
HOST-PAM-008
Checks that the PATH set for root does not include the current directory, empty entries, relative paths or directories other users can write to.
Why it matters. When root's PATH contains . or an empty element, typing ls in a directory an attacker controls runs the attacker's ls as root. A world-writable directory on the PATH has the same effect for every command name that is not found earlier. This is one of the oldest Unix privilege escalations and still common in copied dotfiles.
root PATH: Root's PATH contains unsafe entries
/root/.bashrc: entry . (current directory)
/root/.bashrc: empty entry (trailing colon) means the current directory
- Fix
- Edit the listed file so PATH holds only absolute, root-owned directories, for example PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" , remove any . or trailing colon, and chmod o-w any listed directory. Log out and in again.
- Verify
sudo -i sh -c 'echo $PATH' should show no . or empty element; ls -ld $(echo $PATH | tr : ' ')
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:H
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-426, CWE-427, NIST 800-53 CM-6, AC-6
- References
- MITRE ATT&CK T1574.007, Hijack Execution Flow: Path Interception by PATH Environment Variable
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMRunning Kernel Older Than Installed Kernel
HOST-PKG-005
Checks that the kernel in memory is the newest kernel installed, so kernel security fixes are actually in effect.
Why it matters. A kernel update protects nothing until the machine boots into it. The package manager reports the update as installed, so the gap is invisible unless the running version is compared with the installed one. HOST-UPD-002 reads the Debian reboot marker; this check works on every distribution by comparing versions.
kernel: Running kernel 4.15.0-100-generic is older than installed kernel 4.15.0-150-generic; a reboot is needed
- Fix
- Schedule a maintenance window and reboot into the newest kernel. Where downtime is a problem, use the distribution's live patching service and still plan regular reboots.
- Verify
uname -r should match the newest version in dpkg -l 'linux-image-*' | grep ^ii or rpm -q kernel-core .
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, RA-5
- References
- NIST SP 800-40 Rev. 4, Guide to Enterprise Patch Management Planning
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/pkg_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWeak Password Hashing Algorithm Configured
HOST-PWD-001
Checks that new passwords are hashed with a modern, slow algorithm (SHA-512 or yescrypt).
Why it matters. If the shadow file ever leaks, fast or obsolete hashes such as MD5 or DES can be cracked in minutes. Slow, salted algorithms make offline cracking far more expensive.
/etc/login.defs: ENCRYPT_METHOD MD5 is weak
- Fix
- Set ENCRYPT_METHOD YESCRYPT (or SHA512 on older systems) in /etc/login.defs, and make sure pam_unix uses the same algorithm. Ask users to change passwords so existing hashes are upgraded.
- Verify
grep -i '^ENCRYPT_METHOD' /etc/login.defs
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:H/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-916, CWE-328, OWASP A02:2021, NIST 800-53 IA-5(1)
- References
- login.defs(5), Linux man-pages
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMAccounts With Obsolete Password Hashes
HOST-PWD-002
Checks /etc/shadow for passwords still stored with MD5 or traditional DES crypt.
Why it matters. Old hashes survive configuration changes until the user changes the password. MD5-crypt and DES hashes can be cracked quickly with commodity hardware.
/etc/shadow: Accounts use obsolete password hashes
olduser (MD5-crypt)
- Fix
- Configure a modern algorithm (HOST-PWD-001), then force a password change for each listed account (chage -d 0 <user>) or lock unused accounts (passwd -l <user>).
- Verify
Re-run this check; no accounts should be listed.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-916, CWE-328, OWASP A02:2021, NIST 800-53 IA-5(1)
- References
- crypt(5), libxcrypt, Debian trixie manual pages (hashing methods)
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMNo Account Lockout After Failed Logins
HOST-PWD-004
Checks that PAM temporarily locks accounts after repeated failed logins.
Why it matters. Without lockout, local and PAM-backed remote logins can be guessed indefinitely. A temporary lock after a few failures slows attacks and makes them visible. This check covers whether lockout exists and its deny threshold; HOST-PAM-002 covers only how long the lock lasts (unlock_time), so one missing lockout is reported once, here.
pam: No effective account lockout in the authentication stack
/etc/pam.d/common-auth: pam_faillock deny=100 (need 1 to 10)
- Fix
- Enable pam_faillock (authselect enable-feature with-faillock on RHEL family; pam-auth-update or a faillock profile on Debian/Ubuntu) with settings such as deny=5 unlock_time=900 in /etc/security/faillock.conf. Keep a root session open and test a login in a second session before closing it: a wrong PAM line can lock every user out, including administrators. Do not lock root (no even_deny_root) unless console access is assured.
- Verify
grep -E 'pam_faillock|pam_tally2' /etc/pam.d/common-auth /etc/pam.d/system-auth
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-307, OWASP A07:2021, NIST 800-53 AC-7
- References
- pam_faillock(8), Linux-PAM
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSSH Password Authentication Enabled
HOST-SSH-002
Checks whether SSH accepts passwords instead of only keys.
Why it matters. Internet-facing SSH receives constant automated password guessing. Public-key authentication cannot be guessed, phished as easily, or reused from another breached site.
sshd: Password logins are accepted (PasswordAuthentication defaults to yes)
passwordauthentication yes
- Fix
- Install your public key for each admin user (ssh-copy-id), confirm key login works in a second session, then set PasswordAuthentication no and KbdInteractiveAuthentication no in /etc/ssh/sshd_config and reload sshd.
- Verify
sshd -T | grep -Ei 'passwordauthentication|kbdinteractive' should show 'no' for both.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-307, CWE-521, NIST 800-53 IA-2(1), IA-5
- References
- OpenBSD, sshd_config(5) manual page
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/ssh_password_auth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSSH Offers Weak Cryptography
HOST-SSH-004
Checks the SSH ciphers, MACs, key exchange and host key algorithms for outdated choices.
Why it matters. CBC-mode ciphers, RC4, MD5/SHA-1 MACs and 1024-bit Diffie-Hellman have known practical weaknesses. Offering them lets a network attacker downgrade or weaken the session.
sshd: Weak SSH algorithms are offered
ciphers: aes128-cbc
macs: hmac-md5
kexalgorithms: diffie-hellman-group1-sha1
hostkeyalgorithms: ssh-rsa
- Fix
- Remove the listed algorithms. On OpenSSH 8.x and later the defaults are already strong: delete any custom Ciphers/MACs/KexAlgorithms lines, or set explicit modern lists such as Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com then reload sshd.
- Verify
sshd -T | grep -Ei '^(ciphers|macs|kexalgorithms)' should list no cbc, arcfour, md5 or sha1 entries, and hostkeyalgorithms should not list ssh-rsa.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-327, OWASP A02:2021, NIST 800-53 SC-8, SC-13
- References
- OpenBSD, sshd_config(5) manual page
RFC 9142, Key Exchange Method Updates for SSH
NIST SP 800-131A Rev. 2, Transitioning Cryptographic Algorithms
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
- Source
internal/checks/host/ssh_weak_crypto.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSSH Forwarding Features Enabled
HOST-SSH-007
Checks effective SSH Match contexts for TCP, agent, tunnel and gateway forwarding.
Why it matters. Forwarding can turn an SSH account into a route to protected services or expose a user's authentication agent.
sshd: SSH forwarding is enabled in at least one evaluated context
allowtcpforwarding default yes
allowagentforwarding default yes
- Fix
- Set AllowTcpForwarding no, AllowAgentForwarding no, PermitTunnel no and GatewayPorts no globally or in every applicable Match block, then reload sshd.
- Verify
Run sshd -T -C user=nobody,host=localhost,addr=192.0.2.1 and confirm each forwarding option is no.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-441, NIST 800-53 AC-4, CM-7
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
- Source
internal/checks/host/ssh_forwarding.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSSH Legacy Trust Options Enabled
HOST-SSH-011
Checks for host-based trust and user environment options that weaken SSH authentication.
Why it matters. HostbasedAuthentication and ignoring .rhosts trust other machines instead of users. PermitUserEnvironment lets users set variables such as LD_PRELOAD that can bypass restrictions.
sshd: Legacy trust options are enabled
hostbasedauthentication yes
ignorerhosts no
permituserenvironment yes
- Fix
- Set HostbasedAuthentication no , IgnoreRhosts yes and PermitUserEnvironment no in /etc/ssh/sshd_config, then reload sshd.
- Verify
sshd -T | grep -Ei 'hostbasedauthentication|ignorerhosts|permituserenvironment'
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-290, CWE-15, NIST 800-53 IA-2, CM-6
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMTelnet Server Installed or Enabled
HOST-SVC-002
Checks whether a Telnet server is installed or set to start at boot.
Why it matters. Telnet sends user names, passwords and every keystroke in the clear. Anyone on the network path reads them. SSH replaced it decades ago; a Telnet server on a modern server is almost always forgotten rather than needed.
services: 2 legacy service component(s) present
package telnetd is installed
unit telnet.socket is enabled at boot
- Fix
- apt purge telnetd inetutils-telnetd or dnf remove telnet-server , and systemctl disable --now telnet.socket . Use SSH. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l telnetd inetutils-telnetd telnetd-ssl telnet-server 2>/dev/null | grep '^ii' ; systemctl is-enabled telnet.socket telnetd.service inetutils-telnetd.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-1188, NIST 800-53 CM-7, CM-7(1), SC-8
- References
- MITRE ATT&CK T1040, Network Sniffing
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMrsh, rlogin, rexec or finger Server Installed or Enabled
HOST-SVC-003
Checks whether the Berkeley r-services (rsh, rlogin, rexec) or a finger server is installed or enabled.
Why it matters. The r-services trust the client's claim of who it is and send everything unencrypted; .rhosts files (HOST-USR-007) exist for them. finger lists account names and login times to anyone who asks, which is reconnaissance for password guessing.
services: 1 legacy service component(s) present
package rsh-server is installed
- Fix
- apt purge rsh-server rsh-redone-server fingerd or dnf remove rsh-server finger-server , and systemctl disable --now rsh.socket rlogin.socket rexec.socket finger.socket . Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l rsh-server rsh-redone-server fingerd finger-server efingerd cfingerd 2>/dev/null | grep '^ii' ; systemctl is-enabled rsh.socket rlogin.socket rexec.socket finger.socket rsh-redone-server.service fingerd.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-1188, NIST 800-53 CM-7, CM-7(1), SC-8
- References
- MITRE ATT&CK T1040, Network Sniffing
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMTFTP Server Installed or Enabled
HOST-SVC-004
Checks whether a TFTP server is installed or set to start at boot.
Why it matters. TFTP has no authentication and no encryption: any client that can reach it can read, and often write, every file in its directory. It is needed only on network boot (PXE) servers and for some network equipment, and is a frequent source of leaked configuration files. If this machine is one of the network boot (PXE) servers that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 1 legacy service component(s) present
package tftpd-hpa is installed
- Fix
- apt purge tftpd-hpa atftpd or dnf remove tftp-server , and systemctl disable --now tftpd-hpa.service tftp.socket . Where PXE is required, serve only that directory, read-only, from a dedicated host. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l tftpd-hpa atftpd tftp-server tftpd 2>/dev/null | grep '^ii' ; systemctl is-enabled tftpd-hpa.service atftpd.service tftp.socket tftp.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-306, CWE-1188, NIST 800-53 CM-7, CM-7(1), SC-8
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMFTP Server Installed or Enabled
HOST-SVC-005
Checks whether an FTP server (vsftpd, ProFTPD or Pure-FTPd) is installed or set to start at boot.
Why it matters. Plain FTP sends passwords and files unencrypted and needs a wide range of ports open. SFTP over SSH, which the SSH server already provides, does the same job encrypted. An FTP server is usually a leftover from a web hosting panel. If this machine is one of the hosts that must serve legacy FTP clients that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 2 legacy service component(s) present
package vsftpd is installed
unit vsftpd.service is enabled at boot
- Fix
- Move users to SFTP (the OpenSSH internal-sftp subsystem), then apt purge vsftpd proftpd-core pure-ftpd or dnf remove vsftpd proftpd and systemctl disable --now vsftpd . If FTP must stay, enforce TLS (FTPS) and restrict it to named users. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l vsftpd proftpd-core proftpd-basic proftpd pure-ftpd pure-ftpd-common 2>/dev/null | grep '^ii' ; systemctl is-enabled vsftpd.service proftpd.service pure-ftpd.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-1188, NIST 800-53 CM-7, CM-7(1), SC-8
- References
- MITRE ATT&CK T1040, Network Sniffing
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMNIS Server or Client Installed or Enabled
HOST-SVC-006
Checks whether the Network Information Service (NIS, ypserv or ypbind) is installed or enabled.
Why it matters. NIS distributes account and password hash databases over the network without encryption or strong authentication; anyone who can reach the server can request the whole password map. HOST-USR-006 looks for its + entries in the account files; this check looks for the software itself.
services: 1 legacy service component(s) present
package nis is installed
- Fix
- Replace NIS with a modern directory (SSSD with LDAPS or FreeIPA), then apt purge nis or dnf remove ypserv ypbind and systemctl disable --now ypserv ypbind . Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l nis ypserv ypbind yp-tools 2>/dev/null | grep '^ii' ; systemctl is-enabled ypserv.service ypbind.service nis.service yppasswdd.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-522, NIST 800-53 CM-7, CM-7(1), SC-8
- References
- MITRE ATT&CK T1040, Network Sniffing
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMCustom Services Run as Root
HOST-SYSD-001
Checks whether long-running services written by the administrator run as root instead of a dedicated user.
Why it matters. Application services (Node.js, Python, Java, custom daemons) are the code most exposed to attackers. If one runs as root, any bug in it gives the attacker full control of the machine instead of one unprivileged account.
systemd units: 4 custom service(s) run as root
shop-admin.service: no User= or DynamicUser=, runs as root (/etc/systemd/system/shop-admin.service)
shop-api.service: no User= or DynamicUser=, runs as root (/etc/systemd/system/shop-api.service)
shop-reports.service: no User= or DynamicUser=, runs as root (/etc/systemd/system/shop-reports.service)
shop-worker.service: no User= or DynamicUser=, runs as root (/etc/systemd/system/shop-worker.service)
- Fix
- Create a dedicated account (useradd --system --no-create-home --shell /usr/sbin/nologin <app>), give it ownership of only the folders the app writes to, then add User=<app> and Group=<app> to the [Service] section (or DynamicUser=yes). Run systemctl daemon-reload and restart the service. Ports below 1024 can be allowed with AmbientCapabilities=CAP_NET_BIND_SERVICE instead of root.
- Verify
systemctl show -p User,DynamicUser <unit> and ps -o user= -p $(systemctl show -p MainPID --value <unit>)
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 AC-6, CM-7
- References
- systemd.exec(5), execution environment configuration
NIST SP 800-123, Guide to General Server Security (least privilege for services)
- Learn
- P11: Service Hardening With systemd (offline:
openvapt learn P11)
- Source
internal/checks/host/systemd.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSecrets Written Into Service Unit Files
HOST-SYSD-005
Checks whether passwords, tokens or keys are set with Environment= in systemd unit files.
Why it matters. Unit files are normally readable by every user, and systemctl show prints a service's Environment= values to any local user. A database password or API token placed there is effectively public on the machine.
systemd units: Service unit files store secrets
shop-api.service (values not shown): Environment= sets DB_PASSWORD, STRIPE_API_KEY
- Fix
- Move secrets to a root-owned file readable only by root (chmod 600) and load it with EnvironmentFile=, or better use LoadCredential=/SetCredentialEncrypted= so the secret is only visible to the service. Then rotate every secret that was exposed.
- Verify
systemctl show -p Environment <unit> should show no secret values.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-526, CWE-312, OWASP A05:2021, NIST 800-53 IA-5, SC-28
- References
- systemd.exec(5), execution environment configuration
systemd, System and Service Credentials
- Learn
- P11: Service Hardening With systemd (offline:
openvapt learn P11)
- Source
internal/checks/host/systemd.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMReboot Required to Apply Updates
HOST-UPD-002
Checks whether installed updates (often kernel or core library fixes) are waiting for a reboot.
Why it matters. Updated packages do not protect anything until the running kernel and libraries are replaced. A pending reboot means known-fixed vulnerabilities are still live.
reboot: A reboot is required to apply installed updates
/var/run/reboot-required exists
linux-image-generic
libc6
- Fix
- Schedule a maintenance window and reboot (or use live patching where supported).
- Verify
ls /var/run/reboot-required should not exist after the reboot.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, NIST 800-53 SI-2
- References
- NIST SP 800-40 Rev. 4
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDuplicate User IDs
HOST-USR-004
Checks that no two accounts share the same numeric user id.
Why it matters. Accounts with the same UID are the same user to the kernel: they own each other's files and processes, and audit logs cannot tell them apart.
/etc/passwd: Accounts share user ids
UID 0: root, toor
- Fix
- Give each account a unique UID (usermod -u <new-uid> <user>) and fix file ownership (find / -xdev -uid <old-uid>).
- Verify
cut -d: -f3 /etc/passwd | sort | uniq -d should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-286, NIST 800-53 AC-2, IA-2
- References
- passwd(5), Linux man-pages
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMLegacy NIS Entries in Account Files
HOST-USR-006
Checks /etc/passwd, /etc/shadow and /etc/group for legacy '+' NIS inclusion entries.
Why it matters. '+' entries pull accounts from NIS, an unencrypted legacy directory service. If NIS is gone, the entry can still be abused to create unexpected accounts.
account files: Legacy NIS '+' entries found
/etc/passwd: +
- Fix
- Remove the '+' lines (with vipw / vigr) and use a modern directory service such as SSSD with LDAPS if central accounts are needed.
- Verify
grep '^+' /etc/passwd /etc/shadow /etc/group should print nothing.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-288, NIST 800-53 IA-2, CM-7
- References
- nsswitch.conf(5), Linux man-pages (compat mode)
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDuplicate Group IDs or Account Names
HOST-USR-008
Checks /etc/group for duplicate GIDs and group names, and /etc/passwd for duplicate user names.
Why it matters. Two groups with one GID are the same group to the kernel, so file permissions granted to one are granted to both. Duplicate names make tools and audit logs act on the wrong entry, and are a sign that the account files were edited by hand or by a broken script.
/etc/group: Duplicate group ids or names in the account files
GID 4: adm, staff
- Fix
- groupmod -g <new-gid> <group> for one of each duplicate pair, then fix file ownership (find / -xdev -gid <old-gid>); remove or rename the duplicate name entries with vigr and vipw, which lock the files while editing.
- Verify
cut -d: -f3 /etc/group | sort | uniq -d ; cut -d: -f1 /etc/group /etc/passwd | sort | uniq -d print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-286, NIST 800-53 AC-2, AC-3
- References
- group(5), Linux man-pages
passwd(5), Linux man-pages
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
P20: Secrets, Cron and Account Hygiene (offline: openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPassword and Shadow Files Out of Step
HOST-USR-009
Checks that every /etc/passwd account has a /etc/shadow entry, that no password hash sits in /etc/passwd, and that /etc/shadow has no orphan entries.
Why it matters. A hash in the world-readable /etc/passwd can be cracked offline by any user. An account with 'x' in passwd but no shadow line has an undefined password state that differs between tools, and shadow lines for deleted accounts are leftovers of a removal that did not finish.
/etc/passwd: Account files are inconsistent
olduser: /etc/shadow entry has no /etc/passwd account
daemon: /etc/passwd account has no /etc/shadow entry
toor: /etc/passwd account has no /etc/shadow entry
- Fix
- pwconv moves hashes into /etc/shadow and creates missing entries; userdel or vipw/vigr removes orphan lines; run pwck and grpck to confirm the files are consistent.
- Verify
pwck -r reports no errors.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-256, CWE-522, NIST 800-53 IA-5, AC-2
- References
- shadow(5), Linux man-pages
passwd(5), Linux man-pages
pwck(8), Linux man-pages
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
P20: Secrets, Cron and Account Hygiene (offline: openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMApplication Server Ports Reachable Without a Reverse Proxy
NET-APP-002
Checks whether application servers and developer tools (Node.js, Tomcat, Django, Flask, Vite) serve HTTP on network-reachable addresses.
Why it matters. Application servers are designed to sit behind a reverse proxy that adds TLS, security headers, logging and request limits. Reached directly they bypass all of that, and development servers on these ports often run with debug pages on. The port number alone does not prove a weakness, so this is rated Medium and should be reviewed.
sockets: Application server ports are network-reachable
tcp 0.0.0.0:3000 Node.js / Express app server, bound to all interfaces
a web server listens on port 80 or 443 on this machine: bind the application to 127.0.0.1 and publish it through that proxy
- Fix
- Bind the application to 127.0.0.1 (Node.js: app.listen(3000, '127.0.0.1'); Gunicorn: --bind 127.0.0.1:8000; Tomcat: address="127.0.0.1" on the Connector) and publish it only through nginx or Apache.
- Verify
ss -tlnp shows these ports on 127.0.0.1 or ::1 only.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-1327, OWASP A05:2021, NIST 800-53 SC-7, CM-7
- References
- OWASP Node.js Security Cheat Sheet
Gunicorn documentation, Deploying Gunicorn (behind a proxy)
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/network/firewall_exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMail Cleartext Authentication Allowed
NET-DB-013
Postfix or Dovecot permits plaintext authentication without requiring TLS.
Why it matters. Credentials sent before transport encryption can be observed by any party able to intercept the connection.
/etc/postfix/main.cf, /etc/dovecot/conf.d/10-auth.conf: Postfix or Dovecot permits plaintext authentication without requiring TLS.
smtpd_tls_auth_only is no
disable_plaintext_auth is no
- Fix
- Set smtpd_tls_auth_only = yes and disable_plaintext_auth = yes. Use implicit TLS on ports 465, 993, and 995. STARTTLS assessment is out of scope.
- Verify
Confirm the effective mail configuration and that unauthenticated plaintext sessions do not advertise AUTH.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-523, OWASP A02:2021, ASVS 9.1.1, NIST 800-53 SC-8, IA-5(1)
- References
- Dovecot Authentication Settings
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMySQL Symbolic Links Allowed for Tables
NET-DB-014
MySQL or MariaDB does not disable symbolic links for table files (skip-symbolic-links or symbolic-links=0).
Why it matters. With symlinks allowed, a user who can create tables can point table files at paths outside the data directory and read or overwrite them with the server's privileges. The MySQL manual recommends disabling the feature unless it is needed.
/etc/mysql/mysql.conf.d/mysqld.cnf: MySQL or MariaDB does not disable symbolic links for table files (skip-symbolic-links or symbolic-links=0).
no symbolic-links setting; MySQL 5.x (dpkg status mysql-server-5.7) allows symbolic links by default
- Fix
- Add symbolic-links=0 (or skip-symbolic-links ) under [mysqld] and restart the service in a maintenance window.
- Verify
SHOW VARIABLES LIKE 'have_symlink'; from an administrator session should print DISABLED.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-59, CWE-732, OWASP A05:2021, ASVS 14.1.3, NIST 800-53 CM-6, AC-6
- References
- MySQL 8.4 Reference Manual, Using Symbolic Links
MySQL 8.4 Reference Manual, Security Guidelines
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMySQL secure_file_priv Not Restricted
NET-DB-015
secure_file_priv is not set, or is set to an empty value, so LOAD DATA and SELECT ... INTO OUTFILE can read and write anywhere the server process can.
Why it matters. File import and export statements run with the database server's filesystem rights. Limiting them to one folder, or disabling them with NULL, stops an injected query from reading /etc files or dropping a web shell into the document root.
/etc/mysql/mysql.conf.d/mysqld.cnf: secure_file_priv is not set, or is set to an empty value, so LOAD DATA and SELECT ... INTO OUTFILE can read and write anywhere the server process can.
secure_file_priv is not set in the option files; MySQL 5.x (dpkg status mysql-server-5.7) leaves it empty by default
- Fix
- Add secure_file_priv = NULL (no file operations) or secure_file_priv = /var/lib/mysql-files under [mysqld] and restart in a maintenance window.
- Verify
SHOW VARIABLES LIKE 'secure_file_priv'; should print NULL or the chosen folder.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:L/A:N
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-73, CWE-250, OWASP A05:2021, ASVS 14.1.3, NIST 800-53 CM-6, AC-6, SI-10
- References
- MySQL 8.4 Reference Manual, secure_file_priv
MySQL 8.4 Reference Manual, Security Guidelines
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMySQL Does Not Require Encrypted Client Connections
NET-DB-016
require_secure_transport is not ON, so clients may log in and query over plaintext TCP.
Why it matters. Without the requirement, a client that is misconfigured or downgraded sends credentials and data in the clear across the network. The setting is harmless for Unix socket connections and makes TLS a server-side rule rather than a client choice. When bind-address keeps the server on loopback (127.0.0.1, ::1 or localhost) the plaintext path never leaves the machine and only a local root user could read it, so the check reports Pass with a note instead of a Medium finding; the Medium applies to servers reachable from the network.
/etc/mysql/mysql.conf.d/mysqld.cnf: require_secure_transport is not ON, so clients may log in and query over plaintext TCP.
require_secure_transport is not set; the default is OFF
- Fix
- Provision a server certificate (MySQL creates one by default), then add require_secure_transport = ON under [mysqld] and restart in a maintenance window. Test every application connection string first.
- Verify
SHOW VARIABLES LIKE 'require_secure_transport'; should print ON, and a client that disables TLS (ssl-mode DISABLED) connecting to 127.0.0.1 should be refused.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, ASVS 9.2.2, NIST 800-53 SC-8, SC-13
- References
- MySQL 8.4 Reference Manual, Configuring MySQL to Use Encrypted Connections
NIST SP 800-53 Rev. 5, SC-8 Transmission Confidentiality and Integrity
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPostgreSQL Uses md5 or password Authentication
NET-DB-019
pg_hba.conf has active rules with the md5 or password method instead of scram-sha-256.
Why it matters. The password method sends the password in clear text unless the connection is encrypted; md5 is a fast unsalted construction whose stored hashes work as passwords themselves (pass-the-hash) and which the PostgreSQL documentation describes as obsolete. SCRAM-SHA-256 fixes both.
/etc/postgresql/16/main/pg_hba.conf: pg_hba.conf has active rules with the md5 or password method instead of scram-sha-256.
/etc/postgresql/16/main/pg_hba.conf: host all all 10.0.0.0/8 md5
- Fix
- Set password_encryption = scram-sha-256 in postgresql.conf, have every role reset its password so a SCRAM verifier is stored, then change the pg_hba.conf methods to scram-sha-256 and reload.
- Verify
SELECT * FROM pg_hba_file_rules WHERE auth_method IN ('md5','password'); should return no rows.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-328, CWE-916, OWASP A02:2021, A07:2021, ASVS 2.4.1, NIST 800-53 IA-5, IA-5(1), SC-13
- References
- PostgreSQL, Authentication Methods
PostgreSQL, Password Authentication
NIST SP 800-63B, Digital Identity Guidelines: Authentication
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPostgreSQL SSL Not Enabled
NET-DB-020
postgresql.conf does not set ssl = on, so TCP clients cannot encrypt their sessions and hostssl rules cannot apply.
Why it matters. Without SSL every query and result crosses the network in the clear. Enabling it costs one certificate and lets pg_hba.conf require hostssl for remote clients. When listen_addresses keeps the server on loopback (the PostgreSQL default, localhost) the plaintext path never leaves the machine and only a local root user could read it, so the check reports Pass with a note instead of a Medium finding; the Medium applies to servers reachable from the network.
/etc/postgresql/16/main/postgresql.conf: postgresql.conf does not set ssl = on, so TCP clients cannot encrypt their sessions and hostssl rules cannot apply.
ssl is not set; the default is off
- Fix
- Install a certificate and key readable only by the postgres user, set ssl = on , ssl_cert_file and ssl_key_file, reload, then change remote pg_hba.conf rules from host to hostssl.
- Verify
SHOW ssl; should print on, and psql "sslmode=require host=127.0.0.1" should connect.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, ASVS 9.2.2, NIST 800-53 SC-8, SC-13
- References
- PostgreSQL, Secure TCP/IP Connections with SSL
NIST SP 800-53 Rev. 5, SC-8 Transmission Confidentiality and Integrity
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPostgreSQL Password Encryption Not SCRAM
NET-DB-022
password_encryption is set to md5, so new and changed passwords are stored as md5 verifiers that work as pass-the-hash credentials.
Why it matters. The stored md5 value is itself sufficient to authenticate, so a leaked catalog is a leaked set of passwords. SCRAM-SHA-256 stores a salted, iterated verifier that is not usable directly. PostgreSQL 14 and newer default to scram-sha-256; older clusters often carry an explicit md5 line.
/etc/postgresql/16/main/postgresql.conf: password_encryption is set to md5, so new and changed passwords are stored as md5 verifiers that work as pass-the-hash credentials.
/etc/postgresql/16/main/postgresql.conf: password_encryption = md5
- Fix
- Set password_encryption = scram-sha-256 , reload, and ask every role to reset its password so the verifier is regenerated. Then move pg_hba.conf to scram-sha-256 (NET-DB-019).
- Verify
SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%'; should return no rows after the resets.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-916, CWE-328, OWASP A02:2021, ASVS 2.4.1, NIST 800-53 IA-5(1), SC-13
- References
- PostgreSQL, Password Authentication
PostgreSQL, Connections and Authentication
NIST SP 800-63B, Digital Identity Guidelines: Authentication
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMRedis Dangerous Commands Not Restricted
NET-DB-023
redis.conf neither renames nor disables CONFIG, FLUSHALL, FLUSHDB, DEBUG and KEYS, and no ACL user excludes the @dangerous category.
Why it matters. An attacker who reaches Redis with any credential can wipe data with FLUSHALL, rewrite the configuration with CONFIG SET to write files (the classic path to a cron job or SSH key), or stall the server with KEYS *. Removing or renaming these for application users limits what a stolen credential can do.
/etc/redis/redis.conf: redis.conf neither renames nor disables CONFIG, FLUSHALL, FLUSHDB, DEBUG and KEYS, and no ACL user excludes the @dangerous category.
no rename-command, user or aclfile directive
- Fix
- Prefer ACLs on Redis 6 and newer: user app on >secret ~app:* -@all +@read +@write -@dangerous . Otherwise add rename-command FLUSHALL "" (and the same for FLUSHDB, CONFIG, DEBUG, KEYS) and restart.
- Verify
redis-cli -a <secret> ACL LIST or redis-cli CONFIG GET dir should be refused for the application user.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:L
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, OWASP A01:2021, A05:2021, ASVS 14.1.3, NIST 800-53 AC-6, CM-7
- References
- Redis Security
Redis ACL
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMBIND DNSSEC Validation Disabled
NET-DNS-002
named.conf sets dnssec-validation no, so the resolver accepts forged answers for signed zones.
Why it matters. DNSSEC validation lets a recursive resolver reject spoofed records for zones that are signed, which blocks cache poisoning of those names. BIND 9.16 and newer default to auto with the built-in root trust anchor, so an explicit no is a deliberate weakening.
/etc/bind/named.conf.options: named.conf sets dnssec-validation no, so the resolver accepts forged answers for signed zones.
dnssec-validation no
- Fix
- Set dnssec-validation auto; in options (remove any no ), run named-checkconf and rndc reconfig. Authoritative-only servers with recursion off may leave it unset.
- Verify
dig @127.0.0.1 dnssec-failed.org a should return SERVFAIL, and a signed name should show the ad flag.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-347, CWE-350, OWASP A08:2021, NIST 800-53 SC-20, SC-21
- References
- BIND 9 Administrator Reference Manual, dnssec-validation
NIST SP 800-81 Rev. 2, Secure Domain Name System Deployment Guide
- Learn
- P19: Database, Mail and DNS Hardening (offline:
openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMNo Active Host Firewall
NET-FW-001
Checks whether a host firewall (nftables, iptables, ufw or firewalld) is filtering incoming traffic.
Why it matters. A default-deny host firewall is a safety net: a service that is installed or misconfigured by mistake is still not reachable from the internet.
firewall: iptables has no drop or reject rules (input policy ACCEPT)
- Fix
- Ubuntu: ufw default deny incoming && ufw allow OpenSSH && ufw allow 80,443/tcp && ufw enable . RHEL family: systemctl enable --now firewalld . Always allow SSH before enabling, or you will lock yourself out.
- Verify
ufw status verbose or firewall-cmd --list-all or nft list ruleset
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Category
- Network Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-923, NIST 800-53 SC-7
- References
- NIST SP 800-41 Rev. 1, Guidelines on Firewalls and Firewall Policy
nftables wiki
- Learn
- F1: Security Basics (offline:
openvapt learn F1)
P3: Network Exposure and Firewalls (offline: openvapt learn P3)
- Source
internal/checks/network/firewall.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMContainer Ports Bypass the Host Firewall
NET-FW-005
Checks whether Docker publishes container ports through its own iptables chains with no DOCKER-USER filtering.
Why it matters. Docker inserts its NAT and FORWARD rules ahead of ufw and of the INPUT chain, so a port published with -p 8080:80 is reachable from the internet even when ufw says the port is denied. Administrators routinely believe the firewall protects these containers when it does not.
iptables: 1 published container port rule(s) are not filtered by the host firewall
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
- Fix
- Publish container ports on loopback only (-p 127.0.0.1:8080:80) and put a reverse proxy in front, or add filtering to DOCKER-USER, for example: iptables -I DOCKER-USER -i eth0 ! -s 203.0.113.0/24 -j DROP (persist it with your firewall tooling). Caution: test from an allowed address first; a wrong interface name or source range cuts access to every published container.
- Verify
docker ps --format '{{.Ports}}' shows 127.0.0.1 bindings, or iptables -S DOCKER-USER shows DROP rules.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Category
- Network Exposure
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-923, CWE-1327, OWASP A05:2021, NIST 800-53 SC-7, CM-7
- References
- Docker documentation, Packet filtering and firewalls
NIST SP 800-41 Rev. 1, Guidelines on Firewalls and Firewall Policy
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P12: Firewall Policy Versus What Is Listening (offline: openvapt learn P12)
- Source
internal/checks/network/firewall_exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPostfix SMTP TLS Not Offered or Has No Certificate
NET-MAIL-001
smtpd_tls_security_level is none or unset, or is may or encrypt without a server certificate, so incoming SMTP sessions cannot be encrypted.
Why it matters. Without STARTTLS every message and every authentication exchange that other servers and clients send to this host crosses the network in the clear. Opportunistic TLS (may) with a valid certificate is the baseline that other mail servers expect.
/etc/postfix/main.cf: smtpd_tls_security_level is none or unset, or is may or encrypt without a server certificate, so incoming SMTP sessions cannot be encrypted.
/etc/postfix/main.cf: smtpd_tls_security_level = may
TLS is enabled but no smtpd_tls_cert_file or smtpd_tls_chain_files is set
- Fix
- Set smtpd_tls_security_level = may , smtpd_tls_chain_files = /etc/letsencrypt/live/<host>/privkey.pem, /etc/letsencrypt/live/<host>/fullchain.pem (or smtpd_tls_cert_file and smtpd_tls_key_file), then postfix reload.
- Verify
postconf smtpd_tls_security_level smtpd_tls_chain_files and an authorised openssl s_client -starttls smtp -connect 127.0.0.1:25 showing a certificate.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, ASVS 9.2.2, NIST 800-53 SC-8, SC-13
- References
- Postfix TLS Support
Postfix Configuration Parameters
NIST SP 800-177 Rev. 1, Trustworthy Email
- Learn
- P19: Database, Mail and DNS Hardening (offline:
openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPostfix Allows TLS 1.0 or 1.1
NET-MAIL-002
smtpd_tls_protocols or smtpd_tls_mandatory_protocols is unset or still allows TLSv1 or TLSv1.1.
Why it matters. The Postfix default for opportunistic TLS still admits TLS 1.0 and 1.1, which RFC 8996 deprecates. Setting a floor of TLS 1.2 is compatible with every current mail server and client. Severity is Medium rather than High because SMTP opportunistic TLS already tolerates fallback to plaintext. Postfix uses the system OpenSSL, so when its configuration already sets a floor of TLS 1.2 (MinProtocol in openssl.cnf on Debian 12 and Ubuntu 22.04 and later, or a crypto policy of DEFAULT, FUTURE or FIPS on the RHEL family) the old versions cannot be negotiated whatever main.cf says; the check then reports Pass and names the floor, and the directives remain worth setting so the configuration says what it does.
/etc/postfix/main.cf: smtpd_tls_protocols or smtpd_tls_mandatory_protocols is unset or still allows TLSv1 or TLSv1.1.
smtpd_tls_protocols = !SSLv2, !SSLv3 (allows TLS 1.0 or 1.1)
smtpd_tls_mandatory_protocols is not set; the default allows TLS 1.0 and 1.1
- Fix
- Add smtpd_tls_protocols = >=TLSv1.2 and smtpd_tls_mandatory_protocols = >=TLSv1.2 (Postfix 3.6 and newer; on older releases use !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 ), then postfix reload.
- Verify
postconf smtpd_tls_protocols smtpd_tls_mandatory_protocols
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-326, CWE-327, OWASP A02:2021, ASVS 9.1.3, NIST 800-53 SC-8, SC-13
- References
- Postfix TLS Support
RFC 8996, Deprecating TLS 1.0 and TLS 1.1
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
- Learn
- P19: Database, Mail and DNS Hardening (offline:
openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDovecot Does Not Require TLS
NET-MAIL-004
Dovecot's ssl setting is yes or no instead of required, so IMAP and POP3 clients may use unencrypted sessions.
Why it matters. With ssl = yes, TLS is offered but a client may keep the whole session in the clear, and non-plaintext mechanisms still travel unprotected. ssl = required refuses any command before STARTTLS or implicit TLS, which makes disable_plaintext_auth (NET-DB-013) effective.
/etc/dovecot/conf.d/10-ssl.conf: Dovecot's ssl setting is yes or no instead of required, so IMAP and POP3 clients may use unencrypted sessions.
/etc/dovecot/conf.d/10-ssl.conf: ssl = yes
- Fix
- Set ssl = required and ssl_min_protocol = TLSv1.2 in conf.d/10-ssl.conf, then doveadm reload. Prefer implicit TLS ports 993 and 995 for clients. Caution: clients set to plaintext stop connecting, so confirm every mail client uses TLS first.
- Verify
doveconf ssl ssl_min_protocol should print required and TLSv1.2.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, ASVS 9.2.2, NIST 800-53 SC-8, SC-13
- References
- Dovecot SSL/TLS Configuration
RFC 8996, Deprecating TLS 1.0 and TLS 1.1
- Learn
- P19: Database, Mail and DNS Hardening (offline:
openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMManagement Panel or Monitoring Ports Network-Reachable
NET-SVC-004
Webmin, cPanel, WHM, RabbitMQ Management, Consul, the Docker API with TLS or the Prometheus node exporter listen on network-reachable addresses.
Why it matters. Management panels and exporters publish host metrics, service configuration and often a login form. They are a reconnaissance gift and a password guessing target, but they sit behind their own authentication or TLS, so the risk is lower than an open control plane.
sockets: Management panel or monitoring ports are network-reachable
tcp6 [::]:10000 Webmin, bound to all interfaces
tcp 0.0.0.0:15672 RabbitMQ Management, bound to all interfaces
- Fix
- Bind the panel or exporter to 127.0.0.1 or a management address, put it behind a reverse proxy with authentication, or restrict the port to monitoring hosts in the firewall.
- Verify
ss -tulpn shows these ports on 127.0.0.1, ::1 or a management address only.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-1327, OWASP A05:2021, NIST 800-53 AC-17, CM-7, SC-7
- References
- Prometheus, Security model
IANA Service Name and Transport Protocol Port Number Registry
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
- Source
internal/checks/network/services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDeprecated TLS 1.0 or 1.1 Accepted
NET-TLS-001
Checks whether local TLS services still accept TLS 1.0 or TLS 1.1.
Why it matters. TLS 1.0 and 1.1 were formally deprecated by RFC 8996 in 2021. They rely on outdated constructions (e.g. SHA-1 in the handshake) and fail PCI DSS and most compliance baselines.
shop.example.test on port 443: Deprecated TLS versions accepted
TLS 1.0 accepted
TLS 1.1 accepted
- Fix
- Apache: SSLProtocol -all +TLSv1.2 +TLSv1.3 . nginx: ssl_protocols TLSv1.2 TLSv1.3; . Postfix/Dovecot: set the minimum protocol to TLSv1.2. Reload the service afterwards.
- Verify
openssl s_client -connect 127.0.0.1:443 -tls1_1 </dev/null should fail to connect.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- Low
- Standards
- CWE-326, CWE-327, OWASP A02:2021, ASVS 9.1.3, NIST 800-53 SC-8, SC-13
- References
- RFC 8996, Deprecating TLS 1.0 and TLS 1.1
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
Mozilla Server Side TLS guidelines
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/network/tls.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMTLS Certificate Expired or Expiring Soon
NET-TLS-002
Checks the expiry date of the certificate each local TLS service presents.
Why it matters. An expired certificate breaks the site for visitors and trains users to click through warnings, which is exactly what an attacker needs for interception.
shop.example.test on port 443: Certificate expires in 8 days
notAfter 2026-10-25
- Fix
- Renew the certificate (certbot renew, or your provider's process) and make sure renewal is automated (systemctl list-timers | grep certbot).
- Verify
echo | openssl s_client -connect 127.0.0.1:443 -servername <site> 2>/dev/null | openssl x509 -noout -enddate
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-298, OWASP A02:2021, ASVS 9.2.1, NIST 800-53 SC-12, SC-17
- References
- Let's Encrypt, certificate lifetimes and renewal
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/network/tls.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSelf-Signed or Mismatched TLS Certificate
NET-TLS-003
Checks whether each site presents a self-signed certificate, or one that does not cover its name.
Why it matters. Browsers reject these certificates, so visitors either leave or learn to ignore warnings, which removes protection against interception.
shop.example.test: Certificate is self-signed
subject shop.example.test
- Fix
- Issue a certificate from a public CA covering every site name, for example with certbot --apache or certbot --nginx -d example.com -d www.example.com.
- Verify
openssl s_client -connect 127.0.0.1:443 -servername <site> </dev/null | openssl x509 -noout -subject -issuer -ext subjectAltName
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-295, CWE-297, OWASP A02:2021, A07:2021, ASVS 9.2.1, NIST 800-53 SC-17
- References
- RFC 6125, Representation and Verification of Domain-Based Application Service Identity
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/network/tls.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWeak TLS 1.2 Cipher Suites Accepted
NET-TLS-004
A local TLS service accepts an RC4, 3DES, or CBC with SHA-1 cipher suite under TLS 1.2.
Why it matters. Obsolete cipher constructions lack modern authenticated encryption and are prohibited by current TLS hardening guidance.
shop.example.test on port 443: Weak TLS 1.2 cipher suite accepted
TLS_RSA_WITH_3DES_EDE_CBC_SHA
- Fix
- Allow only modern AEAD suites for TLS 1.2 and prefer TLS 1.3. Remove RC4, 3DES, NULL, EXPORT, anonymous, and CBC with SHA-1 suites. Caution: very old clients and devices that support only those suites stop connecting; check the access logs for them first.
- Verify
Use an approved local TLS scanner and confirm each prohibited TLS 1.2 suite is rejected. Implicit TLS mail ports 465, 993, and 995 are included; STARTTLS is out of scope.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-326, CWE-327, OWASP A02:2021, ASVS 9.1.3, NIST 800-53 SC-8, SC-13
- References
- RFC 8996, Deprecating TLS 1.0 and TLS 1.1
NIST SP 800-52 Rev. 2, Guidelines for TLS Implementations
Mozilla Server Side TLS guidelines
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/network/tls_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMTLS Certificate Public Key Too Small
NET-TLS-005
A TLS leaf certificate uses RSA below 2048 bits or an elliptic curve below 256 bits.
Why it matters. Undersized public keys provide inadequate security strength and may permit certificate impersonation as cryptanalytic capability improves.
shop.example.test on port 443: Leaf certificate public key is too small
key RSA 1024 bits, signature SHA1-RSA
- Fix
- Replace the certificate and private key with RSA 2048 bits or stronger, or an approved EC key of at least 256 bits.
- Verify
Inspect the renewed leaf certificate key size on ports 443, 465, 993, 995, 8443, and 10000. STARTTLS is out of scope.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Medium
- Confidence
- Low
- Standards
- CWE-326, OWASP A02:2021, NIST 800-53 SC-12, SC-13
- References
- NIST SP 800-131A Rev. 2, Transitioning the Use of Cryptographic Algorithms and Key Lengths
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/network/tls_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSHA-1 Signed TLS Leaf Certificate
NET-TLS-006
A TLS leaf certificate is signed using SHA-1.
Why it matters. SHA-1 collision attacks invalidate its use for digital signatures and modern clients reject SHA-1 certificates.
shop.example.test on port 443: Leaf certificate uses a SHA-1 signature
key RSA 1024 bits, signature SHA1-RSA
- Fix
- Reissue the certificate with SHA-256 or stronger and deploy the complete updated chain.
- Verify
Inspect the signature algorithm on each implicit TLS service. STARTTLS is out of scope.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
- Category
- Cryptography and TLS
- Effort
- Medium
- Confidence
- Low
- Standards
- CWE-327, OWASP A02:2021, NIST 800-53 SC-12, SC-13
- References
- NIST Transitioning Away from SHA-1
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/network/tls_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMApache Directory Indexes Enabled in Configuration
WEB-APA-003
An Options directive enables Indexes (or All), so folders without an index page list their files.
Why it matters. Directory listings publish uploads, backups and scripts that were never linked. Debian ships Indexes on in the default /var/www block, so a fresh install fails this until changed.
/etc/apache2/apache2.conf: An Options directive enables Indexes (or All), so folders without an index page list their files.
/etc/apache2/apache2.conf: Options Indexes FollowSymLinks
- Fix
- Change the block to Options -Indexes +FollowSymLinks (or remove Indexes). Where a listing is wanted, protect that Directory with Require.
- Verify
apachectl -t -D DUMP_CONFIG 2>/dev/null | grep -n Options should show no Indexes except with a leading minus.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-548, OWASP A01:2021, A05:2021, ASVS 4.3.2, NIST 800-53 CM-7, AC-3
- References
- Apache HTTP Server, Options directive
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMApache Has No Slow Request Protection
WEB-APA-011
mod_reqtimeout does not appear to be loaded and no RequestReadTimeout is set, so a client that sends its request very slowly can hold a worker for the whole Timeout.
Why it matters. Apache keeps one worker busy for each open request. Without minimum read rates, a few clients sending headers a byte at a time (the Slowloris technique) can use up every worker and take the site offline. The module is enabled by default on most distributions, so its absence usually means it was removed.
/etc/apache2/apache2.conf: mod_reqtimeout does not appear to be loaded and no RequestReadTimeout is set, so a client that sends its request very slowly can hold a worker for the whole Timeout.
no reqtimeout_module and no RequestReadTimeout directive
- Fix
- Enable the module (Debian and Ubuntu: a2enmod reqtimeout; other systems: LoadModule reqtimeout_module modules/mod_reqtimeout.so) and keep or set RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 , then reload.
- Verify
apachectl -M 2>/dev/null | grep reqtimeout
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-770, OWASP A05:2021, NIST 800-53 SC-5, CM-6
- References
- Apache HTTP Server, mod_reqtimeout
Apache HTTP Server, Security Tips
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
P25: Availability Without Load Testing (offline: openvapt learn P25)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMApplication .env File Readable by All Users
WEB-APP-002
Checks the permission bits of framework .env files for world-read access.
Why it matters. .env files hold database passwords, API tokens and signing keys in plain text. A world-readable .env hands every account on the server, including other websites' PHP-FPM pools, the keys to this application.
/srv/shop-crm/.env: .env file is readable by all users
mode 0644 is readable by all users
/srv/shop-laravel/.env: .env file is readable by all users
mode 0644 is readable by all users
/var/www/shop/.env: .env file is readable by all users
mode 0644 is readable by all users
- Fix
- chmod 640 .env && chown <app-user>:<web-group> .env (or 600 when the application runs as its own user). Rotate the secrets if other people have had shell access.
- Verify
stat -c '%a %U:%G %n' .env shows 640 or 600.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-312, OWASP A05:2021, A02:2021, ASVS 14.1.3, NIST 800-53 AC-3, SC-28
- References
- OWASP Secrets Management Cheat Sheet
OWASP ASVS 4.0.3, V14 Configuration
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMRails Production Does Not Force HTTPS
WEB-APP-005
Checks config/environments/production.rb for config.force_ssl = true.
Why it matters. force_ssl redirects plain HTTP to HTTPS, marks cookies Secure and sends Strict-Transport-Security. Without it a session cookie can travel over HTTP once and be read on the network, even when the site also works over HTTPS.
/srv/shop-rails/config/environments/production.rb: Rails production does not force HTTPS
config.force_ssl is not true
- Fix
- Set config.force_ssl = true in config/environments/production.rb (and config.assume_ssl = true behind a TLS-terminating proxy), then restart the application.
- Verify
grep -n force_ssl config/environments/production.rb shows true, and curl -I http://<site>/ returns a 301 to https.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-614, OWASP A02:2021, A05:2021, ASVS 9.1.1, 3.4.1, NIST 800-53 SC-8, CM-6
- References
- Ruby on Rails Guides, Configuring Rails Applications
Ruby on Rails Guides, Securing Rails Applications
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMGit Repository Stored Inside a Web Root
WEB-APP-009
Looks on disk for a .git folder directly inside each web document root.
Why it matters. A .git folder in the document root is one web server rule away from being downloadable, which rebuilds the full source and its history, often with committed credentials. WEB-EXP-001 tests whether it is already reachable; this check finds it before a configuration change exposes it.
/var/www/shop: A .git repository is stored inside the web root
/var/www/shop/.git
- Fix
- Deploy from a build step that copies only the needed files (git archive, rsync --exclude .git, or a CI artefact), or point the document root at a public/ sub-folder as Laravel, Symfony and Rails expect. Remove the .git folder from the web root and rotate any secret ever committed.
- Verify
ls -d <docroot>/.git prints nothing.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-527, CWE-538, OWASP A05:2021, ASVS 12.5.1, NIST 800-53 CM-7, SC-28
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files
OWASP Secrets Management Cheat Sheet
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMFramework Writable Folders Open to All Users
WEB-APP-010
Checks Laravel and Symfony cache, log and storage folders for world-write permission.
Why it matters. chmod -R 777 storage is a common fix for permission errors. Laravel's bootstrap/cache and Symfony's var/cache hold compiled PHP that the framework includes on every request, so any local user who can write there runs code as the web server. Logs and sessions in storage are readable and forgeable too.
/srv/shop-laravel/.env: Framework cache or storage folders are world-writable
0777 /srv/shop-laravel/storage
0777 /srv/shop-laravel/bootstrap/cache
- Fix
- chmod -R o-w storage bootstrap/cache var and give the web server group write access instead: chgrp -R www-data storage bootstrap/cache && chmod -R g+w storage bootstrap/cache.
- Verify
find storage bootstrap/cache var -perm -0002 -type d prints nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:L
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-94, OWASP A05:2021, ASVS 14.1.3, NIST 800-53 AC-3, AC-6, CM-5
- References
- Laravel documentation, Deployment
Symfony documentation, Setting up or Fixing File Permissions
OWASP WSTG-CONF-09, Test File Permission
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMCookies Missing Secure, HttpOnly or SameSite
WEB-CK-001
Checks the security flags on cookies the home page sets.
Why it matters. Without Secure, cookies leak over plain HTTP. Without HttpOnly, any XSS bug can steal sessions. Without SameSite, cross-site request forgery is easier.
shop.example.test: Cookies are missing security flags
PHPSESSID: missing Secure, HttpOnly, SameSite
- Fix
- PHP: session.cookie_secure=1, session.cookie_httponly=1, session.cookie_samesite=Lax in php.ini . Frameworks have equivalent settings (e.g. Laravel config/session.php). Use HttpOnly for every cookie JavaScript does not need to read.
- Verify
curl -sI https://<site>/ | grep -i set-cookie
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:N
- Category
- Web Application Security
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-614, CWE-1004, CWE-1275, OWASP A05:2021, A07:2021, ASVS 3.4.1, 3.4.2, 3.4.3, NIST 800-53 SC-8, SC-23
- References
- OWASP Session Management Cheat Sheet
RFC 6265, HTTP State Management Mechanism
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
- Source
internal/checks/web/transport.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWordPress Shows Debug Output to Visitors
WEB-CMS-006
Checks wp-config.php for WP_DEBUG enabled without WP_DEBUG_DISPLAY set to false.
Why it matters. With WP_DEBUG on and display not turned off, PHP notices and errors are printed into pages, revealing server paths, plugin names and sometimes database details to anyone browsing the site.
/var/www/shop/wp-config.php: WordPress displays debug output
WP_DEBUG is true and WP_DEBUG_DISPLAY is not false
- Fix
- In production set define('WP_DEBUG', false);. If you need logs, use define('WP_DEBUG_LOG', '/path/outside/webroot/wp-debug.log'); together with define('WP_DEBUG_DISPLAY', false);.
- Verify
grep -E "WP_DEBUG(_DISPLAY)?'" wp-config.php
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-209, CWE-489, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 SI-11
- References
- WordPress Developer Resources, Debugging in WordPress
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWordPress Automatic Updates Disabled
WEB-CMS-008
Checks whether wp-config.php turns off WordPress background updates, including security releases.
Why it matters. WordPress ships security fixes as automatic minor updates. Turning the updater off means the site stays vulnerable until someone remembers to update by hand, which is how most compromised WordPress sites fall behind.
/var/www/shop/wp-config.php: WordPress automatic updates are disabled
AUTOMATIC_UPDATER_DISABLED is true
- Fix
- Remove those lines, or set define('WP_AUTO_UPDATE_CORE', 'minor'); so at least security releases install automatically. Keep backups and enable plugin auto-updates where practical.
- Verify
Dashboard, Updates shows that automatic updates for maintenance and security releases are on.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L
- Category
- Patch and Vulnerability Management
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2
- References
- WordPress Developer Resources, Configuring Automatic Background Updates
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMJoomla Debug or Verbose Error Reporting Enabled
WEB-CMS-009
Checks Joomla configuration.php for debug mode or maximum/development error reporting.
Why it matters. Joomla's debug console and verbose error reporting print queries, file paths and configuration details into pages that visitors can see.
/var/www/shop/configuration.php: Joomla debug output is enabled
$debug is enabled
$error_reporting is maximum
- Fix
- In System, Global Configuration set Debug System to No and Error Reporting to None (or System Default), or set public $debug = false; and public $error_reporting = 'none'; in configuration.php.
- Verify
grep -E 'debug|error_reporting' configuration.php
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-209, CWE-489, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 SI-11
- References
- Joomla Documentation, Security Checklist: Site Administration
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDrupal Trusted Host Patterns Not Set
WEB-CMS-013
Checks Drupal settings.php for the trusted_host_patterns setting.
Why it matters. Without trusted_host_patterns Drupal builds absolute links, including password reset links, from whatever Host header the request carries. An attacker who sends a crafted Host header can poison caches and redirect reset links to a domain they control.
/var/www/shop/sites/default/settings.php: Drupal accepts any Host header
$settings['trusted_host_patterns'] is not set
/var/www/shop/sites/intranet/settings.php: Drupal accepts any Host header
$settings['trusted_host_patterns'] is not set
- Fix
- Add to settings.php: $settings['trusted_host_patterns'] = ['^www\.example\.com$', '^example\.com$']; then clear caches (drush cr). The status report page should no longer warn about trusted hosts.
- Verify
drush status-report | grep -i 'trusted host'
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-644, CWE-346, OWASP A05:2021, ASVS 14.4.1, NIST 800-53 CM-6, SI-10
- References
- Drupal.org, Trusted Host settings
OWASP WSTG-INPV-17, Testing for Host Header Injection
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMagento Not in Production Mode
WEB-CMS-015
Checks app/etc/env.php for a MAGE_MODE other than production.
Why it matters. Developer and default modes show exceptions with stack traces and file paths to shoppers, disable static file signing and compile code on the fly. Adobe documents production as the only mode for a live store.
/var/www/shop/app/etc/env.php: MAGE_MODE is developer
- Fix
- bin/magento deploy:mode:set production (which also deploys static content and compiles DI), then clear caches. Keep developer mode for staging only.
- Verify
bin/magento deploy:mode:show prints production.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-209, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-6, SI-11
- References
- Adobe Commerce documentation, Set the Magento mode
Adobe Commerce documentation, Security best practices
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMGhost Configured With a Plain HTTP Site URL
WEB-CMS-016
Checks Ghost config.production.json for a url that starts with http://.
Why it matters. Ghost builds every link, including the admin login and member sign-in links, from the configured url. With http:// the admin session and members' tokens travel in the clear even when HTTPS is available, and browsers see mixed content.
/srv/shop-blog/config.production.json: Ghost url uses plain http://
- Fix
- ghost config url https://<your-domain> (or edit config.production.json), set up TLS with ghost setup ssl or your reverse proxy, then ghost restart.
- Verify
ghost config get url prints an https:// address.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, A05:2021, ASVS 9.1.1, NIST 800-53 SC-8, CM-6
- References
- Ghost documentation, Configuration (url)
OWASP Transport Layer Security Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMCross-Origin Resource Sharing Allows Any Origin With Credentials
WEB-COR-001
Checks the home page's CORS headers for a wildcard origin combined with credentials, or an origin of null.
Why it matters. A permissive CORS policy can let any website read responses on behalf of a logged-in visitor, exposing personal data and tokens.
shop.example.test: Permissive CORS policy
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
- Fix
- Return Access-Control-Allow-Origin only for an explicit allow-list of trusted origins, never '*' or 'null' together with credentials, and add Vary: Origin.
- Verify
curl -sI https://<site>/ | grep -i access-control
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-942, OWASP A05:2021, A01:2021, ASVS 14.5.3, NIST 800-53 AC-4, CM-6
- References
- OWASP WSTG-CLNT-07, Testing Cross Origin Resource Sharing
MDN Web Docs, Access-Control-Allow-Origin
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
- Source
internal/checks/web/docroot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMArchives or Certificates Inside a Web Root
WEB-DOC-003
Lists archives (*.tar.gz, *.tgz, *.tar, *.7z) and certificate files (*.pem, *.crt) inside each web document root for review, outside download folders.
Why it matters. A tarball inside a web root is often a site or database backup left after a migration, and a .pem file sometimes carries the private key next to the certificate. Both are downloadable by anyone who guesses the name. But download sites publish archives on purpose and public certificates are harmless, so this is a Medium review item, not a High finding; names that clearly mean backup, dump or key are rated High by WEB-DOC-001.
/var/www/shop: 2 archive or certificate file(s) inside the web root to review
/var/www/shop/shop-2026.tar.gz (archive; confirm it is a published download, not a site backup)
/var/www/shop/cert.pem (certificate or key material; confirm it holds no private key)
/var/www/shop/downloads/catalogue.tar.gz (in a download folder, expected)
- Fix
- Confirm each file is meant to be public. Move backups and anything holding a private key outside the document root, rotate any exposed key, and keep published downloads in a dedicated folder such as /downloads/.
- Verify
Re-run this check; only files you have confirmed as intended downloads should remain, in a download folder.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-538, CWE-552, OWASP A05:2021, ASVS 12.5.1, NIST 800-53 SC-28, CM-6
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files for Sensitive Information
OWASP Secrets Management Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/docroot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPHP Information Page Exposed
WEB-EXP-003
Checks for phpinfo() pages left on the site.
Why it matters. phpinfo() reveals PHP and module versions, file paths, environment variables and sometimes credentials, giving attackers a detailed map of the server.
shop.example.test: Exposed: /phpinfo.php (HTTP 200)
/phpinfo.php (HTTP 200)
- Fix
- Delete the file. Never leave diagnostic pages on a production server.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/phpinfo.php should print 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-7, SI-11
- References
- PHP manual, phpinfo()
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDirectory Listing Enabled
WEB-EXP-005
Checks whether the web server lists folder contents when there is no index page.
Why it matters. Directory listings reveal every file in a folder, including backups, uploads and scripts never meant to be linked.
shop.example.test: Exposed: /uploads/ (HTTP 200)
/uploads/ (HTTP 200)
- Fix
- Apache: Options -Indexes . nginx: autoindex off; (the default). Add an empty index.html to folders that must stay browsable-free.
- Verify
curl -s https://<site>/uploads/ | grep -i 'index of' should print nothing.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-548, OWASP A01:2021, A05:2021, ASVS 4.3.2, NIST 800-53 CM-7, AC-3
- References
- Apache HTTP Server, Options directive
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMWeb Server Status Page Exposed
WEB-EXP-006
Checks whether Apache server-status/server-info or nginx stub_status are reachable for each site.
Why it matters. Status pages show live requests (including URLs with tokens), client IPs, virtual hosts and modules.
shop.example.test: Exposed: /server-status (HTTP 200), no local-only restriction (Require local, Require ip 127.0.0.1 or allow 127.0.0.1 with deny all) found in the web server configuration; the scan requests from 127.0.0.1, so confirm from another machine
/server-status (HTTP 200)
no local-only restriction (Require local, Require ip 127.0.0.1 or allow 127.0.0.1 with deny all) found in the web server configuration; the scan requests from 127.0.0.1, so confirm from another machine
- Fix
- Restrict to administrators: <Location /server-status> Require local </Location> (Apache), or allow 127.0.0.1; deny all; (nginx). Remove the module if unused.
- Verify
From another machine: curl -s -o /dev/null -w '%{http_code}' https://<site>/server-status should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-7, SI-11
- References
- Apache HTTP Server, mod_status
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDatabase Administration Tool Exposed
WEB-EXP-011
Checks whether phpMyAdmin or Adminer login pages are publicly reachable.
Why it matters. Database admin tools are among the most attacked paths on the internet: they invite password guessing and their own vulnerabilities give direct database access.
shop.example.test: Exposed: /phpmyadmin/ (HTTP 200)
/phpmyadmin/ (HTTP 200)
- Fix
- Remove the tool, or restrict it to administrators by IP allow-list, VPN or an extra authentication layer, and keep it updated.
- Verify
From outside your network, the paths should return 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-306, OWASP A05:2021, A07:2021, NIST 800-53 CM-7, AC-3
- References
- OWASP WSTG-CONF-05, Enumerate Infrastructure and Application Admin Interfaces
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMissing HTTP Strict Transport Security (HSTS)
WEB-HDR-001
Checks that HTTPS sites tell browsers to always use HTTPS, for at least six months.
Why it matters. Without HSTS, the first visit or any typed http:// link can be intercepted and downgraded to plain HTTP (SSL stripping) on public Wi-Fi.
shop.example.test: Strict-Transport-Security header is missing
- Fix
- Apache: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" . nginx: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; . Only add 'preload' once every subdomain supports HTTPS.
- Verify
curl -sI https://<site>/ | grep -i strict-transport-security
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, CWE-523, OWASP A05:2021, ASVS 14.4.5, NIST 800-53 SC-8
- References
- RFC 6797, HTTP Strict Transport Security
OWASP HTTP Headers Cheat Sheet
MDN Web Docs, Strict-Transport-Security
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMMissing Content Security Policy
WEB-HDR-002
Checks that each site sends a Content-Security-Policy header.
Why it matters. A CSP limits where scripts may load from, turning many cross-site scripting (XSS) bugs from account takeover into a blocked request.
shop.example.test: Content-Security-Policy header is missing
- Fix
- Start with a report-only policy to find what the site loads, then enforce, for example: Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
- Verify
curl -sI https://<site>/ | grep -i content-security-policy
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N
- Category
- Web Application Security
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1021, CWE-79, OWASP A03:2021, A05:2021, ASVS 14.4.3, NIST 800-53 SI-10
- References
- OWASP Content Security Policy Cheat Sheet
W3C Content Security Policy Level 3
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSite Can Be Framed (Clickjacking)
WEB-HDR-003
Checks that each site forbids being embedded in other sites' frames.
Why it matters. If a page can be framed, an attacker can overlay it invisibly and trick users into clicking buttons (clickjacking), such as 'delete' or 'transfer'.
shop.example.test: Neither X-Frame-Options nor CSP frame-ancestors is set
- Fix
- Send Content-Security-Policy: frame-ancestors 'self' (modern) and X-Frame-Options: SAMEORIGIN (older browsers).
- Verify
curl -sI https://<site>/ | grep -Ei 'x-frame-options|frame-ancestors'
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1021, OWASP A04:2021, ASVS 14.4.7, NIST 800-53 SC-18
- References
- OWASP Clickjacking Defense Cheat Sheet
MDN Web Docs, X-Frame-Options
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMnginx Directory Listing Enabled in Configuration
WEB-NGX-002
An nginx server or location block sets autoindex on.
Why it matters. Directory listings publish every file in a folder, including uploads, backups and scripts that were never linked. The configuration view finds this even for folders the probe check did not request.
/etc/nginx/nginx.conf: An nginx server or location block sets autoindex on.
/etc/nginx/nginx.conf: autoindex on
- Fix
- Remove autoindex on; or set autoindex off; in that block. Where a listing is really needed, protect the location with auth_basic or an allow list.
- Verify
nginx -T | grep -n autoindex should show only off or nothing.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-548, OWASP A01:2021, A05:2021, ASVS 4.3.2, NIST 800-53 CM-7, AC-3
- References
- nginx documentation, ngx_http_autoindex_module
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMnginx Serves Hidden Files and Folders
WEB-NGX-007
No location block denies paths that begin with a dot, so .git, .env, .svn and .htaccess files under the document root are served if present.
Why it matters. Dot files hold repository history, credentials and server rules. One deny rule for every path segment starting with a dot removes a whole class of leaks, including files deployed by mistake later.
/etc/nginx/nginx.conf: No location block denies paths that begin with a dot, so .git, .env, .svn and .htaccess files under the document root are served if present.
no location ~ /\. block found
- Fix
- Add to every server block: location ~ /\. { deny all; access_log off; log_not_found off; } and keep .well-known reachable with a more specific location ^~ /.well-known/ block before it.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/.git/HEAD should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-538, CWE-527, OWASP A05:2021, ASVS 12.5.1, 14.3.3, NIST 800-53 CM-7, SC-28
- References
- nginx documentation, ngx_http_core_module
OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPHP Displays Errors to Visitors
WEB-PHP-001
Checks whether PHP prints error messages into web pages.
Why it matters. Error messages reveal file paths, SQL queries and code structure, and can leak data. They help attackers turn a small bug into a working exploit.
php: display_errors = 1
- Fix
- In php.ini set display_errors = Off and log_errors = On , then restart PHP-FPM or the web server.
- Verify
php -r "echo ini_get('display_errors');" and check the FPM pool's php.ini or php_admin_value settings.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-209, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 SI-11, CM-6
- References
- PHP manual, php.ini directives
OWASP PHP Configuration Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/php.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPHP Session Cookies Not Hardened
WEB-PHP-005
Checks PHP's session settings: HttpOnly and SameSite cookies and strict session id mode.
Why it matters. Session cookies are the keys to logged-in accounts. Without HttpOnly any XSS bug can steal them; without strict mode PHP accepts attacker-chosen session ids (session fixation).
php: PHP session cookies are not hardened
session.cookie_httponly = Off
session.use_strict_mode = 0
session.cookie_samesite is empty
- Fix
- In php.ini set session.cookie_httponly = 1 , session.use_strict_mode = 1 , session.cookie_samesite = Lax and, for HTTPS sites, session.cookie_secure = 1 , then restart PHP-FPM.
- Verify
php -r "echo ini_get('session.cookie_httponly'), ini_get('session.use_strict_mode'), ini_get('session.cookie_samesite');"
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1004, CWE-384, OWASP A07:2021, ASVS 3.4.2, 3.2.1, NIST 800-53 SC-23, CM-6
- References
- PHP manual, php.ini directives
PHP manual, Session security
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
P6: Information Exposure and Misconfiguration (offline: openvapt learn P6)
- Source
internal/checks/web/php.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMDjango Accepts Any Host Header
WEB-PY-002
Checks Django settings for ALLOWED_HOSTS = ['*'].
Why it matters. ALLOWED_HOSTS protects against Host header attacks. With a wildcard, an attacker can make Django build password-reset and other absolute links that point at the attacker's domain, and can poison shared caches.
/srv/shopadmin/shopadmin: Django accepts any Host header
/srv/shopadmin/shopadmin/settings.py: ALLOWED_HOSTS allows any host
- Fix
- List the real domain names: ALLOWED_HOSTS = ['example.com', 'www.example.com'], and restart the application.
- Verify
python manage.py check --deploy
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-346, OWASP A05:2021, NIST 800-53 CM-6, SI-10
- References
- Django documentation, Deployment checklist
Django settings reference, ALLOWED_HOSTS
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMPython Development Server Used in a Service
WEB-PY-005
Checks whether a service runs a development web server such as manage.py runserver, flask run or python -m http.server.
Why it matters. Development servers are documented as unsuitable for production: they have not been security-audited, handle load and slow clients poorly and often run with debugging features. python -m http.server publishes a whole folder.
systemd units: Services run Python development servers
shop-admin.service: runs a development server (manage.py runserver)
shop-reports.service: runs a development server (flask run)
- Fix
- Serve the application with a production server (Gunicorn or uWSGI for WSGI, Uvicorn without --reload or Hypercorn for ASGI) bound to 127.0.0.1, behind nginx or Apache. Serve static files from the web server.
- Verify
systemctl show -p ExecStart <unit> shows a production server.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-489, CWE-1188, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-7
- References
- Django documentation, django-admin runserver (not for production)
Flask documentation, Deploying to Production
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMSite Available Over Plain HTTP Without Redirect
WEB-TLS-001
Checks that every site redirects http:// requests to https://.
Why it matters. Pages served over plain HTTP can be read and changed by anyone on the network path, including injected malware and stolen session cookies.
shop.example.test: Site content is served over plain HTTP
HTTP status 200
- Fix
- Apache: in the port 80 vhost add Redirect permanent / https://<site>/ . nginx: return 301 https://$host$request_uri; . Get a free certificate with certbot if HTTPS is not set up yet.
- Verify
curl -sI http://<site>/ should show a 301 with Location: https://...
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:L/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-319, OWASP A02:2021, ASVS 9.1.1, NIST 800-53 SC-8
- References
- OWASP Transport Layer Security Cheat Sheet
- Learn
- P4: TLS, Certificates and HTTPS (offline:
openvapt learn P4)
- Source
internal/checks/web/transport.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMTomcat Shutdown Port Uses the Default Command
WEB-TOM-003
Checks whether Tomcat's shutdown port is enabled with the well-known default command SHUTDOWN.
Why it matters. Anyone who can connect to the shutdown port (8005 by default) and send the shutdown string stops Tomcat. With the default string, every local user and every compromised process on the machine can take the applications offline.
/etc/tomcat9: Tomcat shutdown port uses the default command
<Server port="8005" shutdown="SHUTDOWN">
- Fix
- Disable the port with <Server port="-1" ...> and stop Tomcat through systemd, or set shutdown to a long random string. Restart Tomcat.
- Verify
grep '<Server' <conf>/server.xml shows port="-1".
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, OWASP A05:2021, NIST 800-53 CM-6, CM-7
- References
- Apache Tomcat 10.1, Security Considerations
Apache Tomcat 10.1 Configuration Reference, The Server Component
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/tomcat.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
MEDIUMTomcat Example and Documentation Applications Deployed
WEB-TOM-005
Checks whether the examples or docs web applications that ship with Tomcat are deployed.
Why it matters. The sample applications are written to demonstrate features, not to be safe. Some (such as the session example) let visitors change server-side session data, and all of them reveal the exact Tomcat version.
/etc/tomcat9: Tomcat sample applications are deployed
/var/lib/tomcat9/webapps/examples is deployed
- Fix
- Delete the examples and docs folders from webapps (or apt remove tomcatN-examples tomcatN-docs) and restart Tomcat.
- Verify
ls <webapps> lists only your own applications (and ROOT).
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, OWASP A05:2021, NIST 800-53 CM-7
- References
- Apache Tomcat 10.1, Security Considerations
OWASP WSTG-CONF-02, Test Application Platform Configuration
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/tomcat.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAudit Daemon Not Enabled at Boot
HOST-AUD-001
Checks that the audit daemon (auditd) is set to start at every boot, not only running now.
Why it matters. An audit daemon that was started by hand stops recording at the next reboot, leaving a gap exactly when an attacker who forced a restart would want one. HOST-LOG-002 reports whether auditd is running; this check reports whether it will come back.
auditd: auditd is disabled, so it will not record after the next reboot
- Fix
- systemctl enable auditd (on some distributions: systemctl enable --now auditd). Then confirm the rules in /etc/audit/rules.d load at boot with augenrules --check.
- Verify
systemctl is-enabled auditd should print enabled.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12
- References
- auditd(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWIdentity Files Not Audited
HOST-AUD-002
Checks that changes to the account, group, password and sudo files are recorded by the audit system.
Why it matters. An attacker who adds an account, joins a privileged group or grants themselves sudo edits one of a handful of files. A watch rule on each makes that change an audit event with the user, process and time attached; without it the change leaves no trace beyond the file itself.
audit rules: Audit rules are missing
no watch on /etc/passwd
no watch on /etc/group
no watch on /etc/shadow
no watch on /etc/gshadow
no watch on /etc/sudoers
no watch on /etc/sudoers.d
- Fix
- Add to /etc/audit/rules.d/50-identity.rules: -w /etc/passwd -p wa -k identity and the same for /etc/group, /etc/shadow, /etc/gshadow, /etc/sudoers and /etc/sudoers.d/ , then run augenrules --load.
- Verify
auditctl -l | grep -E 'passwd|shadow|sudoers'
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12, AC-2(4)
- References
- auditctl(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWLogin and Logout Events Not Audited
HOST-AUD-003
Checks that the files recording logins, failed logins and sessions are watched by the audit system.
Why it matters. Login records are the first thing an investigator asks for and the first thing an intruder cleans. Watching lastlog, the failed-login store and the wtmp and btmp session files makes tampering itself an audit event.
audit rules: Audit rules are missing
no watch on /var/log/lastlog
no watch on the failed-login store (/var/run/faillock or /var/log/faillog)
no watch on /var/log/wtmp
no watch on /var/log/btmp
- Fix
- Add to /etc/audit/rules.d/50-login.rules: -w /var/log/lastlog -p wa -k logins , -w /var/run/faillock -p wa -k logins , -w /var/log/wtmp -p wa -k session , -w /var/log/btmp -p wa -k session , then augenrules --load.
- Verify
auditctl -l | grep -E 'lastlog|faillock|wtmp|btmp'
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12, AC-7
- References
- auditctl(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSystem Time Changes Not Audited
HOST-AUD-004
Checks that the audit system records changes to the system clock and time zone.
Why it matters. Moving the clock is a classic way to confuse log timelines, forge timestamps or defeat certificate and token expiry. Auditing the time-setting system calls and /etc/localtime attributes every change to a user and process.
audit rules: Audit rules are missing
no rule for system call adjtimex
no rule for system call settimeofday
no rule for system call clock_settime
no watch on /etc/localtime
- Fix
- Add to /etc/audit/rules.d/50-time.rules: -a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change (and the same with arch=b32), plus -w /etc/localtime -p wa -k time-change , then augenrules --load.
- Verify
auditctl -l | grep -E 'settimeofday|localtime'
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-8, AU-12
- References
- auditctl(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWKernel Module Loading Not Audited
HOST-AUD-005
Checks that loading and unloading kernel modules is recorded by the audit system.
Why it matters. A rootkit is usually a kernel module. Auditing init_module, finit_module and delete_module (or the kmod program) records the moment one is loaded, which is often the only evidence that survives.
audit rules: Audit rules are missing
no rule for init_module and delete_module, and no rule on the kmod program
- Fix
- Add to /etc/audit/rules.d/50-modules.rules: -a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k modules (and arch=b32), or -a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>=1000 -F auid!=unset -k modules , then augenrules --load.
- Verify
auditctl -l | grep -E 'init_module|kmod'
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12, CM-7
- References
- auditctl(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPrivileged Command Use Not Audited
HOST-AUD-006
Checks that the audit system records when ordinary users run privileged (setuid or setgid) programs.
Why it matters. Programs such as sudo, su, passwd and mount run with elevated rights. Recording each execution by a real user (auid at or above the first normal user id) shows who used privilege and when, which is the core of a usable audit trail.
audit rules: Audit rules are missing
no execution rule with perm=x and an auid>= filter
- Fix
- Generate rules for every setuid and setgid program: find / -xdev \( -perm -4000 -o -perm -2000 \) -type f | awk '{print "-a always,exit -F path=" $1 " -F perm=x -F auid>=1000 -F auid!=unset -k privileged"}' > /etc/audit/rules.d/50-privileged.rules then augenrules --load.
- Verify
auditctl -l | grep 'perm=x'
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12, AC-6(9)
- References
- auditctl(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAudit Configuration Not Immutable
HOST-AUD-007
Checks that the audit rule set ends with -e 2, which locks the rules until the next reboot.
Why it matters. Without the immutable flag, anyone who gains root can delete the audit rules (auditctl -D) and work unobserved. With -e 2 the rules can only be changed by rebooting, which is itself a loud, logged event.
audit rules: Audit rules are missing
last rule is not -e 2 (found: -f 1)
- Fix
- Add -e 2 as the last line of the last file in /etc/audit/rules.d (for example 99-finalize.rules), then augenrules --load and reboot. Plan rule changes before enabling it: every later change needs a reboot.
- Verify
auditctl -s | grep enabled should print enabled 2.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-9, AU-12
- References
- auditctl(8), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAudit Log Files Readable by Others
HOST-AUD-008
Checks that the audit log directory and files can be read only by root.
Why it matters. Audit logs record which user ran which command with which arguments, including file names and sometimes secrets passed on a command line. They are also the record an intruder most wants to edit. Both reasons call for root-only access.
/var/log/audit: Audit logs are accessible beyond root
directory /var/log/audit mode 0755 uid 0 (need 0750 or stricter, owned by root)
/var/log/audit/audit.log mode 0644 uid 0 (need 0640 or stricter, owned by root)
- Fix
- chmod 0750 /var/log/audit && chmod 0600 /var/log/audit/* && chown -R root:root /var/log/audit , and set log_group = root in /etc/audit/auditd.conf so new files keep these modes.
- Verify
stat -c '%a %U %n' /var/log/audit /var/log/audit/*
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-532, CWE-732, OWASP A09:2021, NIST 800-53 AU-9, AC-6
- References
- auditd.conf(5), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAudit Daemon Ignores a Full Log Disk
HOST-AUD-009
Checks that auditd is told what to do when its log file is full or the disk runs low, rather than silently dropping events.
Why it matters. With max_log_file_action = ignore the log grows until the disk is full; with suspend auditing simply stops. An unset space_left_action means nobody is warned before that happens. Either way an attacker who fills the disk switches auditing off.
/etc/audit/auditd.conf: auditd will drop or stop auditing when the log disk fills
max_log_file_action = ignore
space_left_action = ignore
admin_space_left_action is not set
- Fix
- In /etc/audit/auditd.conf set max_log_file_action = keep_logs (or rotate with enough num_logs), space_left_action = email (or syslog or exec), and admin_space_left_action = halt or single as policy requires, then systemctl restart auditd. Caution: admin_space_left_action = halt or single stops the server or drops it to single-user mode when the audit disk fills; choose it only where losing audit records is worse than downtime, and give /var/log/audit room and monitoring first.
- Verify
grep -E '^(max_log_file_action|space_left_action|admin_space_left_action)' /etc/audit/auditd.conf
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-4, AU-5
- References
- auditd.conf(5), Linux man-pages
NIST SP 800-92, Guide to Computer Security Log Management
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWJournal Not Persistent or Not Compressed
HOST-AUD-010
Checks that systemd-journald is configured to keep the journal on disk and to compress it.
Why it matters. Storage=volatile keeps the journal only in memory, so a reboot (or a crash an attacker caused) erases the evidence. Compression keeps a persistent journal small enough to retain for weeks. HOST-LOG-001 looks for the journal directory; this check reads the configuration that decides what happens to it.
journald.conf: The journal is not kept persistently and compressed
Storage=volatile (/etc/systemd/journald.conf): the journal is lost at reboot
Compress=no (/etc/systemd/journald.conf)
- Fix
- In /etc/systemd/journald.conf set Storage=persistent and Compress=yes , create the directory with mkdir -p /var/log/journal && systemd-tmpfiles --create --prefix /var/log/journal , then systemctl restart systemd-journald.
- Verify
journalctl --header | head and ls -d /var/log/journal
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-4, AU-9, AU-11
- References
- journald.conf(5), systemd
NIST SP 800-92, Guide to Computer Security Log Management
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWLogs Not Forwarded to a Remote Collector
HOST-AUD-011
Checks that system logs are sent to another machine, so an intruder with root cannot erase the only copy.
Why it matters. Whoever gains root on a server can delete or edit its local logs. A copy that already left the machine, to a log server or a SIEM, is the record an investigation can trust. NIST SP 800-92 treats centralised log collection as a basic log management control.
syslog: No remote log destination is configured; the only copy of the logs is on this machine
- Fix
- rsyslog: create /etc/rsyslog.d/90-remote.conf with *.* action(type="omfwd" target="logs.example.internal" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="x509/name") and restart rsyslog. Or configure systemd-journal-upload with URL= pointing at a journal-remote collector. Prefer TLS so logs are not readable in transit.
- Verify
grep -rE '^[^#].*@|omfwd' /etc/rsyslog.conf /etc/rsyslog.d/ or grep '^URL=' /etc/systemd/journal-upload.conf
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-9(2), AU-6, SI-4
- References
- NIST SP 800-92, Guide to Computer Security Log Management
rsyslog.conf(5), Debian trixie manual pages (forwarding actions)
journal-upload.conf(5), systemd
- Learn
- P21: Audit Logging and Monitoring Depth (offline:
openvapt learn P21)
- Source
internal/checks/host/audit_journal.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWKernel Module Loading Unrestricted
HOST-BOOT-005
Checks that the running kernel refuses unsigned modules or has module loading switched off entirely.
Why it matters. A root-level attacker who can load any module owns the kernel: rootkits hide processes and files from every tool on the box. Signature enforcement or kernel.modules_disabled = 1 after boot makes that persistence step fail.
kernel.modules_disabled: Any module can be loaded: modules_disabled = 0 and no signature enforcement or lockdown
- Fix
- Boot with module.sig_enforce=1 (or lockdown=integrity) on the kernel command line and sign any out-of-tree modules, or set kernel.modules_disabled = 1 from a late boot service once every needed module is loaded (it cannot be turned back on without a reboot).
- Verify
sysctl kernel.modules_disabled; cat /sys/module/module/parameters/sig_enforce /sys/kernel/security/lockdown
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 SI-7, CM-7
- References
- Linux kernel documentation, Kernel module signing facility
Kernel Self Protection Project, Recommended Settings
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPrelink Installed
HOST-BOOT-007
Checks that the prelink tool is absent, or disabled where the package is still installed.
Why it matters. Prelink rewrites binaries and libraries in place, which changes their hashes and defeats integrity monitoring and package verification, and it weakens address randomisation by fixing load addresses. Modern systems gain nothing from it.
prelink: Prelink is installed
/usr/sbin/prelink
/etc/prelink.conf
- Fix
- Undo and remove it: prelink -ua && apt purge prelink (or dnf remove prelink). Then re-initialise the integrity database (aide --init).
- Verify
command -v prelink should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-344, NIST 800-53 SI-7, CM-7
- References
- prelink(8), Linux man-pages
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWCore Dumps Not Restricted
HOST-BOOT-008
Checks that process core dumps are turned off through PAM limits, and through systemd-coredump where the kernel hands dumps to it.
Why it matters. A core dump is a copy of a program's memory, including passwords, keys and session tokens it held. On a server nobody debugs, dumps are only a leak waiting in /var/lib/systemd/coredump or the working directory. HOST-KRN-004 covers setuid programs; this check covers every process.
core dumps: No hard core 0 limit and no systemd-coredump Storage=none
kernel.core_pattern = core
- Fix
- Add * hard core 0 to /etc/security/limits.conf (or a file in limits.d), set Storage=none and ProcessSizeMax=0 in the [Coredump] section of /etc/systemd/coredump.conf, and keep fs.suid_dumpable = 0.
- Verify
grep -E '^\*\s+hard\s+core\s+0' /etc/security/limits.conf /etc/security/limits.d/*; grep -E '^(Storage|ProcessSizeMax)' /etc/systemd/coredump.conf; cat /proc/sys/kernel/core_pattern
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-528, NIST 800-53 SI-11, CM-6, AC-6
- References
- limits.conf(5), Linux-PAM
coredump.conf(5), systemd
Linux kernel documentation, /proc/sys/kernel
- Learn
- P17: Kernel, Filesystem and Boot Hardening (offline:
openvapt learn P17)
- Source
internal/checks/host/boot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDocker Container Logs Have No Size Limit
HOST-CTR-005
Checks whether the Docker daemon's default log driver caps log file size and rotation.
Why it matters. With the default json-file driver and no max-size, a chatty or attacked container can fill the disk with its own logs and take the host and every other container down. Bounded, rotated logs also keep evidence manageable for investigations.
/etc/docker/daemon.json: Container logs are unbounded
daemon log-driver json-file (default) has no max-size
3f2a9c1d8e7b: json-file logging without max-size
- Fix
- Add to /etc/docker/daemon.json: "log-driver": "json-file", "log-opts": {"max-size": "10m", "max-file": "3"} (or use journald) and restart Docker; recreate containers that set their own LogConfig.
- Verify
docker info --format '{{.LoggingDriver}}' ; grep -A3 log-opts /etc/docker/daemon.json
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-779, CWE-770, NIST 800-53 AU-4, SC-5, CM-6
- References
- Docker documentation, Configure logging drivers
NIST SP 800-190, Application Container Security Guide
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDocker Userland Proxy Enabled
HOST-CTR-006
Checks whether the Docker daemon still uses the docker-proxy userland process for published ports.
Why it matters. The userland proxy is a root process per published port that exists only for an old loopback edge case. Hairpin NAT does the same job in the kernel with less code running as root and fewer processes to crash or exploit.
/etc/docker/daemon.json: userland-proxy is not false
- Fix
- Add "userland-proxy": false to /etc/docker/daemon.json and restart Docker; test that published ports still answer from the host itself.
- Verify
ps -C docker-proxy should list nothing after containers are recreated.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7, CM-6
- References
- Docker documentation, dockerd daemon reference
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDocker Default Ulimits Not Set
HOST-CTR-007
Checks whether the Docker daemon sets default ulimits (open files and processes) for containers.
Why it matters. Without default limits a container inherits the daemon's generous limits and can exhaust file descriptors or spawn processes until the host starves. Daemon-wide defaults protect every container that forgets to set its own.
/etc/docker/daemon.json: Default ulimits are not set
default-ulimits has no nofile
default-ulimits has no nproc
- Fix
- Add to /etc/docker/daemon.json: "default-ulimits": {"nofile": {"Name": "nofile", "Hard": 65536, "Soft": 32768}, "nproc": {"Name": "nproc", "Hard": 4096, "Soft": 2048}} and restart Docker; tune the numbers to your workloads.
- Verify
docker info | grep -A3 -i ulimit or docker run --rm alpine sh -c 'ulimit -n; ulimit -u' (your own test container)
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-770, NIST 800-53 SC-6, CM-6
- References
- Docker documentation, dockerd daemon reference
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDocker Content Trust Not Enabled
HOST-CTR-015
Checks whether DOCKER_CONTENT_TRUST=1 is set system-wide so that only signed images are pulled.
Why it matters. Without content trust, docker pull accepts whatever the registry or a tampering proxy returns for a tag. Signature verification makes a substituted image fail to pull instead of running as root on your host.
/etc/environment: DOCKER_CONTENT_TRUST is not set system-wide; unsigned images are accepted
- Fix
- Add DOCKER_CONTENT_TRUST=1 to /etc/environment (or a file in /etc/profile.d) and sign your own images with docker trust sign; images without signatures then need an explicit --disable-content-trust for a deliberate exception.
- Verify
grep -r DOCKER_CONTENT_TRUST /etc/environment /etc/profile.d
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-494, CWE-347, NIST 800-53 SI-7, CM-14
- References
- Docker documentation, Content trust in Docker
CIS Docker Benchmark (referenced by recommendation number)
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWVulnerability Snapshot Outdated or Test Data
HOST-CVE-003
Checks installed packages against an offline vulnerability snapshot.
Why it matters. Known vulnerable package versions can expose a server to documented attacks.
vulnerability snapshot: Snapshot date 2021-01-01. An outdated snapshot misses newer vulnerabilities.
- Fix
- Install the vendor security update. For a source build, run 'make vulndb' to embed a snapshot generated from OSV and CISA KEV, then rebuild.
- Verify
Re-run OpenVAPT after patching and confirm the finding is absent.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, RA-5
- References
- OSV vulnerability database
NVD
CISA KEV
- Learn
- P10: Vulnerability Management: CVE, OSV and Known Exploited Vulnerabilities (offline:
openvapt learn P10)
- Source
internal/checks/host/cve.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWTemporary Filesystems Allow Executables or Devices
HOST-FS-008
Checks that /tmp, /var/tmp and /dev/shm are mounted with nodev and nosuid.
Why it matters. World-writable temporary areas are where attackers drop tools. nosuid stops planted setuid programs working there, and nodev stops device files being created.
/tmp: /tmp is mounted without nodev, nosuid
options rw,relatime
/dev/shm: /dev/shm is mounted without nodev, nosuid
options rw
- Fix
- Mount the path as tmpfs or a separate filesystem with options nodev,nosuid (and noexec where software allows), for example via systemd tmp.mount or /etc/fstab, then remount.
- Verify
findmnt -no OPTIONS /tmp /var/tmp /dev/shm
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-276, NIST 800-53 CM-6, CM-7
- References
- mount(8), Linux man-pages (nodev, nosuid, noexec)
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDefault File Creation Mask Too Permissive
HOST-FS-009
Checks that the default umask makes new files unreadable to other users (027 or stricter).
Why it matters. With umask 022 every new file is readable by every local user, including configuration exports, reports and backups created by administrators.
/etc/login.defs: UMASK 022 lets other users read new files (recommended 027)
- Fix
- Set UMASK 027 in /etc/login.defs (and, if used, in /etc/profile or /etc/bash.bashrc).
- Verify
grep '^UMASK' /etc/login.defs
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-276, NIST 800-53 AC-6, CM-6
- References
- login.defs(5), Linux man-pages
umask(2), Linux man-pages
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOW/var/tmp Not a Separate Filesystem
HOST-FS-010
Checks that /var/tmp is its own mount (or a bind mount of /tmp) with nodev, nosuid and noexec.
Why it matters. /var/tmp is world-writable and survives reboots. On the root filesystem it can be filled to exhaust disk space, and it accepts planted device files and executables unless mounted with restricting options.
/var/tmp: /var/tmp is not a separate filesystem (it lives on the root filesystem)
- Fix
- Mount /var/tmp as a separate filesystem, or bind-mount it onto /tmp: /tmp /var/tmp none bind,nodev,nosuid,noexec 0 0 in /etc/fstab, then reboot or remount. Caution: /var/tmp is meant to survive reboots and some installers and databases run programs from it, so check what uses it before binding it to /tmp with noexec, and keep console access when editing /etc/fstab (a wrong line can stop the boot).
- Verify
findmnt -no TARGET,OPTIONS /var/tmp
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-276, NIST 800-53 CM-6, CM-7, SC-5
- References
- mount(8), Linux man-pages (nodev, nosuid, noexec)
proc(5), Linux man-pages (/proc/[pid]/mounts)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOW/home Not a Separate Filesystem With nodev
HOST-FS-011
Checks that user home directories live on their own mount with nodev (and nosuid where practical).
Why it matters. Users control the contents of /home. A separate mount stops a user filling the root filesystem, and nodev stops device files being created in a home directory to reach raw disks or memory.
/home: /home is not a separate filesystem (it lives on the root filesystem)
- Fix
- Place /home on its own partition or logical volume and add nodev,nosuid to its options in /etc/fstab; remount with: mount -o remount /home . Caution: moving /home to a new volume needs a backup, a maintenance window and console access; a wrong /etc/fstab line can stop the boot.
- Verify
findmnt -no TARGET,OPTIONS /home
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-276, NIST 800-53 CM-6, CM-7, SC-5
- References
- mount(8), Linux man-pages (nodev, nosuid, noexec)
proc(5), Linux man-pages (/proc/[pid]/mounts)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWLog Directories on the Root Filesystem
HOST-FS-012
Checks that /var/log (or /var) is a separate filesystem so runaway logging cannot fill the root disk.
Why it matters. Logs grow under attacker influence (failed logins, scanner noise). When they share the root filesystem, filling them stops the whole server, and when the disk is full new security events are lost.
/var/log: /var/log is not a separate filesystem (it lives on the root filesystem)
- Fix
- Place /var/log (and ideally /var/log/audit) on its own partition or logical volume, listed in /etc/fstab with nodev,nosuid,noexec. Caution: moving log directories needs a backup, a maintenance window and console access; stop the logging services while copying, and a wrong /etc/fstab line can stop the boot.
- Verify
findmnt -no TARGET,OPTIONS /var/log /var
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-770, NIST 800-53 CM-6, CM-7, SC-5
- References
- mount(8), Linux man-pages (nodev, nosuid, noexec)
proc(5), Linux man-pages (/proc/[pid]/mounts)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWTemporary Filesystems Allow Executables
HOST-FS-013
Checks that /tmp, /var/tmp and /dev/shm, where they are separate mounts, carry the noexec option.
Why it matters. Attackers who gain a foothold download tools into a world-writable temporary directory and run them from there. noexec makes that step fail and forces noisier workarounds.
/tmp: /tmp allows executables
options rw,relatime
/dev/shm: /dev/shm allows executables
options rw
- Fix
- Add noexec to the mount options of each temporary filesystem (systemd tmp.mount drop-in or /etc/fstab) and remount. Some package managers need exec on /tmp during installs; set TMPDIR for them rather than removing noexec.
- Verify
findmnt -no TARGET,OPTIONS /tmp /var/tmp /dev/shm
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-276, NIST 800-53 CM-6, CM-7
- References
- mount(8), Linux man-pages (nodev, nosuid, noexec)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWFiles With No Known Owner or Group
HOST-FS-015
Looks for files whose owner or group id no longer appears in /etc/passwd or /etc/group.
Why it matters. When an account is deleted, its files keep the numeric id. The next account created with that id silently inherits them, which can hand a new user old keys, scripts or cron jobs.
filesystem: 1 file(s) have an unknown owner or group
uid=1003 gid=1003 /opt/legacy/app.bin (no such user or group)
- Fix
- Decide who should own each listed file and apply chown <user>:<group> <path>, or remove files that belonged to a deleted account after checking their contents.
- Verify
find /etc /usr/local /opt /srv /var/www /home -xdev \( -nouser -o -nogroup \) should print nothing.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-282, NIST 800-53 AC-2, AC-6, CM-6
- References
- NIST SP 800-123, Guide to General Server Security
passwd(5), Linux man-pages
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWKernel Symbol Map or Initial RAM Disk Readable by Others
HOST-FS-018
Checks that /boot/System.map-* and the initial RAM disk images are not readable by every user.
Why it matters. System.map lists every kernel symbol address, which defeats kptr_restrict and helps kernel exploits. An initial RAM disk can embed network credentials, disk-unlock key files or custom scripts that should not be world-readable.
/boot: 1 boot file(s) are readable by others
0644 /boot/System.map-4.15.0-20-generic
- Fix
- chmod 600 /boot/System.map-* /boot/initrd* /boot/initramfs* and, on Debian family systems, set UMASK=0077 in /etc/initramfs-tools/initramfs.conf so new images are created private.
- Verify
stat -c '%a %n' /boot/System.map-* /boot/initrd*
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, CWE-732, NIST 800-53 AC-3, AC-6
- References
- Linux kernel documentation, /proc/sys/kernel
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWCron and At Not Restricted to Allowed Users
HOST-FS-019
Checks that cron.allow and at.allow exist, are private to root, and that the deny lists are not relied upon instead.
Why it matters. By default every local account may schedule jobs. A deny list only names known accounts; an allow list says exactly who may schedule, which is what least privilege asks for and what makes persistence by a compromised service account harder.
/etc/cron.allow: /etc/cron.allow does not exist; only /etc/cron.deny limits who may schedule cron jobs
/etc/at.allow: /etc/at.allow does not exist; only /etc/at.deny limits who may schedule at jobs
- Fix
- Create the allow lists: touch /etc/cron.allow /etc/at.allow && chmod 600 /etc/cron.allow /etc/at.allow && chown root:root /etc/cron.allow /etc/at.allow then add one user name per line for the accounts that need scheduling, and remove /etc/cron.deny and /etc/at.deny. Caution: once cron.allow exists, crontabs of users not listed stop running, so list every service and user account that has a crontab (ls /var/spool/cron/crontabs or /var/spool/cron) before creating it.
- Verify
stat -c '%a %U %n' /etc/cron.allow /etc/at.allow; ls /etc/cron.deny /etc/at.deny 2>&1
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-862, NIST 800-53 AC-6, CM-7
- References
- crontab(1), Linux man-pages (cron.allow and cron.deny)
at(1), Linux man-pages (at.allow and at.deny)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWCron Configuration Readable by Other Users
HOST-FS-020
Checks that /etc/crontab is mode 600 and the cron.d, cron.hourly, cron.daily, cron.weekly and cron.monthly directories are mode 700, all owned by root.
Why it matters. Readable cron configuration tells a local attacker exactly which scripts root runs and when, which is the reconnaissance step before replacing one of them. HOST-FS-005 stops writing; this check stops reading.
cron: 1 cron path(s) are readable by group or others
0666 uid=0 /etc/crontab
- Fix
- chown root:root /etc/crontab /etc/cron.* && chmod 600 /etc/crontab && chmod 700 /etc/cron.d /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly
- Verify
stat -c '%a %U %n' /etc/crontab /etc/cron.*
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, NIST 800-53 AC-3, AC-6
- References
- crontab(5), Linux man-pages
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWShell Profile Sets a Permissive File Creation Mask
HOST-FS-021
Checks that system-wide shell start-up files do not set a umask that leaves new files readable by every user.
Why it matters. A umask line in /etc/profile or /etc/bash.bashrc overrides the login.defs default for every interactive shell. Many distributions still ship umask 022 there, which makes every file an administrator creates readable by all local accounts.
/etc/profile: 1 shell file(s) set a umask that lets other users read new files
/etc/profile: umask 022
- Fix
- Change every umask 022 line in the listed files to umask 027, or remove the line so the login.defs value applies. Users start a new login shell to pick it up.
- Verify
grep -rn '^[[:space:]]*umask' /etc/profile /etc/bash.bashrc /etc/bashrc /etc/profile.d/ 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-276, NIST 800-53 AC-6, CM-6
- References
- umask(2), Linux man-pages
login.defs(5), Linux man-pages
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/files_mounts.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWNo Brute-Force Protection Service
HOST-IDS-001
Checks that a log-based intrusion prevention service (fail2ban, sshguard or CrowdSec) is running.
Why it matters. Internet-facing services receive constant guessing. Automatically blocking sources that fail repeatedly reduces noise and risk, and turns logs into active defence.
ids: No brute-force protection service is active
- Fix
- Install and enable one, for example: apt install fail2ban && systemctl enable --now fail2ban , with an sshd jail enabled.
- Verify
systemctl is-active fail2ban
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-307, OWASP A07:2021, NIST 800-53 SI-4, AC-7
- References
- fail2ban project
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P16: Logging, Auditing and Time (offline:
openvapt learn P16)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWKernel Pointers Exposed to Unprivileged Users
HOST-KRN-002
Checks that kernel memory addresses are hidden from normal users.
Why it matters. Leaked kernel addresses defeat kernel ASLR and are the first step of most local kernel exploits.
kernel.kptr_restrict: kernel.kptr_restrict = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.kptr_restrict = 1 then apply with: sysctl --system
- Verify
sysctl kernel.kptr_restrict should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, NIST 800-53 CM-6, SI-16
- References
- Linux kernel documentation, /proc/sys/kernel
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWKernel Log Readable by Unprivileged Users
HOST-KRN-003
Checks that only privileged users can read the kernel log (dmesg).
Why it matters. The kernel log can reveal addresses, hardware and driver details useful for local exploitation.
kernel.dmesg_restrict: kernel.dmesg_restrict = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.dmesg_restrict = 1 then apply with: sysctl --system
- Verify
sysctl kernel.dmesg_restrict should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/kernel
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSetuid Programs May Dump Core
HOST-KRN-004
Checks that privileged programs do not write core dumps.
Why it matters. A core dump of a setuid program can contain password hashes or keys and may be readable by the user who crashed it.
fs.suid_dumpable: fs.suid_dumpable = 2 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.suid_dumpable = 0 then apply with: sysctl --system
- Verify
sysctl fs.suid_dumpable should print 0.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-528, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/fs
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWIP Forwarding Enabled
HOST-KRN-005
Checks that the server does not route packets between networks.
Why it matters. A server that forwards packets can be used to pivot between networks. Only routers, VPN gateways and container hosts need this.
net.ipv4.ip_forward: net.ipv4.ip_forward = 1; container runtime detected (/var/run/docker.sock); forwarding is required by the runtime, but forwarded traffic is accepted by default. Set the FORWARD policy to DROP or add DOCKER-USER rules (see NET-FW-005)
container runtime detected (/var/run/docker.sock); forwarding is required by the runtime
iptables FORWARD policy ACCEPT
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.ip_forward = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv4.ip_forward should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWICMP Redirects Accepted
HOST-KRN-006
Checks that the kernel ignores ICMP redirect messages.
Why it matters. Forged ICMP redirects let an attacker on the local network reroute the server's traffic through themselves.
net.ipv4.conf.all.accept_redirects: net.ipv4.conf.all.accept_redirects = 1 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.accept_redirects = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv4.conf.all.accept_redirects should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSource-Routed Packets Accepted
HOST-KRN-007
Checks that the kernel drops packets that dictate their own route.
Why it matters. Source routing lets an attacker bypass network filtering and spoof trusted addresses.
net.ipv4.conf.all.accept_source_route: net.ipv4.conf.all.accept_source_route = 1 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.accept_source_route = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv4.conf.all.accept_source_route should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWTCP SYN Cookies Disabled
HOST-KRN-008
Checks that SYN cookies protect the server from SYN flood attacks.
Why it matters. Without SYN cookies a simple flood of half-open connections can make every service unreachable.
net.ipv4.tcp_syncookies: net.ipv4.tcp_syncookies = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.tcp_syncookies = 1 then apply with: sysctl --system
- Verify
sysctl net.ipv4.tcp_syncookies should print 1.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-770, NIST 800-53 SC-5, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWProcess Tracing Not Restricted
HOST-KRN-010
Checks that processes cannot attach a debugger to other processes of the same user.
Why it matters. Unrestricted ptrace lets any compromised process read the memory of others, for example to steal SSH agent keys or browser sessions.
kernel.yama.ptrace_scope: kernel.yama.ptrace_scope = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.yama.ptrace_scope = 1 then apply with: sysctl --system
- Verify
sysctl kernel.yama.ptrace_scope should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, Yama LSM
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSymlink Protection Disabled
HOST-KRN-011
Checks that the kernel blocks following symlinks owned by other users in world-writable sticky directories.
Why it matters. Without it, classic /tmp symlink races let local users trick root-run programs into overwriting files.
fs.protected_symlinks: fs.protected_symlinks = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_symlinks = 1 then apply with: sysctl --system
- Verify
sysctl fs.protected_symlinks should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-59, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/fs
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWHardlink Protection Disabled
HOST-KRN-012
Checks that users cannot create hard links to files they do not own.
Why it matters. Hard links to privileged files enable time-of-check races and keep vulnerable setuid binaries alive after updates.
fs.protected_hardlinks: fs.protected_hardlinks = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_hardlinks = 1 then apply with: sysctl --system
- Verify
sysctl fs.protected_hardlinks should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-59, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/fs
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWReverse Path Filtering Disabled
HOST-KRN-013
Checks that the kernel drops packets whose source address could not be routed back through the receiving interface.
Why it matters. Reverse path filtering blocks many spoofed-source packets used in attacks and amplification.
net.ipv4.conf.all.rp_filter: net.ipv4.conf.all.rp_filter = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.rp_filter = 1 then apply with: sysctl --system
- Verify
sysctl net.ipv4.conf.all.rp_filter should print 1.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMartian Packets Not Logged
HOST-KRN-014
Checks that packets with impossible source addresses are logged.
Why it matters. Logging martian packets helps detect spoofing and misrouting attempts.
net.ipv4.conf.all.log_martians: net.ipv4.conf.all.log_martians = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.log_martians = 1 then apply with: sysctl --system
- Verify
sysctl net.ipv4.conf.all.log_martians should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWServer Sends ICMP Redirects
HOST-KRN-015
Checks that the server does not send ICMP redirects, which only routers should do.
Why it matters. A non-router sending redirects can be abused to influence other hosts' routing on the local network.
net.ipv4.conf.all.send_redirects: 1 of 1 setting(s) differ from the hardened value 0
net/ipv4/conf/all/send_redirects = 1
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.send_redirects = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv4.conf.all.send_redirects should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWBroadcast ICMP Echo Answered
HOST-KRN-016
Checks that the server ignores ping requests sent to broadcast addresses.
Why it matters. Answering broadcast pings makes the server a participant in Smurf-style amplification attacks.
net.ipv4.icmp_echo_ignore_broadcasts: net.ipv4.icmp_echo_ignore_broadcasts = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.icmp_echo_ignore_broadcasts = 1 then apply with: sysctl --system
- Verify
sysctl net.ipv4.icmp_echo_ignore_broadcasts should print 1.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-406, NIST 800-53 SC-5, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWIPv6 ICMP Redirects Accepted
HOST-KRN-017
Checks that the kernel ignores IPv6 ICMP redirect messages.
Why it matters. Forged IPv6 redirects let an attacker on the local network reroute traffic through themselves.
net.ipv6.conf.all.accept_redirects: 1 of 1 setting(s) differ from the hardened value 0
net/ipv6/conf/all/accept_redirects = 1
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv6.conf.all.accept_redirects = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv6.conf.all.accept_redirects should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPerformance Events Open to Unprivileged Users
HOST-KRN-018
Checks that unprivileged users cannot use kernel performance events to observe the system.
Why it matters. Unrestricted perf events expose kernel and other processes' activity and have been used in local exploits.
kernel.perf_event_paranoid: kernel.perf_event_paranoid = 1 (hardened value: 2)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.perf_event_paranoid = 2 then apply with: sysctl --system
- Verify
sysctl kernel.perf_event_paranoid should print 2.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 CM-6, SI-16
- References
- Linux kernel documentation, /proc/sys/kernel
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMagic SysRq Key Enabled
HOST-KRN-019
Checks that the magic SysRq key combination is disabled or limited to keyboard synchronisation.
Why it matters. With SysRq enabled, anyone at a console or with access to /proc/sysrq-trigger can reboot the machine, kill every process or dump memory without logging in.
kernel.sysrq: kernel.sysrq = 1 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.sysrq = 0 then apply with: sysctl --system
- Verify
sysctl kernel.sysrq should print 0.
- CVSS v3.1
CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, Linux Magic System Request Key Hacks
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWFIFO Protection in Shared Directories Disabled
HOST-KRN-020
Checks that the kernel refuses to open FIFOs in world-writable sticky directories that another user owns.
Why it matters. A FIFO planted in /tmp can make a privileged program block or write into an attacker-controlled pipe, a classic step in local attacks.
fs.protected_fifos: fs.protected_fifos = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_fifos = 1 then apply with: sysctl --system
- Verify
sysctl fs.protected_fifos should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-59, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/fs
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWRegular File Protection in Shared Directories Disabled
HOST-KRN-021
Checks that the kernel refuses to open, with O_CREAT, regular files in world-writable sticky directories that another user owns.
Why it matters. Without it, a user can pre-create a file that a root-run script later writes to in /tmp, redirecting privileged output into a file they control.
fs.protected_regular: fs.protected_regular = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: fs.protected_regular = 1 then apply with: sysctl --system
- Verify
sysctl fs.protected_regular should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-59, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/fs
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWUnprivileged User Namespaces Allowed
HOST-KRN-022
Checks that normal users cannot create user namespaces, unless the server runs containers that need them.
Why it matters. User namespaces give an unprivileged process a fake root inside a namespace, which exposes kernel code paths that were written for root only; many local kernel exploits start by unsharing a user namespace.
kernel.unprivileged_userns_clone: kernel.unprivileged_userns_clone = 1 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing kernel.unprivileged_userns_clone = 0 (Debian family) or user.max_user_namespaces = 0 (other kernels), then apply with: sysctl --system. Rootless Docker, Podman, Flatpak and some browsers need user namespaces, so test first.
- Verify
sysctl kernel.unprivileged_userns_clone user.max_user_namespaces
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 CM-6, CM-7
- References
- user_namespaces(7), Linux man-pages
Kernel Self Protection Project, Recommended Settings
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWIPv6 Source-Routed Packets Accepted
HOST-KRN-023
Checks that the kernel drops IPv6 packets that dictate their own route.
Why it matters. IPv6 routing headers can be used to bypass filters and spoof trusted addresses, as source routing could in IPv4.
net.ipv6.conf.all.accept_source_route: 1 of 1 setting(s) differ from the hardened value 0
net/ipv6/conf/all/accept_source_route = 1
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv6.conf.all.accept_source_route = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv6.conf.all.accept_source_route should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSecure ICMP Redirects Accepted
HOST-KRN-024
Checks that the kernel also ignores ICMP redirects that come from its configured gateways.
Why it matters. An attacker who spoofs the gateway address can still reroute traffic unless secure redirects are off as well; a server has no reason to accept redirects at all.
net.ipv4.conf.all.secure_redirects: 1 of 1 setting(s) differ from the hardened value 0
net/ipv4/conf/all/secure_redirects = 1
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.conf.all.secure_redirects = 0 then apply with: sysctl --system
- Verify
sysctl net.ipv4.conf.all.secure_redirects should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWIPv6 Router Advertisements Accepted
HOST-KRN-025
Checks that the server does not reconfigure its IPv6 addresses and routes from router advertisements.
Why it matters. A rogue router advertisement on the local network can add a default route through an attacker's machine or assign addresses that bypass firewall rules; servers use static addressing.
net.ipv6.conf.all.accept_ra: 1 of 1 setting(s) differ from the hardened value 0
net/ipv6/conf/all/accept_ra = 1
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv6.conf.all.accept_ra = 0 then apply with: sysctl --system. Caution: on a host that gets its IPv6 address or default route from router advertisements (SLAAC, most cloud dual-stack VMs), accept_ra = 0 removes the IPv6 default route and cuts IPv6 connectivity. Use it only with static IPv6 addressing; otherwise keep accept_ra = 1 and rely on RA Guard on the switch or a host firewall rule for RA sources.
- Verify
sysctl net.ipv6.conf.all.accept_ra should print 0.
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-940, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWBogus ICMP Error Responses Logged
HOST-KRN-026
Checks that the kernel silently ignores malformed ICMP error responses instead of logging each one.
Why it matters. Logging every bogus ICMP error lets a remote sender fill the kernel log and disk at will, hiding real events among noise.
net.ipv4.icmp_ignore_bogus_error_responses: net.ipv4.icmp_ignore_bogus_error_responses = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.ipv4.icmp_ignore_bogus_error_responses = 1 then apply with: sysctl --system
- Verify
sysctl net.ipv4.icmp_ignore_bogus_error_responses should print 1.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-779, NIST 800-53 SC-7, CM-6
- References
- Linux kernel documentation, IP sysctl
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWKexec Kernel Replacement Allowed
HOST-KRN-027
Checks that a running kernel cannot be replaced at run time with kexec.
Why it matters. kexec lets root boot a different kernel without going through the firmware, which bypasses Secure Boot and module signing and is used to load unsigned kernels after a compromise.
kernel.kexec_load_disabled: kernel.kexec_load_disabled = 0 (hardened value: 1)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.kexec_load_disabled = 1 then apply with: sysctl --system. Caution: kexec_load_disabled = 1 also stops kdump from loading its crash kernel (kdump.service on the RHEL family, kdump-tools on Debian and Ubuntu), so crash dumps are lost. Keep it 0 where kdump is used, or accept that trade-off deliberately. The setting cannot be turned back off without a reboot.
- Verify
sysctl kernel.kexec_load_disabled should print 1.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:L/A:L
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 AC-6, CM-6
- References
- Kernel Self Protection Project, Recommended Settings
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWUnprivileged userfaultfd Allowed
HOST-KRN-028
Checks that only privileged processes can use userfaultfd.
Why it matters. userfaultfd lets a process pause the kernel at a chosen moment, which has turned many kernel race conditions into reliable local exploits.
vm.unprivileged_userfaultfd: vm.unprivileged_userfaultfd = 1 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: vm.unprivileged_userfaultfd = 0 then apply with: sysctl --system. Caution: unprivileged live migration tools (for example QEMU post-copy migration or CRIU run as a normal user) need userfaultfd; test those first.
- Verify
sysctl vm.unprivileged_userfaultfd should print 0.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 AC-6, CM-6
- References
- Linux kernel documentation, /proc/sys/vm
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWTTY Line Discipline Autoloading Enabled
HOST-KRN-029
Checks that unprivileged users cannot make the kernel load terminal line discipline modules.
Why it matters. Automatically loaded line disciplines have carried several exploitable kernel bugs; disabling autoload shrinks the kernel attack surface reachable from a normal shell.
dev.tty.ldisc_autoload: dev.tty.ldisc_autoload = 1 (hardened value: 0)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: dev.tty.ldisc_autoload = 0 then apply with: sysctl --system
- Verify
sysctl dev.tty.ldisc_autoload should print 0.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 AC-6, CM-6
- References
- Kernel Self Protection Project, Recommended Settings
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWBPF JIT Hardening Off
HOST-KRN-030
Checks that the BPF just-in-time compiler blinds constants in generated code for every user.
Why it matters. Without hardening, attacker-chosen constants in BPF programs land in executable kernel memory, a known technique for building kernel exploit payloads.
net.core.bpf_jit_harden: net.core.bpf_jit_harden = 0 (hardened value: 2)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: net.core.bpf_jit_harden = 2 then apply with: sysctl --system
- Verify
sysctl net.core.bpf_jit_harden should print 2.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 SC-7, CM-6
- References
- Kernel Self Protection Project, Recommended Settings
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWio_uring Open to Unprivileged Users
HOST-KRN-031
Checks that io_uring is disabled, or limited to privileged processes, on kernels that offer the setting.
Why it matters. io_uring has produced a long run of local privilege-escalation bugs; several large operators disable it for untrusted workloads.
kernel.io_uring_disabled: kernel.io_uring_disabled = 0 (hardened value: 2)
- Fix
- Create /etc/sysctl.d/60-openvapt-hardening.conf containing: kernel.io_uring_disabled = 2 then apply with: sysctl --system. Caution: applications that use io_uring for fast I/O (some databases, proxies and runtimes) fall back or fail to start when it is disabled; test them first, or use 1 to allow only a chosen group.
- Verify
sysctl kernel.io_uring_disabled should print 2.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-749, NIST 800-53 AC-6, CM-6
- References
- Kernel Self Protection Project, Recommended Settings
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P17: Kernel, Filesystem and Boot Hardening (offline: openvapt learn P17)
- Source
internal/checks/host/kernel.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSystem Logging Not Persistent
HOST-LOG-001
Checks that system logs survive a reboot (rsyslog/syslog-ng running, or a persistent journal).
Why it matters. Without persistent logs there is no evidence after an incident: no record of logins, sudo use, or service errors.
logging: No syslog daemon active and the journal is not persistent
- Fix
- Either install and enable rsyslog, or make the journal persistent: mkdir -p /var/log/journal && systemd-tmpfiles --create --prefix /var/log/journal && systemctl restart systemd-journald
- Verify
ls -d /var/log/journal or systemctl is-active rsyslog
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-9, AU-11
- References
- NIST SP 800-92, Guide to Computer Security Log Management
journald.conf(5)
- Learn
- P16: Logging, Auditing and Time (offline:
openvapt learn P16)
A4: Building Your Own Check (offline: openvapt learn A4)
- Source
internal/checks/host/logging_time.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSecurity Audit Daemon Not Running
HOST-LOG-002
Checks whether the Linux audit daemon (auditd) is running.
Why it matters. auditd records security-relevant events (changes to /etc/passwd, privilege use, file deletions) that ordinary logs miss, which incident responders rely on.
auditd: auditd is not active
- Fix
- Install the audit package (apt install auditd, or dnf install audit), enable it (systemctl enable --now auditd) and load a rule set appropriate to your policy.
- Verify
systemctl is-active auditd should print 'active'.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12
- References
- auditd(8), Linux man-pages
- Learn
- P16: Logging, Auditing and Time (offline:
openvapt learn P16)
- Source
internal/checks/host/logging_time.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSecurity Logs Readable by All Users
HOST-LOG-003
Checks that authentication and system logs are not world-readable.
Why it matters. Authentication logs contain user names, source addresses and sometimes passwords typed into the user name field. Only administrators should read them.
/var/log/auth.log: 1 file(s) are readable or writable by others
0644 /var/log/auth.log
- Fix
- chmod o-rwx /var/log/auth.log /var/log/secure /var/log/syslog /var/log/messages and set the matching create mode in /etc/logrotate.d.
- Verify
stat -c '%a %n' /var/log/auth.log /var/log/secure
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-532, NIST 800-53 AC-3, AC-6
- References
- NIST SP 800-92, Guide to Computer Security Log Management
- Learn
- P16: Logging, Auditing and Time (offline:
openvapt learn P16)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWLog Rotation Not Configured
HOST-LOG-004
Checks that logrotate (or journald size limits) keeps logs from filling the disk.
Why it matters. Unrotated logs eventually fill the disk and stop services, and an attacker can deliberately flood logs to cause that or to hide activity.
logs: No log rotation or journal size limit configured
- Fix
- Install logrotate (apt install logrotate / dnf install logrotate) and keep its daily timer enabled, or set SystemMaxUse= in journald.conf.
- Verify
ls /etc/logrotate.conf ; systemctl is-active logrotate.timer
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-770, NIST 800-53 AU-4, AU-11
- References
- logrotate(8), Linux man-pages
- Learn
- P16: Logging, Auditing and Time (offline:
openvapt learn P16)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWNo Mandatory Access Control Enforced
HOST-MAC-001
Checks that AppArmor or SELinux is enabled and enforcing.
Why it matters. Mandatory access control confines services even when they run as root, so a compromised web server or database cannot freely read or change the rest of the system.
mac: Neither SELinux (enforcing) nor AppArmor is active
- Fix
- Ubuntu/Debian: keep AppArmor enabled (systemctl enable --now apparmor) and its profiles in enforce mode. RHEL family: set SELINUX=enforcing in /etc/selinux/config and relabel. Test applications in permissive or complain mode first.
- Verify
getenforce or aa-status
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- High
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 AC-3(3), AC-6
- References
- Linux kernel documentation, Linux Security Module development and LSMs
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPassword Quality Module Not Enforced
HOST-PAM-001
Checks that new passwords pass through pam_pwquality with its dictionary check on, so dictionary words and user-name variants are rejected.
Why it matters. NIST SP 800-63B-4 asks verifiers to reject passwords found in dictionaries and blocklists rather than to impose composition rules. pam_pwquality does that work on Linux, but only when the password stack actually calls it and its dictcheck and usercheck options are not switched off. A minlen in pwquality.conf (HOST-PWD-003) does nothing if the module is never invoked.
pam: Password quality checks are not enforced
no pam_pwquality line in /etc/pam.d/common-password
dictcheck = 0 (/etc/security/pwquality.conf.d/10-lab.conf)
- Fix
- Install libpam-pwquality (Debian/Ubuntu) or libpwquality (RHEL family). Make sure the password stack has password requisite pam_pwquality.so retry=3 before pam_unix (pam-auth-update or authselect enable-feature with-pwquality), and in /etc/security/pwquality.conf keep dictcheck = 1 and usercheck = 1 . Pair it with a breached-password blocklist where possible. Keep a root session open and test a login and a password change in a second session before closing it: a wrong PAM line can lock every user out.
- Verify
grep pam_pwquality /etc/pam.d/common-password /etc/pam.d/system-auth 2>/dev/null; grep -rE '^(dictcheck|usercheck|enforcing)' /etc/security/pwquality.conf /etc/security/pwquality.conf.d/
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-521, OWASP A07:2021, NIST 800-53 IA-5(1)
- References
- pwquality.conf(5), libpwquality, Debian trixie manual pages
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAccount Lockout Releases Too Quickly
HOST-PAM-002
Checks that a locked account stays locked for at least 15 minutes (or until an administrator unlocks it).
Why it matters. This check and HOST-PWD-004 split one control so a single root cause is never counted twice: HOST-PWD-004 covers whether lockout exists and its deny threshold (how many failures lock the account); this check covers only unlock_time (how long the lock lasts). How long the lock lasts decides whether it slows an attacker: pam_faillock's default unlock_time of 600 seconds lets guessing resume every ten minutes. Fifteen minutes or more, or 0 (manual unlock), makes online guessing impractical.
/etc/pam.d/common-auth: unlock_time=60 seconds (need 900 or more, or 0 for manual unlock)
- Fix
- In /etc/security/faillock.conf set unlock_time = 900 (or 0 to require an administrator to run faillock --reset), keeping deny between 3 and 10. Keep a root session open and test in a second session before closing the first: a wrong PAM line can lock every user out, and unlock_time = 0 means locked accounts, administrators included, wait for faillock --reset.
- Verify
grep -E 'unlock_time' /etc/security/faillock.conf /etc/pam.d/common-auth /etc/pam.d/system-auth 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-307, OWASP A07:2021, NIST 800-53 AC-7
- References
- pam_faillock(8), Linux-PAM
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWsu Not Restricted to an Administrative Group
HOST-PAM-003
Checks that only members of a named group (wheel or sudo) may use su to become another user.
Why it matters. Without pam_wheel, every local account, including a compromised web service user, can run su and start guessing the root password. Restricting su to an administrative group removes that path and leaves sudo, which logs each command, as the way to gain privilege.
/etc/pam.d/su: No active pam_wheel line: any user may attempt su
- Fix
- In /etc/pam.d/su uncomment or add auth required pam_wheel.so use_uid group=sudo (group=wheel on the RHEL family), and make sure the group contains only administrators. Caution: add every administrator who uses su to that group first and test from a second session, or they lose su access.
- Verify
grep -E '^auth\s+required\s+pam_wheel.so' /etc/pam.d/su
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-250, CWE-862, NIST 800-53 AC-6(2), AC-3
- References
- pam_wheel(8), Linux-PAM
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPassword History Not Enforced
HOST-PAM-004
Checks that PAM remembers at least the last 5 passwords so a changed password cannot be changed straight back.
Why it matters. When a password must be changed after a suspected compromise, the point is lost if the user can set the old one again. pam_pwhistory (or pam_unix remember=) keeps recent hashes and refuses reuse. Five is a common minimum.
/etc/pam.d/common-password: No remember= setting: old passwords can be reused at once
- Fix
- Add password required pam_pwhistory.so remember=5 use_authtok before pam_unix in the password stack (pam-auth-update on Debian/Ubuntu, authselect enable-feature with-pwhistory on the RHEL family), or set remember = 5 in /etc/security/pwhistory.conf. Keep a root session open and test a password change in a second session before closing it: a wrong PAM line can block password changes or logins.
- Verify
grep -E 'remember' /etc/pam.d/common-password /etc/pam.d/system-auth /etc/security/pwhistory.conf 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-262, OWASP A07:2021, NIST 800-53 IA-5(1)
- References
- pam_pwhistory(8), Linux-PAM
pam_unix(8), Linux-PAM
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMinimum Password Age Not Set
HOST-PAM-005
Checks that a password cannot be changed again on the same day it was set.
Why it matters. Password history (HOST-PAM-004) only works if users cannot cycle through several changes in a minute to get back to a favourite password. PASS_MIN_DAYS 1 closes that loop with no real cost to users.
/etc/login.defs: PASS_MIN_DAYS 0 (1 or more)
- Fix
- Set PASS_MIN_DAYS 1 in /etc/login.defs, and for existing accounts chage --mindays 1 <user> .
- Verify
grep '^PASS_MIN_DAYS' /etc/login.defs
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-262, OWASP A07:2021, NIST 800-53 IA-5(1)
- References
- login.defs(5), Linux man-pages
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWInactive Accounts Never Locked
HOST-PAM-007
Checks that new accounts are set to lock automatically after a password has been expired and unused for at most 30 days.
Why it matters. Accounts of people who left, or test accounts nobody remembers, stay usable for years unless something disables them. The INACTIVE default in /etc/default/useradd makes new accounts lock themselves a fixed number of days after their password expires.
/etc/default/useradd: INACTIVE=-1 (need 0 to 30)
- Fix
- useradd -D -f 30 (writes INACTIVE=30 to /etc/default/useradd), and for existing accounts chage --inactive 30 <user> . Caution: this locks accounts whose password has expired for 30 days, so exempt break-glass and rarely used administrator accounts or keep their passwords current.
- Verify
useradd -D | grep INACTIVE
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-262, NIST 800-53 AC-2(3)
- References
- useradd(8), Linux man-pages (default INACTIVE value)
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWNo Shell Idle Timeout
HOST-PAM-009
Checks that interactive shells log out after at most 15 minutes without input (TMOUT).
Why it matters. A root shell left open on an unattended terminal, or a forgotten SSH session on a shared workstation, is free privilege for whoever sits down next. TMOUT makes bash and ksh close an idle session automatically; readonly stops users from switching it off.
TMOUT: No TMOUT is set in the shell start-up files
- Fix
- Create /etc/profile.d/99-tmout.sh with TMOUT=900 ; readonly TMOUT ; export TMOUT (mode 644, owned by root). Sessions that must stay open should use a multiplexer such as tmux with its own lock, not a longer TMOUT. Caution: a readonly TMOUT ends idle interactive shells, including foreground jobs left waiting in them; run long jobs under nohup, systemd-run or a multiplexer.
- Verify
grep -rE '^\s*(readonly |export )?TMOUT=' /etc/profile /etc/profile.d/ /etc/bash.bashrc /etc/bashrc 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-613, OWASP A07:2021, NIST 800-53 AC-11, AC-12
- References
- Bash Reference Manual, Bash Variables (TMOUT)
NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMany Old Kernels Retained
HOST-PKG-004
Checks that no more than three kernel versions are installed.
Why it matters. Every installed kernel stays bootable from the boot menu, with every vulnerability it had. Old kernels also fill /boot until updates fail to install, which is a quiet way to stop receiving kernel patches. Keeping the running kernel plus one or two fallbacks is enough.
kernels: 5 kernel versions installed (recommended at most 3)
4.15.0-100-generic
4.15.0-112-generic
4.15.0-120-generic
4.15.0-140-generic
4.15.0-150-generic
- Fix
- Debian/Ubuntu: apt-get autoremove --purge removes kernels outside the keep list. RHEL family: set installonly_limit=3 in /etc/dnf/dnf.conf and run dnf remove --oldinstallonly . Never remove the running kernel (uname -r).
- Verify
dpkg -l 'linux-image-*' | grep '^ii' or rpm -q kernel kernel-core
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N
- Category
- Patch and Vulnerability Management
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, CM-7
- References
- NIST SP 800-40 Rev. 4, Guide to Enterprise Patch Management Planning
apt-get(8), Debian trixie manual pages (autoremove)
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/pkg_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPackage Lists Not Refreshed Automatically
HOST-PKG-006
Checks that the package manager downloads fresh repository metadata on a schedule, so pending updates can be seen at all.
Why it matters. apt and dnf only know about updates listed in the metadata they last downloaded. Without a timer that refreshes it, HOST-PKG-001 and the administrator's own apt list --upgradable both report a clean system that is weeks behind. The refresh is read-only and separate from installing anything.
apt: Package lists are not refreshed automatically (no APT::Periodic::Update-Package-Lists and apt-daily.timer not enabled)
- Fix
- Debian/Ubuntu: create /etc/apt/apt.conf.d/20auto-upgrades with APT::Periodic::Update-Package-Lists "1"; (dpkg-reconfigure unattended-upgrades writes it) and systemctl enable apt-daily.timer . RHEL family: systemctl enable --now dnf-makecache.timer .
- Verify
systemctl is-enabled apt-daily.timer or systemctl is-enabled dnf-makecache.timer
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Patch and Vulnerability Management
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2, RA-5
- References
- Debian, UnattendedUpgrades (APT::Periodic settings)
NIST SP 800-40 Rev. 4, Guide to Enterprise Patch Management Planning
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/pkg_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWShort Minimum Password Length
HOST-PWD-003
Checks that the password quality policy requires at least 15 characters.
Why it matters. Length is the single most effective property against guessing. NIST SP 800-63B-4 (2025) requires at least 15 characters for a password used as the only authentication factor, and recommends allowing long passphrases.
/etc/security/pwquality.conf: minlen = 8 (NIST SP 800-63B-4 requires 15 or more for single-factor passwords)
- Fix
- Install libpam-pwquality (Debian/Ubuntu) or libpwquality (RHEL family) and set minlen = 15 (or more) in /etc/security/pwquality.conf.
- Verify
grep -r '^minlen' /etc/security/pwquality.conf /etc/security/pwquality.conf.d/
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-521, OWASP A07:2021, NIST 800-53 IA-5(1)
- References
- pwquality.conf(5), libpwquality, Debian trixie manual pages
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSSH X11 Forwarding Enabled
HOST-SSH-005
Checks whether SSH forwards graphical X11 sessions.
Why it matters. Servers rarely need X11. Forwarding it exposes the connecting user's display to anyone with root on the server, and widens the attack surface of sshd.
sshd: X11 forwarding is enabled
x11forwarding yes
- Fix
- Set X11Forwarding no in /etc/ssh/sshd_config and reload sshd.
- Verify
sshd -T | grep -i x11forwarding should print 'no'.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
- Source
internal/checks/host/ssh_misc.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSSH Allows Many Authentication Attempts
HOST-SSH-006
Checks whether MaxAuthTries is above 4.
Why it matters. Each connection may try this many passwords or keys. A low limit slows guessing and makes attacks show up in the logs sooner.
sshd: MaxAuthTries is 10 (recommended 4 or lower)
- Fix
- Set MaxAuthTries 4 (or lower) in /etc/ssh/sshd_config and reload sshd. Consider fail2ban or sshguard for rate limiting.
- Verify
sshd -T | grep -i maxauthtries should print 4 or lower.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-307, NIST 800-53 AC-7
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/ssh_misc.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSSH Authentication Controls Too Permissive
HOST-SSH-008
Checks effective SSH authentication method and login grace settings.
Why it matters. Long login windows and unconstrained single-factor authentication give online guessing and stolen credentials more opportunity.
sshd: SSH authentication restrictions are too permissive
logingracetime 120
password or keyboard-interactive login enabled without a second factor (authenticationmethods (not set, default applies))
- Fix
- Set LoginGraceTime 60 or lower and choose AuthenticationMethods appropriate to the server, such as publickey, then restrict access with AllowUsers or AllowGroups where practical.
- Verify
Use sshd -T -C for each allowed user and source context and inspect logingracetime, authenticationmethods, allowusers and allowgroups.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-307, CWE-308, NIST 800-53 AC-7, IA-2
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/ssh_forwarding.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSSH Logging Level Too Low
HOST-SSH-012
Checks that sshd logs at INFO or VERBOSE level.
Why it matters. QUIET, FATAL or ERROR levels drop login records, so failed and successful logins cannot be investigated. VERBOSE also records the key fingerprint used.
sshd: LogLevel quiet drops login records
- Fix
- Set LogLevel VERBOSE (or INFO) in /etc/ssh/sshd_config and reload sshd.
- Verify
sshd -T | grep -i loglevel
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-3
- References
- OpenBSD, sshd_config(5) manual page
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P16: Logging, Auditing and Time (offline: openvapt learn P16)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSSH Authorized Keys Without Restrictions or Protection
HOST-SSH-013
Checks root's authorized_keys for keys without from= or command= options, and every authorized_keys file for permissive modes.
Why it matters. A key in root's authorized_keys is a root password that never expires. Restricting it with from= (allowed source addresses) or command= (one fixed command) limits what a stolen key can do. An authorized_keys file that others can write lets them add their own key; one that others can read tells them which keys to steal.
authorized_keys: SSH authorized keys lack restrictions or protection
0644 /root/.ssh/authorized_keys is readable by others
/root/.ssh/authorized_keys: 1 root key(s) without from= or command= restrictions
- Fix
- Prefix each root key with options, for example from="203.0.113.0/24",no-port-forwarding,no-agent-forwarding or command="/usr/local/bin/backup",restrict ; chmod 600 ~/.ssh/authorized_keys and 700 ~/.ssh for every account. Prefer sudo from a personal account over direct root keys.
- Verify
cut -c1-40 /root/.ssh/authorized_keys ; stat -c '%a %n' /root/.ssh/authorized_keys /home/*/.ssh/authorized_keys
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-250, NIST 800-53 IA-5, AC-6, AC-17
- References
- sshd(8), AUTHORIZED_KEYS FILE FORMAT, OpenBSD manual pages
NIST IR 7966, Security of Interactive and Automated Access Management Using Secure Shell (SSH)
- Learn
- P2: SSH Security (offline:
openvapt learn P2)
P20: Secrets, Cron and Account Hygiene (offline: openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSudo Commands Not Logged to a Dedicated File
HOST-SUDO-001
Checks that sudo uses a pseudo-terminal and keeps its own log file.
Why it matters. Defaults use_pty stops background processes from a sudo session lingering after it ends. A dedicated logfile keeps an easily reviewed record of privileged commands.
/etc/sudoers: Missing: Defaults use_pty, Defaults logfile=
- Fix
- With visudo add: Defaults use_pty and Defaults logfile="/var/log/sudo.log"
- Verify
grep -rE 'use_pty|logfile' /etc/sudoers /etc/sudoers.d
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, NIST 800-53 AU-2, AU-12
- References
- sudoers(5) manual
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
P16: Logging, Auditing and Time (offline: openvapt learn P16)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWUnnecessary Legacy Services Running
HOST-SVC-001
Checks for desktop and legacy network services that servers rarely need.
Why it matters. Each running service adds attack surface. Zeroconf discovery, printing, RPC portmapping and inetd-style super-servers are common, long-forgotten exposures.
services: Unnecessary services are active
avahi-daemon
rpcbind
- Fix
- systemctl disable --now <service> for each listed service you do not need, or remove its package. Caution: check first that nothing depends on it (systemctl list-dependencies --reverse <service>) and keep console access when disabling network or remote-access services.
- Verify
systemctl is-active avahi-daemon cups rpcbind xinetd
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAvahi or CUPS Installed or Enabled
HOST-SVC-007
Checks whether zero-configuration discovery (Avahi) or the printing system (CUPS) is installed or enabled.
Why it matters. Avahi announces the machine and its services to the local network, and CUPS listens for print jobs and runs a web interface. Both are desktop features with a history of vulnerabilities and no purpose on a server. If this machine is one of the desktops and print servers that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 3 legacy service component(s) present
package avahi-daemon is installed
package cups is installed
unit avahi-daemon.service is enabled at boot
- Fix
- apt purge avahi-daemon cups cups-daemon or dnf remove avahi cups , and systemctl disable --now avahi-daemon.socket avahi-daemon.service cups.socket cups.service . Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l avahi-daemon cups cups-daemon 2>/dev/null | grep '^ii' ; systemctl is-enabled avahi-daemon.service avahi-daemon.socket cups.service cups.socket cups-browsed.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7, CM-7(1)
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWNFS Server or rpcbind Installed or Enabled
HOST-SVC-008
Checks whether the NFS server or the RPC port mapper (rpcbind) is installed or enabled.
Why it matters. NFS exports whole directory trees with trust based on client IP address and numeric user ids, and rpcbind tells any caller which RPC services are running. Unless this machine is a file server, both are attack surface with no benefit. The rpcbind package is often pulled in as a dependency and left running. If this machine is one of the file servers that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 2 legacy service component(s) present
package nfs-kernel-server is installed
package rpcbind is installed
- Fix
- apt purge nfs-kernel-server rpcbind or dnf remove nfs-utils rpcbind where NFS is not served, and systemctl disable --now nfs-server rpcbind.socket rpcbind.service . Where NFS is required, export read-only with root_squash to named hosts and firewall port 2049 and 111. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l nfs-kernel-server rpcbind 2>/dev/null | grep '^ii' ; systemctl is-enabled nfs-server.service rpcbind.service rpcbind.socket nfs-kernel-server.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-306, NIST 800-53 CM-7, CM-7(1)
- References
- NFS security, Linux kernel documentation (exports and rpcbind)
NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDHCP or DNS Server Installed or Enabled
HOST-SVC-009
Checks whether a DHCP server or an authoritative or recursive DNS server (BIND) is installed or enabled on a machine that is not a network server.
Why it matters. A rogue DHCP server hands out addresses and gateways to the whole network segment, and BIND is a large, privileged network service with a long vulnerability history. Both belong on dedicated infrastructure hosts. On a web or application server they are either forgotten or an attacker's foothold. If this machine is one of the dedicated network infrastructure hosts that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 1 legacy service component(s) present
package isc-dhcp-server is installed
- Fix
- apt purge isc-dhcp-server bind9 or dnf remove dhcp-server bind , and systemctl disable --now isc-dhcp-server named . If this machine is meant to be a DNS or DHCP server, record that in the suppression file and review NET-SVC findings for its configuration. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l isc-dhcp-server dhcp-server kea-dhcp4-server kea-dhcp6-server bind9 bind bind9-dnsutils-server 2>/dev/null | grep '^ii' ; systemctl is-enabled isc-dhcp-server.service dhcpd.service kea-dhcp4-server.service named.service bind9.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7, CM-7(1)
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSamba File Server Installed or Enabled
HOST-SVC-010
Checks whether the Samba SMB file server is installed or set to start at boot.
Why it matters. SMB file sharing exposes files, printers and authentication to the network and has been the target of worms and several critical remote code execution flaws. It is needed only on file servers for Windows-style clients. If this machine is one of the file servers that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 1 legacy service component(s) present
package samba is installed
- Fix
- apt purge samba or dnf remove samba , and systemctl disable --now smbd nmbd (smb nmb on the RHEL family). Where it is required, disable SMB1, require signing and restrict shares to named users. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l samba 2>/dev/null | grep '^ii' ; systemctl is-enabled smbd.service nmbd.service smb.service nmb.service samba.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7, CM-7(1)
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSNMP Agent or Squid Proxy Installed or Enabled
HOST-SVC-011
Checks whether an SNMP agent or the Squid caching proxy is installed or enabled.
Why it matters. SNMP v1 and v2c authenticate with a community string sent in clear text (public and private are the usual defaults) and reveal routing tables, interfaces, processes and installed software. Squid turns the machine into a relay for other traffic and is often left open. Both need a deliberate configuration to be anything but a liability. If this machine is one of the monitored hosts using SNMPv3 and dedicated proxy servers that legitimately run it, record the reason in the suppression file so the finding stays visible but accepted.
services: 1 legacy service component(s) present
package snmpd is installed
- Fix
- apt purge snmpd squid or dnf remove net-snmp squid , and systemctl disable --now snmpd squid . If monitoring needs SNMP, use version 3 with authPriv and bind the agent to the management network. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l snmpd net-snmp squid squid-openssl 2>/dev/null | grep '^ii' ; systemctl is-enabled snmpd.service squid.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-319, NIST 800-53 CM-7, CM-7(1)
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWinetd Super-Server Installed or Enabled
HOST-SVC-012
Checks whether xinetd or another inetd super-server is installed or enabled.
Why it matters. inetd-style super-servers exist to launch small network services (echo, chargen, telnet, tftp) on demand from a shared configuration. On a systemd machine every service they would start has a native unit; the super-server adds a second, rarely reviewed, place where network services are switched on.
services: 2 legacy service component(s) present
package xinetd is installed
unit xinetd.service is enabled at boot
- Fix
- apt purge xinetd openbsd-inetd or dnf remove xinetd , and systemctl disable --now xinetd . Review /etc/inetd.conf and /etc/xinetd.d first so nothing needed disappears. Before removing a package, check that no application on this machine or the network still uses the service, and keep console access when the service is remote-access related.
- Verify
dpkg -l xinetd openbsd-inetd inetutils-inetd 2>/dev/null | grep '^ii' ; systemctl is-enabled xinetd.service inetd.service openbsd-inetd.service inetutils-inetd.service 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 CM-7, CM-7(1)
- References
- NIST SP 800-123, Guide to General Server Security
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/legacy_services.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWCustom Services Lack Sandboxing
HOST-SYSD-002
Checks whether custom long-running services use systemd's basic sandboxing options.
Why it matters. systemd can confine a service with a few lines: block privilege gain through setuid programs, mount the operating system read-only, give it a private /tmp and hide home directories. These limit what an attacker can do after exploiting the service, at almost no cost.
systemd units: 4 custom service(s) lack basic sandboxing
shop-admin.service is missing: NoNewPrivileges=yes, ProtectSystem=strict, PrivateTmp=yes, ProtectHome=yes
shop-api.service is missing: NoNewPrivileges=yes, ProtectSystem=strict, PrivateTmp=yes, ProtectHome=yes
shop-reports.service is missing: NoNewPrivileges=yes, ProtectSystem=strict, PrivateTmp=yes, ProtectHome=yes
shop-worker.service is missing: NoNewPrivileges=yes, ProtectSystem=strict, PrivateTmp=yes, ProtectHome=yes
- Fix
- Add the missing lines with systemctl edit <unit> (a drop-in), for example NoNewPrivileges=yes, ProtectSystem=strict, ReadWritePaths=/var/lib/<app>, PrivateTmp=yes, ProtectHome=yes. Restart the service and test it; add ReadWritePaths= for every folder the app must write. systemd-analyze security <unit> suggests further options.
- Verify
systemd-analyze security <unit> shows a lower exposure score, and the service still works.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-250, CWE-653, NIST 800-53 CM-6, SC-39, AC-6
- References
- systemd.exec(5), execution environment configuration
systemd-analyze(1), security verb
- Learn
- P11: Service Hardening With systemd (offline:
openvapt learn P11)
- Source
internal/checks/host/systemd.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWTime Synchronisation Not Active
HOST-TIME-001
Checks that the clock is kept in sync (chrony, ntpd or systemd-timesyncd).
Why it matters. Accurate time is needed to correlate logs during an investigation, and TLS certificates and one-time-password codes fail when the clock drifts.
time: No time synchronisation service is active
- Fix
- Enable one time service, for example: systemctl enable --now systemd-timesyncd (or install chrony).
- Verify
timedatectl should show 'System clock synchronized: yes'.
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, NIST 800-53 AU-8
- References
- NIST SP 800-53 Rev. 5, Security and Privacy Controls
- Learn
- P16: Logging, Auditing and Time (offline:
openvapt learn P16)
- Source
internal/checks/host/logging_time.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWAutomatic Security Updates Not Configured
HOST-UPD-001
Checks that security updates are installed automatically.
Why it matters. Many compromises use vulnerabilities fixed days or weeks earlier. Automatic security updates close that window without relying on someone remembering.
updates: No automatic security update mechanism is enabled
- Fix
- Debian/Ubuntu: apt install unattended-upgrades && dpkg-reconfigure -plow unattended-upgrades . RHEL family: dnf install dnf-automatic, set apply_updates = yes and upgrade_type = security, then systemctl enable --now dnf-automatic.timer .
- Verify
Re-run this check.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Patch and Vulnerability Management
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1104, OWASP A06:2021, NIST 800-53 SI-2(2)
- References
- Debian, UnattendedUpgrades
NIST SP 800-40 Rev. 4
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
- Source
internal/checks/host/hardening.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWSystem Accounts With Login Shells
HOST-USR-005
Checks that service accounts (UID below UID_MIN, usually 1000, other than root) cannot log in interactively.
Why it matters. Service accounts should never need a shell. A login shell gives an attacker who compromises the service, or guesses its password, an interactive foothold.
/etc/passwd: System accounts have login shells
daemon (/bin/bash)
- Fix
- usermod -s /usr/sbin/nologin <account> for each listed account (use /sbin/nologin on RHEL family).
- Verify
awk -F: '$3>0 && $3<1000 {print $1, $7}' /etc/passwd
- CVSS v3.1
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 AC-2, CM-7
- References
- nologin(8), Linux man-pages
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWHome Directories Accessible to Other Users
HOST-USR-010
Checks that the home directory of each interactive account denies read, write and execute to others.
Why it matters. Home directories hold shell history, SSH keys, application configuration and downloads. With others allowed in, any account on the machine can read another user's history and keys or, with write access, plant a .bashrc that runs when that user logs in.
/home: Home directories are accessible to other users
0755 /home/deploy (deploy) is accessible to others
- Fix
- chmod 750 /home/<user> for each listed account (700 if group access is not needed), and set HOME_MODE 0750 in /etc/login.defs or DIR_MODE=0750 in /etc/adduser.conf so new accounts start that way.
- Verify
stat -c '%a %n' /home/* shows 750 or 700.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Category
- Access Control
- Effort
- Low
- Confidence
- High
- Standards
- CWE-732, CWE-276, NIST 800-53 AC-3, AC-6
- References
- NIST SP 800-123, Guide to General Server Security
login.defs(5), Linux man-pages
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
P20: Secrets, Cron and Account Hygiene (offline: openvapt learn P20)
- Source
internal/checks/host/hygiene.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMySQL Error Log Not Configured
NET-DB-017
log_error is not set, so server errors, failed logins and startup warnings go to the console or syslog without a dedicated, retained file.
Why it matters. The error log is the first place to see authentication failures, crashes and plugin warnings. A named file with rotation makes those events available to incident response and to the audit checks that read it.
/etc/mysql/mysql.conf.d/mysqld.cnf: log_error is not set, so server errors, failed logins and startup warnings go to the console or syslog without a dedicated, retained file.
log_error is not set in the option files
- Fix
- Add log_error = /var/log/mysql/error.log under [mysqld], make the folder writable by the mysql user, and add a logrotate rule.
- Verify
SHOW VARIABLES LIKE 'log_error'; should print the file path.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, ASVS 7.1.1, NIST 800-53 AU-2, AU-12
- References
- MySQL 8.4 Reference Manual, The Error Log
MySQL 8.4 Reference Manual, Server System Variables
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMySQL Resolves Client Host Names
NET-DB-018
skip-name-resolve is not set, so grants that name hosts depend on DNS answers and every connection waits on a reverse lookup.
Why it matters. Host-based grants that trust names can be satisfied by whoever controls DNS or the resolver path. With skip-name-resolve the server matches IP addresses only, which is both faster and not spoofable through DNS. Grants that use host names must be rewritten first.
/etc/mysql/mysql.conf.d/mysqld.cnf: skip-name-resolve is not set, so grants that name hosts depend on DNS answers and every connection waits on a reverse lookup.
skip-name-resolve is not set; the default is OFF
- Fix
- Rewrite grants that use host names to IP addresses or '%', then add skip-name-resolve under [mysqld] and restart in a maintenance window.
- Verify
SHOW VARIABLES LIKE 'skip_name_resolve'; should print ON.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Data Services
- Effort
- Low
- Confidence
- High
- Standards
- CWE-350, CWE-290, OWASP A05:2021, ASVS 14.1.3, NIST 800-53 CM-6, IA-3
- References
- MySQL 8.4 Reference Manual, skip_name_resolve
MySQL 8.4 Reference Manual, Security Guidelines
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPostgreSQL Connection Logging Off
NET-DB-021
log_connections and log_disconnections are off, so successful logins leave no record.
Why it matters. Failed logins are logged by default, but successful ones are not. Knowing which role connected from where and for how long is the base evidence for spotting credential misuse and for any later investigation.
/etc/postgresql/16/main/postgresql.conf: log_connections and log_disconnections are off, so successful logins leave no record.
log_connections is not set; the default is off
- Fix
- Set log_connections = on and log_disconnections = on in postgresql.conf and reload. On PostgreSQL 18 and newer, log_connections accepts a list such as receipt,authentication,authorization .
- Verify
SHOW log_connections; should print on (or a non-empty list).
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N
- Category
- Logging and Monitoring
- Effort
- Low
- Confidence
- High
- Standards
- CWE-778, OWASP A09:2021, ASVS 7.1.3, NIST 800-53 AU-2, AU-12, AC-2(4)
- References
- PostgreSQL, Error Reporting and Logging
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P8: Data Services: Databases, File Shares, DNS and Mail (offline: openvapt learn P8)
P19: Database, Mail and DNS Hardening (offline: openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWBIND Version String Disclosed
NET-DNS-001
named.conf has no version statement in options, so a CHAOS class query for version.bind returns the exact BIND release.
Why it matters. The version string lets an attacker match advisories to the server without any guessing. Replacing it costs nothing and does not break resolution.
/etc/bind/named.conf.options: named.conf has no version statement in options, so a CHAOS class query for version.bind returns the exact BIND release.
no version statement in options
- Fix
- Add version "not disclosed"; inside the options block and run named-checkconf, then rndc reconfig.
- Verify
dig @127.0.0.1 version.bind txt chaos +short should print the chosen string.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, NIST 800-53 CM-6, SI-11
- References
- BIND 9 Administrator Reference Manual, version statement
BIND 9 Administrator Reference Manual, options
- Learn
- P19: Database, Mail and DNS Hardening (offline:
openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWFirewall Rules Open Ports With No Service
NET-FW-004
Checks for firewall allow rules whose port has no listening service on this machine.
Why it matters. Stale rules are holes waiting for a service. Anything later started on that port, by an administrator, a package or an attacker, becomes reachable without anyone deciding it should be. Rule sets also become impossible to review when they no longer match reality.
firewall: 1 allow rule(s) open ports with no service
port 8443/tcp allowed by iptables but nothing listens on it: -A INPUT -p tcp -m tcp --dport 8443 -j ACCEPT
- Fix
- Remove rules for services that no longer exist (ufw status numbered, then ufw delete <n>), or note why a rule must stay. Review the firewall whenever a service is retired.
- Verify
Re-run this check; every allowed port should have a listening service.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Network Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 SC-7, CM-7, CM-3
- References
- NIST SP 800-41 Rev. 1, Guidelines on Firewalls and Firewall Policy
- Learn
- P3: Network Exposure and Firewalls (offline:
openvapt learn P3)
P12: Firewall Policy Versus What Is Listening (offline: openvapt learn P12)
- Source
internal/checks/network/firewall_exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPostfix VRFY Command Enabled
NET-MAIL-003
disable_vrfy_command is not yes, so anyone who connects can ask the server whether a mailbox exists.
Why it matters. VRFY lets a sender enumerate valid addresses one by one, which feeds spam lists and targeted phishing. Legitimate mail flow never needs it.
/etc/postfix/main.cf: disable_vrfy_command is not yes, so anyone who connects can ask the server whether a mailbox exists.
disable_vrfy_command is not set; the default is no
- Fix
- Add disable_vrfy_command = yes to main.cf and postfix reload.
- Verify
postconf disable_vrfy_command should print yes; an authorised VRFY postmaster over a local SMTP session should return 502.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-204, OWASP A05:2021, NIST 800-53 CM-7, SI-11
- References
- Postfix, disable_vrfy_command
RFC 5321, Simple Mail Transfer Protocol, section 7.3
- Learn
- P19: Database, Mail and DNS Hardening (offline:
openvapt learn P19)
- Source
internal/checks/network/data_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWApache Reveals Version in Header and Footer
WEB-APA-001
ServerTokens is not Prod or ServerSignature is On, so responses and error pages show the Apache version and modules.
Why it matters. The Server header and the signature line on error pages tell an attacker the exact release and loaded modules. Hiding them removes a free hint; patching remains the real fix.
/etc/apache2/apache2.conf: ServerTokens is not Prod or ServerSignature is On, so responses and error pages show the Apache version and modules.
/etc/apache2/conf-enabled/security.conf: ServerTokens OS
/etc/apache2/conf-enabled/security.conf: ServerSignature On
- Fix
- Set ServerTokens Prod and ServerSignature Off in apache2.conf or conf-enabled/security.conf (Debian) or httpd.conf (RHEL), then apachectl configtest and reload.
- Verify
curl -sI https://<site>/ | grep -i '^server:' should print Server: Apache with nothing after it.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.3, NIST 800-53 CM-6, SI-11
- References
- Apache HTTP Server, ServerTokens directive
OWASP WSTG-INFO-02, Fingerprint Web Server
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWApache TRACE Method Enabled
WEB-APA-002
TraceEnable is not set to Off, so the HTTP TRACE method echoes requests back to the client.
Why it matters. TRACE reflects request headers, including cookies and authorisation, which older cross-site tracing attacks used to read them from the browser. No production site needs it.
/etc/apache2/apache2.conf: TraceEnable is not set to Off, so the HTTP TRACE method echoes requests back to the client.
/etc/apache2/conf-enabled/security.conf: TraceEnable On
- Fix
- Add TraceEnable Off to the server configuration and reload.
- Verify
curl -s -o /dev/null -w '%{http_code}' -X TRACE https://<site>/ should print 405.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-749, OWASP A05:2021, ASVS 14.5.1, NIST 800-53 CM-7
- References
- Apache HTTP Server, TraceEnable directive
OWASP WSTG-CONF-06, Test HTTP Methods
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWApache AllowOverride All Permits .htaccess Control
WEB-APA-004
A Directory block sets AllowOverride All, so any .htaccess file under it can change handlers, options and access rules.
Why it matters. With AllowOverride All, whoever can write a file into the document root (an upload bug, a compromised CMS) can turn images into executable scripts or lift access controls. Limiting overrides keeps those decisions in root-owned configuration.
/etc/apache2/apache2.conf: A Directory block sets AllowOverride All, so any .htaccess file under it can change handlers, options and access rules.
/etc/apache2/apache2.conf: AllowOverride All
- Fix
- Set AllowOverride None and move needed rules into the vhost, or allow only what the application needs, for example AllowOverride FileInfo Indexes Limit for WordPress permalinks.
- Verify
grep -rn AllowOverride /etc/apache2 /etc/httpd 2>/dev/null should show no All.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-15, CWE-1188, OWASP A05:2021, ASVS 14.1.1, NIST 800-53 CM-6, CM-7
- References
- Apache HTTP Server, AllowOverride directive
Apache HTTP Server, Security Tips
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWApache OCSP Stapling Not Enabled
WEB-APA-007
A TLS-enabled Apache does not set SSLUseStapling on.
Why it matters. Without stapling, every browser asks the certificate authority whether the certificate is revoked, which slows the handshake and reveals the visited site to the CA. Stapling lets the server attach a fresh signed status itself.
/etc/apache2/apache2.conf: A TLS-enabled Apache does not set SSLUseStapling on.
SSLUseStapling is not set; the default is off
- Fix
- Add SSLUseStapling On inside the vhost and SSLStaplingCache "shmcb:logs/ssl_stapling(32768)" outside it, as the Mozilla generator produces.
- Verify
openssl s_client -connect 127.0.0.1:443 -servername <site> -status should print OCSP Response Status: successful.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-299, OWASP A02:2021, ASVS 9.2.4, NIST 800-53 SC-8, SC-17
- References
- Apache HTTP Server, SSLUseStapling directive
Mozilla SSL Configuration Generator
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWApache ETag Reveals Inode Numbers
WEB-APA-009
FileETag includes INode (or All), so ETag headers leak filesystem inode numbers of served files.
Why it matters. Inode numbers help distinguish servers behind a load balancer and have been used to infer file identity across hosts (CVE-2003-1418). The Apache 2.4 default of MTime Size does not include them.
/etc/apache2/apache2.conf: FileETag includes INode (or All), so ETag headers leak filesystem inode numbers of served files.
/etc/apache2/apache2.conf: FileETag INode MTime Size
- Fix
- Set FileETag MTime Size or FileETag None and reload.
- Verify
curl -sI https://<site>/robots.txt | grep -i etag should show a two-part value, not three.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.3, NIST 800-53 SI-11, CM-6
- References
- Apache HTTP Server, FileETag directive
CVE-2003-1418, Apache inode disclosure in ETag
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWApache Serves Repository and Environment Files
WEB-APA-010
No DirectoryMatch, FilesMatch or RedirectMatch rule denies .git, .svn, .hg or .env paths, so they are served if present under a document root.
Why it matters. Repository folders rebuild the source code and its history; .env files hold database passwords and application keys. Debian's default only protects .ht* files. One rule for every dot path removes the whole class, including files deployed by mistake later. The rating is Low because this is a missing safety net, not an exposure: when such a file is actually present under a document root, WEB-APP-009 and WEB-DOC-001 report it at their own higher severity, and when none is present the check passes and only notes the missing rule.
/etc/apache2/apache2.conf: No DirectoryMatch, FilesMatch or RedirectMatch rule denies .git, .svn, .hg or .env paths, so they are served if present under a document root.
no DirectoryMatch, FilesMatch or RedirectMatch rule covers .git, .svn or .env, and these exist under a document root:
/var/www/shop/.git
/var/www/shop/.env
- Fix
- Add to the server configuration: <DirectoryMatch "/\.(git|svn|hg)"> Require all denied </DirectoryMatch> and <FilesMatch "^\.(env|git|svn)"> Require all denied </FilesMatch> , then reload.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/.git/HEAD should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-538, CWE-527, OWASP A05:2021, ASVS 12.5.1, 14.3.3, NIST 800-53 CM-7, SC-28
- References
- Apache HTTP Server, DirectoryMatch directive
OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWFlask Debug Mode Enabled in Application Code
WEB-APP-007
Looks for app.run(debug=True) or app.debug = True in Flask entry files. A heuristic; the service check WEB-PY-004 covers the environment switches.
Why it matters. Debug mode in code follows the application wherever it is deployed. If the file is ever run directly instead of through a WSGI server, the Werkzeug debugger and its code console come up for every visitor.
/srv/shop-reports/app.py: Flask debug mode is enabled in code
app.run(debug=True)
- Fix
- Remove debug=True from app.run() and read it from the environment for local work only (app.run(debug=os.environ.get('FLASK_DEBUG') == '1')); serve production with Gunicorn or uWSGI, which never call app.run().
- Verify
grep -n 'debug' app.py shows no hard-coded True.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- Medium
- Standards
- CWE-489, CWE-215, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-6, CM-7
- References
- Flask documentation, Debug mode
Flask documentation, Deploying to Production
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWWordPress Version Disclosed
WEB-CMS-001
Checks whether WordPress sites reveal their exact version in the page or in readme.html.
Why it matters. The version number lets automated tools pick matching exploits for outdated cores and plugins.
shop.example.test: WordPress version is disclosed
generator tag: WordPress 5.2.1
/readme.html is public and states WordPress 5.2.1
- Fix
- Keep WordPress updated (automatic minor updates on). Remove the generator tag (remove_action('wp_head','wp_generator')) and delete readme.html after each update, or block it at the web server.
- Verify
curl -s https://<site>/ | grep -i 'name="generator"'
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, A06:2021, ASVS 14.3.3, NIST 800-53 CM-7, SI-11
- References
- WordPress Developer Resources, Hardening WordPress
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWWordPress XML-RPC Interface Enabled
WEB-CMS-002
Checks whether xmlrpc.php answers on WordPress sites.
Why it matters. XML-RPC allows many password guesses in one request (system.multicall) and is abused for pingback amplification. Few sites still need it.
shop.example.test: xmlrpc.php is enabled
- Fix
- Block it at the web server (<Files xmlrpc.php> Require all denied </Files>) or disable it with a security plugin, unless Jetpack or the mobile app needs it.
- Verify
curl -s https://<site>/xmlrpc.php should return 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-307, OWASP A07:2021, ASVS 2.2.1, NIST 800-53 AC-7, CM-7
- References
- WordPress Developer Resources, Brute Force Attacks (XML-RPC)
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWWordPress User Accounts Enumerable
WEB-CMS-003
Checks whether the WordPress REST API lists user accounts to anonymous visitors.
Why it matters. A list of login names halves the work of password guessing and phishing against administrators.
shop.example.test: Exposed: /wp-json/wp/v2/users (HTTP 200)
/wp-json/wp/v2/users (HTTP 200)
- Fix
- Restrict the users endpoint to authenticated requests with a security plugin or a small rest_endpoints filter, and use login names that differ from public display names.
- Verify
curl -s https://<site>/wp-json/wp/v2/users should return 401, 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-204, OWASP A07:2021, NIST 800-53 CM-6, SI-11
- References
- WordPress Developer Resources, REST API Users endpoint
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWWordPress Dashboard File Editor Enabled
WEB-CMS-007
Checks whether wp-config.php leaves the built-in theme and plugin file editor enabled.
Why it matters. The editor lets any administrator account change PHP files from the browser. A stolen or phished admin session then becomes code execution on the server in one step.
/var/www/shop/wp-config.php: WordPress file editor is enabled
DISALLOW_FILE_EDIT is not set to true
- Fix
- Add define('DISALLOW_FILE_EDIT', true); to wp-config.php above the line that says to stop editing.
- Verify
The Theme File Editor and Plugin File Editor menus disappear from the dashboard.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-94, CWE-1188, OWASP A05:2021, NIST 800-53 CM-7, AC-6
- References
- WordPress Developer Resources, Hardening WordPress
WordPress Developer Resources, Editing wp-config.php
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWJoomla Version Disclosed
WEB-CMS-010
Checks whether a Joomla site serves its version manifest at /administrator/manifests/files/joomla.xml.
Why it matters. The manifest gives the exact Joomla version, which lets automated tools pick exploits for known vulnerabilities, such as the unauthenticated information disclosure CVE-2023-23752.
shop.example.test: Joomla version manifest is public
version 3.9.0
- Fix
- Block the folder at the web server (Apache: <Directory "/path/administrator/manifests"> Require all denied </Directory>; nginx: location ^~ /administrator/manifests/ { deny all; }) and keep Joomla updated.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/administrator/manifests/files/joomla.xml prints 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, A06:2021, ASVS 14.3.3, NIST 800-53 SI-11
- References
- Joomla Documentation, Security Checklist
NVD, CVE-2023-23752
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDrupal Version Disclosed by Changelog
WEB-CMS-011
Checks whether a Drupal site serves CHANGELOG.txt, which names the exact Drupal version.
Why it matters. The changelog tells attackers precisely which Drupal security advisories apply, as was used at scale for Drupalgeddon 2 (CVE-2018-7600).
shop.example.test: Drupal changelog is public
/core/CHANGELOG.txt: Drupal 8.5.0, 2018-03-07
- Fix
- Delete the changelog files after each update, or deny *.txt files in the Drupal root and core folders at the web server, and keep Drupal updated.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/core/CHANGELOG.txt prints 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, A06:2021, ASVS 14.3.3, NIST 800-53 SI-11
- References
- Drupal.org, Security advisories
NVD, CVE-2018-7600
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
- Source
internal/checks/web/cms_more.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWWordPress Author Archive Reveals Login Names
WEB-CMS-018
Checks whether /?author=1 redirects to an author archive, which exposes the first account's login name in the address.
Why it matters. The author archive address contains the user's slug, which by default equals the login name. Together with the REST API listing (WEB-CMS-003) this gives attackers the administrator's user name for password guessing without touching the login form.
shop.example.test: /?author=1 redirects to the author archive
Location: .../author/<login-name>/
- Fix
- Return 404 for author queries by id (a small redirect rule or a security plugin's user enumeration protection), and give administrators a nickname and display name that differ from the login name.
- Verify
curl -sI https://<site>/?author=1 | grep -i location prints nothing or a 404 page.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-204, OWASP A07:2021, NIST 800-53 CM-6, SI-11
- References
- WordPress Developer Resources, Brute Force Attacks
WordPress Developer Resources, Hardening WordPress
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDependency Manifests Exposed
WEB-EXP-009
Checks whether package manifests and lock files are downloadable.
Why it matters. Lock files list exact library versions, giving attackers a ready list to match against public vulnerabilities, and often reveal internal package names.
shop.example.test: Exposed: /composer.lock (HTTP 200)
/composer.lock (HTTP 200)
- Fix
- Keep manifests outside the public web root (for example serve only a public/ subfolder), or deny them at the web server.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/composer.lock should print 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-538, OWASP A05:2021, A06:2021, ASVS 12.5.1, NIST 800-53 CM-7
- References
- OWASP WSTG-CONF-04, Review Old Backup and Unreferenced Files for Sensitive Information
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWDefault Web Server Page Served
WEB-EXP-010
Checks whether a site shows the web server's default installation page.
Why it matters. Default pages reveal the server software and suggest an unmaintained or forgotten virtual host, which attackers prioritise.
shop.example.test: Exposed: / (HTTP 200)
/ (HTTP 200)
- Fix
- Remove the default site or replace its index page, and disable unused virtual hosts.
- Verify
Open the site in a browser; the default page should not appear.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, CWE-497, OWASP A05:2021, NIST 800-53 CM-7
- References
- OWASP WSTG-INFO-02, Fingerprint Web Server
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/exposure.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMissing X-Content-Type-Options
WEB-HDR-004
Checks that browsers are told not to guess (sniff) content types.
Why it matters. Without nosniff, a browser may execute an uploaded text or image file as script or HTML, enabling XSS through file uploads.
shop.example.test: X-Content-Type-Options is missing or not 'nosniff'
- Fix
- Send X-Content-Type-Options: nosniff on every response (Apache: Header always set X-Content-Type-Options nosniff; nginx: add_header X-Content-Type-Options nosniff always;).
- Verify
curl -sI https://<site>/ | grep -i x-content-type-options
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-430, OWASP A05:2021, ASVS 14.4.4, NIST 800-53 CM-6
- References
- OWASP Secure Headers Project
MDN Web Docs, X-Content-Type-Options
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMissing Referrer-Policy
WEB-HDR-005
Checks that each site limits what URL information is leaked to other sites in the Referer header.
Why it matters. Full URLs can contain session tokens, password-reset links or personal data, which would otherwise be sent to every third-party resource and outbound link.
shop.example.test: Referrer-Policy is missing or not ''
- Fix
- Send Referrer-Policy: strict-origin-when-cross-origin (or no-referrer). Never use unsafe-url.
- Verify
curl -sI https://<site>/ | grep -i referrer-policy
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-201, OWASP A05:2021, ASVS 14.4.6, NIST 800-53 CM-6
- References
- OWASP Secure Headers Project
MDN Web Docs, Referrer-Policy
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWMissing Permissions-Policy
WEB-HDR-006
Checks that each site restricts powerful browser features (camera, microphone, geolocation) it does not use.
Why it matters. Restricting features limits what injected or third-party scripts can do in your visitors' browsers.
shop.example.test: Permissions-Policy is missing or not ''
- Fix
- Send, for example, Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=() adjusted to the features the site really uses.
- Verify
curl -sI https://<site>/ | grep -i permissions-policy
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, OWASP A05:2021, NIST 800-53 CM-6, CM-7
- References
- OWASP Secure Headers Project
MDN Web Docs, Permissions-Policy
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWServer Software Version Disclosed
WEB-HDR-007
Checks whether response headers reveal exact web server, PHP or framework versions.
Why it matters. Exact versions let attackers match the site against public exploit lists in seconds. Hiding them does not fix vulnerabilities but removes free reconnaissance.
shop.example.test: Software versions are disclosed in headers
Server: Apache/2.4.29 (Ubuntu)
X-Powered-By: PHP/7.2.24
- Fix
- Apache: ServerTokens Prod and ServerSignature Off . nginx: server_tokens off; . PHP: expose_php = Off in php.ini . Remove X-Powered-By in the application or proxy.
- Verify
curl -sI https://<site>/ | grep -Ei '^(server|x-powered-by)'
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.3, NIST 800-53 CM-7, SI-11
- References
- OWASP HTTP Headers Cheat Sheet
Apache HTTP Server, ServerTokens directive
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
A8: Tracing Findings to Security Requirements (offline: openvapt learn A8)
- Source
internal/checks/web/headers.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWnginx Version Shown in Server Header
WEB-NGX-001
nginx does not set server_tokens off, so responses and error pages carry the exact nginx version.
Why it matters. The version string lets an attacker pick advisories that match the server instead of guessing. Hiding it is not a fix for old software, but there is no reason to publish it.
/etc/nginx/nginx.conf: nginx does not set server_tokens off, so responses and error pages carry the exact nginx version.
/etc/nginx/conf.d/tokens.conf: server_tokens on
- Fix
- In the http block of nginx.conf add server_tokens off; then run nginx -t and reload.
- Verify
curl -sI https://<site>/ | grep -i '^server:' should print Server: nginx with no version.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.3, NIST 800-53 CM-6, SI-11
- References
- nginx documentation, ngx_http_core_module
OWASP WSTG-INFO-02, Fingerprint Web Server
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWnginx OCSP Stapling Off or Session Tickets On
WEB-NGX-005
A TLS-enabled nginx does not enable ssl_stapling, or leaves ssl_session_tickets on.
Why it matters. Without stapling, every browser asks the certificate authority whether the certificate is revoked, which slows the handshake and leaks the visited site to the CA. Session tickets encrypted with a long-lived key weaken forward secrecy when the key is never rotated; the Mozilla profiles turn them off.
/etc/nginx/nginx.conf: A TLS-enabled nginx does not enable ssl_stapling, or leaves ssl_session_tickets on.
ssl_stapling is not set; the default is off
ssl_session_tickets is not set; the default is on
- Fix
- Add ssl_stapling on; ssl_stapling_verify on; ssl_session_tickets off; and a resolver directive, as the Mozilla generator produces.
- Verify
openssl s_client -connect 127.0.0.1:443 -servername <site> -status should print OCSP Response Status: successful.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Cryptography and TLS
- Effort
- Low
- Confidence
- High
- Standards
- CWE-299, CWE-326, OWASP A02:2021, ASVS 9.2.4, NIST 800-53 SC-8, SC-17
- References
- Mozilla SSL Configuration Generator
nginx documentation, ngx_http_ssl_module
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWNode.js Service Not Running in Production Mode
WEB-NODE-003
Checks whether Node.js services set NODE_ENV=production.
Why it matters. Express and many other frameworks treat a missing NODE_ENV as development: error pages then include stack traces with file paths, and caching and other production safeguards are off.
systemd units: Node.js services are not in production mode
shop-api.service: NODE_ENV=development
- Fix
- Add Environment=NODE_ENV=production to the [Service] section (systemctl edit <unit>), run systemctl daemon-reload and restart the service.
- Verify
systemctl show -p Environment <unit> includes NODE_ENV=production.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-489, CWE-209, OWASP A05:2021, ASVS 14.3.2, NIST 800-53 CM-6
- References
- Express documentation, Production best practices: performance and reliability
OWASP Node.js Security Cheat Sheet
- Learn
- P13: Application Servers: Tomcat, Node.js and Python (offline:
openvapt learn P13)
- Source
internal/checks/web/runtimes.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
LOWPHP Version Exposed in Headers
WEB-PHP-002
Checks whether PHP adds an X-Powered-By header with its version.
Why it matters. The header advertises the exact PHP version to every visitor and scanner.
php: expose_php = 1
- Fix
- In php.ini set expose_php = Off and restart PHP.
- Verify
php -r "echo ini_get('expose_php');" and check the FPM pool's php.ini or php_admin_value settings.
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N
- Category
- Information Exposure
- Effort
- Low
- Confidence
- High
- Standards
- CWE-497, OWASP A05:2021, ASVS 14.3.3, NIST 800-53 CM-7, SI-11
- References
- PHP manual, php.ini directives
OWASP PHP Configuration Cheat Sheet
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
- Source
internal/checks/web/php.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFODocker Not Running in Rootless Mode
HOST-CTR-009
Reports whether the Docker daemon runs as root or in rootless mode. Informational.
Why it matters. In rootless mode the daemon and every container run inside a user namespace as an ordinary account, so a container breakout lands in that account rather than in root. It is not possible for every workload (some networking and storage features differ), so this is information for a design decision, not a failure.
docker: Docker runs as the root daemon only; rootless mode is not in use
- Fix
- Where the workloads allow it, install rootless Docker (dockerd-rootless-setuptool.sh install) for the service account and disable the system daemon; otherwise keep userns-remap (HOST-CTR-002) as the fallback.
- Verify
docker info --format '{{.SecurityOptions}}' lists name=rootless.
- CVSS v3.1
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:N
- Category
- Secure Configuration
- Effort
- High
- Confidence
- High
- Standards
- CWE-250, NIST 800-53 AC-6, SC-39
- References
- Docker documentation, Rootless mode
NIST SP 800-190, Application Container Security Guide
- Learn
- P9: Containers and Kubernetes (offline:
openvapt learn P9)
A5: Container Runtime Hardening Depth (offline: openvapt learn A5)
- Source
internal/checks/host/containers_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFOPassword Expiry Warning Too Short
HOST-PAM-006
Reports whether users are warned at least 7 days before a password expires.
Why it matters. Where passwords do expire, a short or missing warning means users are locked out without notice and support staff reset passwords under pressure, which is when weak temporary passwords and social engineering succeed. This is informational: with no expiry (HOST-PWD-005) the warning never fires.
/etc/login.defs: PASS_WARN_AGE 3 (7 or more)
- Fix
- Set PASS_WARN_AGE 7 in /etc/login.defs, and for existing accounts chage --warndays 7 <user> .
- Verify
grep '^PASS_WARN_AGE' /etc/login.defs
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-262, OWASP A07:2021, NIST 800-53 IA-5(1)
- References
- login.defs(5), Linux man-pages
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
- Learn
- P22: Authentication Policy and Package Hygiene (offline:
openvapt learn P22)
- Source
internal/checks/host/pam_login.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFOThird-Party Package Repositories Present
HOST-PKG-003
Lists package repositories that are not run by the distribution vendor, so each one can be justified.
Why it matters. Every repository can install software as root at the next update, so each one is a supplier you trust completely. Personal package archives, vendor repositories and forgotten test repositories are a common way for unpatched or abandoned software to stay on a server. This is informational: a third-party repository is a decision to review, not a defect by itself.
package repositories: 1 third-party repository host(s) configured
ppa.launchpadcontent.net (/etc/apt/sources.list.d/lab-ppa.list)
- Fix
- For each listed repository, record who runs it and why it is needed; remove the ones nobody can justify (delete the file under /etc/apt/sources.list.d or /etc/yum.repos.d and apt-get update or dnf clean all). Keep the rest pinned to the packages they are for (apt preferences, dnf includepkgs).
- Verify
ls /etc/apt/sources.list.d/ /etc/yum.repos.d/ 2>/dev/null
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1357, OWASP A08:2021, NIST 800-53 CM-8, SR-3, SR-4
- References
- sources.list(5), Debian manual pages
NIST SP 800-40 Rev. 4, Guide to Enterprise Patch Management Planning
NIST SP 800-161 Rev. 1, Cybersecurity Supply Chain Risk Management Practices
- Learn
- P1: Linux Server Hardening (offline:
openvapt learn P1)
P22: Authentication Policy and Package Hygiene (offline: openvapt learn P22)
- Source
internal/checks/host/pkg_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFOForced Periodic Password Rotation Configured
HOST-PWD-005
Reports whether new accounts are forced to change passwords on a short fixed schedule.
Why it matters. NIST SP 800-63B-4 (section 3.1.1.2) says verifiers should not require periodic password changes, and should force a change only on evidence of compromise. Frequent forced rotation pushes users toward predictable variations. CIS Controls v8 safeguard 5.2 asks for unique passwords with a minimum length (8 characters where multi-factor authentication is used, 14 where it is not) and does not ask for periodic changes. This finding is informational: a short PASS_MAX_DAYS is not a vulnerability, but it is worth reviewing against current guidance.
/etc/login.defs: PASS_MAX_DAYS 90 forces a password change every 90 days; NIST SP 800-63B-4 advises against periodic rotation
- Fix
- Prefer long passphrases, a breached-password blocklist and multi-factor authentication over forced rotation. If policy allows, set PASS_MAX_DAYS 365 or 99999 in /etc/login.defs and change passwords when compromise is suspected.
- Verify
grep '^PASS_MAX_DAYS' /etc/login.defs
- CVSS v3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Identity and Authentication
- Effort
- Low
- Confidence
- High
- Standards
- CWE-262, NIST 800-53 IA-5(1)
- References
- login.defs(5), Linux man-pages
NIST SP 800-63B-4, Digital Identity Guidelines: Authentication and Authenticator Management
CIS Critical Security Controls v8, Control 5 (Account Management)
- Learn
- P7: Identity, Passwords and Privilege (offline:
openvapt learn P7)
P15: Access Control: Accounts, Sudo and Logins (offline: openvapt learn P15)
- Source
internal/checks/host/passwords.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFOApache Has No Request Filtering Module
WEB-APA-008
Neither mod_security (ModSecurity) nor mod_evasive is loaded, so Apache has no request filtering or flood control in front of the application.
Why it matters. A web application firewall or flood limiter is a defence-in-depth layer, not a requirement, and a misconfigured one breaks sites. The result is informational so you can decide with the application owner.
/etc/apache2/apache2.conf: Neither mod_security (ModSecurity) nor mod_evasive is loaded, so Apache has no request filtering or flood control in front of the application.
no security2_module or evasive20_module is loaded
- Fix
- Consider ModSecurity with the OWASP Core Rule Set in detection-only mode first, or mod_evasive for simple rate limiting, and tune before blocking.
- Verify
apachectl -M 2>/dev/null | grep -E 'security2|evasive'
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, OWASP A05:2021, ASVS 11.1.4, NIST 800-53 SC-5, SI-10
- References
- OWASP ModSecurity Core Rule Set
Apache HTTP Server, Security Tips
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
P25: Availability Without Load Testing (offline: openvapt learn P25)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFODependency Lock Files Older Than a Year
WEB-APP-008
Reports composer.lock, package-lock.json, yarn.lock, Gemfile.lock and poetry.lock files not modified for 365 days or more (dependency freshness). Informational.
Why it matters. A lock file pins exact library versions. One untouched for a year means the application has had no dependency updates in that time, so every library vulnerability published since is still present. The check cannot tell whether a specific vulnerability applies; the known-vulnerability checks and composer audit or npm audit do that.
/srv/shop-laravel/composer.lock: Lock file last changed 800 days ago
/var/www/shop/admin/Gemfile.lock: Lock file last changed 800 days ago
/var/www/shop/package-lock.json: Lock file last changed 800 days ago
- Fix
- Run composer update / npm update / bundle update / poetry update in a test environment, run the audit command of each ecosystem (composer audit, npm audit, bundle audit, pip-audit) and deploy. Schedule dependency updates at least quarterly.
- Verify
stat -c '%y %n' composer.lock package-lock.json shows a recent date.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Patch and Vulnerability Management
- Effort
- Medium
- Confidence
- High
- Standards
- CWE-1104, CWE-1395, OWASP A06:2021, ASVS 14.2.1, NIST 800-53 SI-2, SA-22
- References
- OWASP Vulnerable Dependency Management Cheat Sheet
OWASP Top 10 2021, A06 Vulnerable and Outdated Components
- Learn
- A6: Application Framework and CMS Configuration (offline:
openvapt learn A6)
- Source
internal/checks/web/frameworks.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFOWordPress Cron Reachable by Visitors
WEB-CMS-017
Reports whether /wp-cron.php answers to anonymous requests on WordPress sites. Informational.
Why it matters. WP-Cron runs scheduled tasks when visitors load pages, and wp-cron.php can be requested directly. On busy or targeted sites that lets anyone make the server do work on demand, and it is a frequent target for resource exhaustion; a system cron job is the documented production setup.
shop.example.test: wp-cron.php answers anonymous requests
- Fix
- Add define('DISABLE_WP_CRON', true); to wp-config.php, run */5 * * * * www-data php /var/www/<site>/wp-cron.php from the system cron (or curl the URL from cron), and deny direct requests to wp-cron.php at the web server.
- Verify
curl -s -o /dev/null -w '%{http_code}' https://<site>/wp-cron.php prints 403 or 404.
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-770, OWASP A05:2021, NIST 800-53 CM-7, SC-5
- References
- WordPress Developer Resources, Hooking WP-Cron Into the System Task Scheduler
WordPress Developer Resources, Hardening WordPress
- Learn
- P6: Information Exposure and Misconfiguration (offline:
openvapt learn P6)
P14: CMS Hardening in Depth: WordPress, Joomla and Drupal (offline: openvapt learn P14)
A6: Application Framework and CMS Configuration (offline: openvapt learn A6)
- Source
internal/checks/web/cms_depth.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFOnginx Request Limits Not Configured
WEB-NGX-006
nginx sets no client_max_body_size, limit_req_zone or limit_conn_zone, so request size and rate rely on defaults alone.
Why it matters. Explicit limits bound what one client can upload or how fast it can call login and search pages. They are an availability and brute-force control, informational here because the right values depend on the application.
/etc/nginx/nginx.conf: nginx sets no client_max_body_size, limit_req_zone or limit_conn_zone, so request size and rate rely on defaults alone.
no client_max_body_size, limit_req_zone or limit_conn_zone directive
- Fix
- Set client_max_body_size to what the application needs (the default is 1m) and add limit_req_zone for login and API locations with a sensible rate. See the nginx limit_req and limit_conn module documentation.
- Verify
nginx -T | grep -nE 'client_max_body_size|limit_(req|conn)_zone'
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Secure Configuration
- Effort
- Low
- Confidence
- High
- Standards
- CWE-770, CWE-307, OWASP A05:2021, A07:2021, ASVS 11.1.4, NIST 800-53 SC-5, AC-7
- References
- nginx documentation, ngx_http_limit_req_module
nginx documentation, ngx_http_core_module
- Learn
- P18: Web Server Hardening: nginx and Apache (offline:
openvapt learn P18)
P25: Availability Without Load Testing (offline: openvapt learn P25)
- Source
internal/checks/web/serverconf.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
INFONo security.txt Contact File
WEB-SEC-001
Checks whether each site publishes /.well-known/security.txt (RFC 9116).
Why it matters. security.txt tells researchers how to report a vulnerability. Without it, reports may go unheard or be disclosed publicly instead.
shop.example.test: No /.well-known/security.txt with a Contact field
- Fix
- Publish /.well-known/security.txt with at least Contact: and Expires: fields (see securitytxt.org).
- Verify
curl -s https://<site>/.well-known/security.txt
- CVSS v3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
- Category
- Web Application Security
- Effort
- Low
- Confidence
- High
- Standards
- CWE-1188, NIST 800-53 RA-5(11)
- References
- RFC 9116, A File Format to Aid in Security Vulnerability Disclosure
- Learn
- P5: Web Security Headers and Cookies (offline:
openvapt learn P5)
- Source
internal/checks/web/docroot.go
If you believe this is a false positive, report it with the False Positive form, or accept it with an expiry date in a suppression file.
Coverage Gaps
Incomplete, Error and Skipped checks did not establish that the affected area is secure. Review the reason and rerun with the required access or corrected configuration.
| ID | Status | Affected Area and Reason |
NET-TLS-001 | Incomplete | shop.example.test on port 10000: Modern TLS handshake failed, so legacy protocol rejection could not be verified |
NET-TLS-005 | Incomplete | shop.example.test on port 10000: TLS certificate could not be read |
NET-TLS-006 | Incomplete | shop.example.test on port 10000: TLS certificate could not be read |
All Checks
| ID | Title | Category | Effort | Severity | Status |
HOST-CTR-001 | Docker API Exposed Over TCP Without TLS | Network Exposure | Low | Critical | Fail |
HOST-CVE-002 | Known Exploited Vulnerabilities Present | Patch and Vulnerability Management | Medium | Critical | Fail |
HOST-K8S-001 | Kubelet Allows Anonymous or Unauthorised Access | Identity and Authentication | Medium | Critical | Fail |
HOST-SSH-003 | SSH Permits Empty Passwords | Identity and Authentication | Low | Critical | Fail |
NET-DB-002 | Redis Authentication and Network Binding | Data Services | Low | Critical | Fail |
NET-DB-003 | MongoDB Authorization and Network Binding | Data Services | Low | Critical | Fail |
NET-DB-004 | PostgreSQL Trust and Broad Client Access | Data Services | Low | Critical | Fail |
NET-DB-007 | Elasticsearch Security and Network Binding | Data Services | Low | Critical | Fail |
NET-SVC-002 | Control Plane or Remote Desktop Ports Network-Reachable | Network Exposure | Medium | Critical | Fail |
WEB-EXP-002 | Environment or Secrets File Exposed | Information Exposure | Medium | Critical | Fail |
WEB-NODE-002 | Node.js Debugger (Inspector) Enabled in a Service | Secure Configuration | Low | Critical | Fail |
WEB-PY-004 | Python Interactive Debugger Enabled in a Service | Secure Configuration | Low | Critical | Fail |
WEB-TOM-002 | Tomcat Administrative Users With Default or Weak Passwords | Identity and Authentication | Low | Critical | Fail |
WEB-TOM-004 | Tomcat AJP Connector Unprotected (Ghostcat) | Web Application Security | Low | Critical | Fail |
HOST-CRON-001 | Cron Jobs Run Programs Other Users Can Modify | Access Control | Low | High | Fail |
HOST-CRON-002 | World-Writable Directory in Cron's PATH | Access Control | Low | High | Fail |
HOST-CTR-003 | Privileged or Host-Namespace Containers | Secure Configuration | Medium | High | Fail |
HOST-CTR-004 | Containers Mount the Docker Socket or Host Root | Access Control | Medium | High | Fail |
HOST-CTR-008 | Docker Socket Accessible to Non-Administrators | Access Control | Low | High | Fail |
HOST-CTR-011 | Seccomp or AppArmor Disabled for Containers | Secure Configuration | Medium | High | Fail |
HOST-CTR-014 | containerd Remote API or Podman Unconfined Defaults | Secure Configuration | Medium | High | Fail |
HOST-CVE-001 | Installed OS Packages With Known Vulnerabilities | Patch and Vulnerability Management | Medium | High | Fail |
HOST-DKR-001 | Users With Root-Equivalent Docker Access | Identity and Authentication | Medium | High | Fail |
HOST-FS-001 | Sensitive Account Files Have Unsafe Permissions | Access Control | Low | High | Fail |
HOST-FS-002 | Temporary Directory Missing the Sticky Bit | Access Control | Low | High | Fail |
HOST-FS-003 | World-Writable Files in System Configuration | Access Control | Medium | High | Fail |
HOST-FS-004 | Unexpected SUID or SGID Programs | Access Control | Medium | High | Fail |
HOST-FS-005 | Cron Files Writable by Non-Root Users | Access Control | Low | High | Fail |
HOST-FS-007 | Private TLS Keys Readable by Others | Cryptography and TLS | Low | High | Fail |
HOST-FS-022 | Account Database Files or Their Backups Not Owned and Locked by Root | Access Control | Low | High | Fail |
HOST-K8S-002 | Kubernetes Data Directory Accessible to Others | Access Control | Low | High | Fail |
HOST-K8S-003 | Kubernetes Credential Files Readable by Others | Identity and Authentication | Low | High | Fail |
HOST-OS-001 | Operating System Past End of Security Support | Patch and Vulnerability Management | High | High | Fail |
HOST-PKG-001 | Security Updates Waiting to Be Installed | Patch and Vulnerability Management | Medium | High | Fail |
HOST-PKG-002 | Repository Signature Checks Disabled | Patch and Vulnerability Management | Low | High | Fail |
HOST-SEC-001 | Secrets in World-Readable Files | Information Exposure | Medium | High | Fail |
HOST-SSH-001 | SSH Allows Direct Root Login | Identity and Authentication | Low | High | Fail |
HOST-SSH-009 | SSH Host Private Keys Readable by Others | Cryptography and TLS | Low | High | Fail |
HOST-SSH-010 | SSH Server Configuration Writable by Non-Root Users | Access Control | Low | High | Fail |
HOST-SYSD-003 | Service Unit Files Writable by Non-Root Users | Access Control | Low | High | Fail |
HOST-SYSD-004 | Service Programs in Writable Locations | Access Control | Low | High | Fail |
HOST-USR-001 | Extra Accounts With Root Privileges (UID 0) | Identity and Authentication | Medium | High | Fail |
HOST-USR-002 | Accounts Without a Password | Identity and Authentication | Low | High | Fail |
HOST-USR-003 | Sudo Rules Without Password (NOPASSWD) | Identity and Authentication | Low | High | Fail |
HOST-USR-007 | Insecure Trust Files in Home Directories | Identity and Authentication | Low | High | Fail |
NET-AI-001 | AI Model Server or Dashboard Reachable From the Network | Network Exposure | Low | High | Fail |
NET-AI-002 | Jupyter Configuration Weakens Authentication | Identity and Authentication | Low | High | Fail |
NET-APP-001 | Debugger or Application Control Ports Exposed | Network Exposure | Low | High | Fail |
NET-DB-001 | Database or Cache Service Exposed to the Network | Data Services | Low | High | Fail |
NET-DB-005 | MySQL or MariaDB Unsafe Network Options | Data Services | Low | High | Fail |
NET-DB-006 | Memcached UDP or Broad Listen Address | Data Services | Low | High | Fail |
NET-DB-008 | Unsafe NFS Export Options | Data Services | Low | High | Fail |
NET-DB-009 | Unsafe Samba Guest or SMB1 Configuration | Data Services | Low | High | Fail |
NET-DB-010 | BIND Open Recursion | Data Services | Low | High | Fail |
NET-DB-011 | BIND Zone Transfers Allowed to Any | Data Services | Low | High | Fail |
NET-DB-012 | Postfix Open Relay Controls | Data Services | Low | High | Fail |
NET-FW-002 | IPv6 Listeners Without IPv6 Firewall | Network Exposure | Medium | High | Fail |
NET-FW-003 | Firewall Allows Sensitive Services From Anywhere | Network Exposure | Low | High | Fail |
NET-SVC-001 | Cleartext Legacy Services Listening | Network Exposure | Medium | High | Fail |
NET-SVC-003 | Network Time Service Amplification Risk | Network Exposure | Low | High | Fail |
WEB-APA-005 | Apache Allows TLS 1.0 or 1.1 | Cryptography and TLS | Low | High | Fail |
WEB-APA-006 | Apache Cipher Suite Includes Weak Suites | Cryptography and TLS | Low | High | Fail |
WEB-APP-001 | Laravel Debug Mode On or Application Key Missing | Information Exposure | Low | High | Fail |
WEB-APP-003 | Symfony Running in the Development Environment | Information Exposure | Low | High | Fail |
WEB-APP-004 | Rails Master Key or Secrets File Exposed | Access Control | Low | High | Fail |
WEB-APP-006 | Spring Boot Actuator Endpoints Fully Exposed | Information Exposure | Low | High | Fail |
WEB-CMS-004 | CMS Configuration Readable by All Users | Access Control | Low | High | Fail |
WEB-CMS-005 | CMS Configuration Writable by Other Users | Access Control | Low | High | Fail |
WEB-CMS-012 | Drupal Core Past End of Life | Patch and Vulnerability Management | High | High | Fail |
WEB-CMS-014 | Joomla Core Past End of Life | Patch and Vulnerability Management | High | High | Fail |
WEB-CMS-019 | Drupal update.php Open Without Authentication | Secure Configuration | Low | High | Fail |
WEB-CVE-001 | Vulnerable Web Application Libraries | Patch and Vulnerability Management | Medium | High | Fail |
WEB-DOC-001 | Secrets or Backups Stored Inside a Web Root | Information Exposure | Low | High | Fail |
WEB-DOC-002 | Web Root Files Writable by Other Users | Access Control | Low | High | Fail |
WEB-EXP-001 | Git Repository Exposed on the Website | Information Exposure | Low | High | Fail |
WEB-EXP-004 | Backup or Database Dump Files Downloadable | Information Exposure | Low | High | Fail |
WEB-EXP-007 | Other Version Control Metadata Exposed | Information Exposure | Low | High | Fail |
WEB-EXP-008 | Log Files Downloadable From the Website | Information Exposure | Low | High | Fail |
WEB-EXP-012 | Framework Debug Pages Exposed | Information Exposure | Low | High | Fail |
WEB-NGX-003 | nginx Allows TLS 1.0 or 1.1 | Cryptography and TLS | Low | High | Fail |
WEB-NGX-004 | nginx Cipher List Includes Weak Suites | Cryptography and TLS | Low | High | Fail |
WEB-NODE-001 | Node.js Version Past End of Life | Patch and Vulnerability Management | High | High | Fail |
WEB-PHP-003 | PHP Allows Remote File Inclusion | Secure Configuration | Low | High | Fail |
WEB-PHP-004 | PHP Version Past End of Security Support | Patch and Vulnerability Management | High | High | Fail |
WEB-PY-001 | Django Debug Mode Enabled | Information Exposure | Low | High | Fail |
WEB-PY-003 | Django Uses the Generated Development Secret Key | Cryptography and TLS | Low | High | Fail |
WEB-TOM-001 | Tomcat Manager Reachable Without Address Restriction | Web Application Security | Low | High | Fail |
HOST-BOOT-001 | Boot Loader Has No Password | Access Control | Medium | Medium | Fail |
HOST-BOOT-002 | UEFI Secure Boot Disabled | Secure Configuration | High | Medium | Fail |
HOST-BOOT-003 | Uncommon Filesystem Modules Not Disabled | Secure Configuration | Low | Medium | Fail |
HOST-BOOT-004 | USB Storage Driver Not Disabled | Secure Configuration | Low | Medium | Fail |
HOST-BOOT-006 | No File Integrity Monitoring | Logging and Monitoring | Medium | Medium | Fail |
HOST-CTR-002 | Docker Daemon Not Hardened | Secure Configuration | Medium | Medium | Fail |
HOST-CTR-010 | Docker Daemon Allows Insecure Registries or Debug Features | Secure Configuration | Low | Medium | Fail |
HOST-CTR-012 | Containers Run Without Memory or Process Limits | Secure Configuration | Medium | Medium | Fail |
HOST-CTR-013 | Containers Run as Root With a Writable Root Filesystem | Secure Configuration | Medium | Medium | Fail |
HOST-FS-006 | Boot Loader Configuration Exposed | Access Control | Low | Medium | Fail |
HOST-FS-014 | World-Writable Files Outside Temporary Directories | Access Control | Low | Medium | Fail |
HOST-FS-016 | SUID or SGID Programs Outside the Known Baseline | Access Control | Medium | Medium | Fail |
HOST-FS-017 | World-Writable Directories Without the Sticky Bit | Access Control | Low | Medium | Fail |
HOST-KRN-001 | Address Space Layout Randomisation Not Fully Enabled | Secure Configuration | Low | Medium | Fail |
HOST-KRN-009 | Unprivileged eBPF Allowed | Secure Configuration | Low | Medium | Fail |
HOST-PAM-008 | Root PATH Contains Unsafe Entries | Identity and Authentication | Low | Medium | Fail |
HOST-PKG-005 | Running Kernel Older Than Installed Kernel | Patch and Vulnerability Management | Medium | Medium | Fail |
HOST-PWD-001 | Weak Password Hashing Algorithm Configured | Identity and Authentication | Low | Medium | Fail |
HOST-PWD-002 | Accounts With Obsolete Password Hashes | Identity and Authentication | Low | Medium | Fail |
HOST-PWD-004 | No Account Lockout After Failed Logins | Identity and Authentication | Medium | Medium | Fail |
HOST-SSH-002 | SSH Password Authentication Enabled | Identity and Authentication | Low | Medium | Fail |
HOST-SSH-004 | SSH Offers Weak Cryptography | Cryptography and TLS | Low | Medium | Fail |
HOST-SSH-007 | SSH Forwarding Features Enabled | Secure Configuration | Low | Medium | Fail |
HOST-SSH-011 | SSH Legacy Trust Options Enabled | Identity and Authentication | Low | Medium | Fail |
HOST-SVC-002 | Telnet Server Installed or Enabled | Secure Configuration | Low | Medium | Fail |
HOST-SVC-003 | rsh, rlogin, rexec or finger Server Installed or Enabled | Secure Configuration | Low | Medium | Fail |
HOST-SVC-004 | TFTP Server Installed or Enabled | Secure Configuration | Low | Medium | Fail |
HOST-SVC-005 | FTP Server Installed or Enabled | Secure Configuration | Low | Medium | Fail |
HOST-SVC-006 | NIS Server or Client Installed or Enabled | Secure Configuration | Low | Medium | Fail |
HOST-SYSD-001 | Custom Services Run as Root | Identity and Authentication | Medium | Medium | Fail |
HOST-SYSD-005 | Secrets Written Into Service Unit Files | Information Exposure | Low | Medium | Fail |
HOST-UPD-002 | Reboot Required to Apply Updates | Patch and Vulnerability Management | Medium | Medium | Fail |
HOST-USR-004 | Duplicate User IDs | Identity and Authentication | Medium | Medium | Fail |
HOST-USR-006 | Legacy NIS Entries in Account Files | Identity and Authentication | Low | Medium | Fail |
HOST-USR-008 | Duplicate Group IDs or Account Names | Identity and Authentication | Medium | Medium | Fail |
HOST-USR-009 | Password and Shadow Files Out of Step | Identity and Authentication | Low | Medium | Fail |
NET-APP-002 | Application Server Ports Reachable Without a Reverse Proxy | Network Exposure | Low | Medium | Fail |
NET-DB-013 | Mail Cleartext Authentication Allowed | Cryptography and TLS | Low | Medium | Fail |
NET-DB-014 | MySQL Symbolic Links Allowed for Tables | Data Services | Low | Medium | Fail |
NET-DB-015 | MySQL secure_file_priv Not Restricted | Data Services | Low | Medium | Fail |
NET-DB-016 | MySQL Does Not Require Encrypted Client Connections | Cryptography and TLS | Low | Medium | Fail |
NET-DB-019 | PostgreSQL Uses md5 or password Authentication | Identity and Authentication | Low | Medium | Fail |
NET-DB-020 | PostgreSQL SSL Not Enabled | Cryptography and TLS | Low | Medium | Fail |
NET-DB-022 | PostgreSQL Password Encryption Not SCRAM | Identity and Authentication | Low | Medium | Fail |
NET-DB-023 | Redis Dangerous Commands Not Restricted | Data Services | Low | Medium | Fail |
NET-DNS-002 | BIND DNSSEC Validation Disabled | Data Services | Low | Medium | Fail |
NET-FW-001 | No Active Host Firewall | Network Exposure | Medium | Medium | Fail |
NET-FW-005 | Container Ports Bypass the Host Firewall | Network Exposure | Medium | Medium | Fail |
NET-MAIL-001 | Postfix SMTP TLS Not Offered or Has No Certificate | Cryptography and TLS | Low | Medium | Fail |
NET-MAIL-002 | Postfix Allows TLS 1.0 or 1.1 | Cryptography and TLS | Low | Medium | Fail |
NET-MAIL-004 | Dovecot Does Not Require TLS | Cryptography and TLS | Low | Medium | Fail |
NET-SVC-004 | Management Panel or Monitoring Ports Network-Reachable | Network Exposure | Low | Medium | Fail |
NET-TLS-001 | Deprecated TLS 1.0 or 1.1 Accepted | Cryptography and TLS | Low | Medium | Fail |
NET-TLS-002 | TLS Certificate Expired or Expiring Soon | Cryptography and TLS | Low | Medium | Fail |
NET-TLS-003 | Self-Signed or Mismatched TLS Certificate | Cryptography and TLS | Low | Medium | Fail |
NET-TLS-004 | Weak TLS 1.2 Cipher Suites Accepted | Cryptography and TLS | Low | Medium | Fail |
NET-TLS-005 | TLS Certificate Public Key Too Small | Cryptography and TLS | Medium | Medium | Fail |
NET-TLS-006 | SHA-1 Signed TLS Leaf Certificate | Cryptography and TLS | Medium | Medium | Fail |
WEB-APA-003 | Apache Directory Indexes Enabled in Configuration | Information Exposure | Low | Medium | Fail |
WEB-APA-011 | Apache Has No Slow Request Protection | Secure Configuration | Low | Medium | Fail |
WEB-APP-002 | Application .env File Readable by All Users | Access Control | Low | Medium | Fail |
WEB-APP-005 | Rails Production Does Not Force HTTPS | Web Application Security | Low | Medium | Fail |
WEB-APP-009 | Git Repository Stored Inside a Web Root | Information Exposure | Low | Medium | Fail |
WEB-APP-010 | Framework Writable Folders Open to All Users | Access Control | Low | Medium | Fail |
WEB-CK-001 | Cookies Missing Secure, HttpOnly or SameSite | Web Application Security | Medium | Medium | Fail |
WEB-CMS-006 | WordPress Shows Debug Output to Visitors | Information Exposure | Low | Medium | Fail |
WEB-CMS-008 | WordPress Automatic Updates Disabled | Patch and Vulnerability Management | Low | Medium | Fail |
WEB-CMS-009 | Joomla Debug or Verbose Error Reporting Enabled | Information Exposure | Low | Medium | Fail |
WEB-CMS-013 | Drupal Trusted Host Patterns Not Set | Web Application Security | Low | Medium | Fail |
WEB-CMS-015 | Magento Not in Production Mode | Information Exposure | Low | Medium | Fail |
WEB-CMS-016 | Ghost Configured With a Plain HTTP Site URL | Web Application Security | Low | Medium | Fail |
WEB-COR-001 | Cross-Origin Resource Sharing Allows Any Origin With Credentials | Web Application Security | Low | Medium | Fail |
WEB-DOC-003 | Archives or Certificates Inside a Web Root | Information Exposure | Low | Medium | Fail |
WEB-EXP-003 | PHP Information Page Exposed | Information Exposure | Low | Medium | Fail |
WEB-EXP-005 | Directory Listing Enabled | Information Exposure | Low | Medium | Fail |
WEB-EXP-006 | Web Server Status Page Exposed | Information Exposure | Low | Medium | Fail |
WEB-EXP-011 | Database Administration Tool Exposed | Information Exposure | Low | Medium | Fail |
WEB-HDR-001 | Missing HTTP Strict Transport Security (HSTS) | Web Application Security | Low | Medium | Fail |
WEB-HDR-002 | Missing Content Security Policy | Web Application Security | Medium | Medium | Fail |
WEB-HDR-003 | Site Can Be Framed (Clickjacking) | Web Application Security | Low | Medium | Fail |
WEB-NGX-002 | nginx Directory Listing Enabled in Configuration | Information Exposure | Low | Medium | Fail |
WEB-NGX-007 | nginx Serves Hidden Files and Folders | Information Exposure | Low | Medium | Fail |
WEB-PHP-001 | PHP Displays Errors to Visitors | Secure Configuration | Low | Medium | Fail |
WEB-PHP-005 | PHP Session Cookies Not Hardened | Web Application Security | Low | Medium | Fail |
WEB-PY-002 | Django Accepts Any Host Header | Web Application Security | Low | Medium | Fail |
WEB-PY-005 | Python Development Server Used in a Service | Secure Configuration | Medium | Medium | Fail |
WEB-TLS-001 | Site Available Over Plain HTTP Without Redirect | Cryptography and TLS | Low | Medium | Fail |
WEB-TOM-003 | Tomcat Shutdown Port Uses the Default Command | Secure Configuration | Low | Medium | Fail |
WEB-TOM-005 | Tomcat Example and Documentation Applications Deployed | Information Exposure | Low | Medium | Fail |
HOST-AUD-001 | Audit Daemon Not Enabled at Boot | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-002 | Identity Files Not Audited | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-003 | Login and Logout Events Not Audited | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-004 | System Time Changes Not Audited | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-005 | Kernel Module Loading Not Audited | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-006 | Privileged Command Use Not Audited | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-007 | Audit Configuration Not Immutable | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-008 | Audit Log Files Readable by Others | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-009 | Audit Daemon Ignores a Full Log Disk | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-010 | Journal Not Persistent or Not Compressed | Logging and Monitoring | Low | Low | Fail |
HOST-AUD-011 | Logs Not Forwarded to a Remote Collector | Logging and Monitoring | Medium | Low | Fail |
HOST-BOOT-005 | Kernel Module Loading Unrestricted | Secure Configuration | Medium | Low | Fail |
HOST-BOOT-007 | Prelink Installed | Secure Configuration | Low | Low | Fail |
HOST-BOOT-008 | Core Dumps Not Restricted | Information Exposure | Low | Low | Fail |
HOST-CTR-005 | Docker Container Logs Have No Size Limit | Logging and Monitoring | Low | Low | Fail |
HOST-CTR-006 | Docker Userland Proxy Enabled | Secure Configuration | Low | Low | Fail |
HOST-CTR-007 | Docker Default Ulimits Not Set | Secure Configuration | Low | Low | Fail |
HOST-CTR-015 | Docker Content Trust Not Enabled | Secure Configuration | Medium | Low | Fail |
HOST-CVE-003 | Vulnerability Snapshot Outdated or Test Data | Patch and Vulnerability Management | Medium | Low | Fail |
HOST-FS-008 | Temporary Filesystems Allow Executables or Devices | Secure Configuration | Medium | Low | Fail |
HOST-FS-009 | Default File Creation Mask Too Permissive | Access Control | Low | Low | Fail |
HOST-FS-010 | /var/tmp Not a Separate Filesystem | Secure Configuration | Medium | Low | Fail |
HOST-FS-011 | /home Not a Separate Filesystem With nodev | Secure Configuration | Medium | Low | Fail |
HOST-FS-012 | Log Directories on the Root Filesystem | Secure Configuration | Medium | Low | Fail |
HOST-FS-013 | Temporary Filesystems Allow Executables | Secure Configuration | Medium | Low | Fail |
HOST-FS-015 | Files With No Known Owner or Group | Access Control | Low | Low | Fail |
HOST-FS-018 | Kernel Symbol Map or Initial RAM Disk Readable by Others | Information Exposure | Low | Low | Fail |
HOST-FS-019 | Cron and At Not Restricted to Allowed Users | Access Control | Low | Low | Fail |
HOST-FS-020 | Cron Configuration Readable by Other Users | Access Control | Low | Low | Fail |
HOST-FS-021 | Shell Profile Sets a Permissive File Creation Mask | Access Control | Low | Low | Fail |
HOST-IDS-001 | No Brute-Force Protection Service | Logging and Monitoring | Low | Low | Fail |
HOST-KRN-002 | Kernel Pointers Exposed to Unprivileged Users | Secure Configuration | Low | Low | Fail |
HOST-KRN-003 | Kernel Log Readable by Unprivileged Users | Secure Configuration | Low | Low | Fail |
HOST-KRN-004 | Setuid Programs May Dump Core | Secure Configuration | Low | Low | Fail |
HOST-KRN-005 | IP Forwarding Enabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-006 | ICMP Redirects Accepted | Secure Configuration | Low | Low | Fail |
HOST-KRN-007 | Source-Routed Packets Accepted | Secure Configuration | Low | Low | Fail |
HOST-KRN-008 | TCP SYN Cookies Disabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-010 | Process Tracing Not Restricted | Secure Configuration | Low | Low | Fail |
HOST-KRN-011 | Symlink Protection Disabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-012 | Hardlink Protection Disabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-013 | Reverse Path Filtering Disabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-014 | Martian Packets Not Logged | Secure Configuration | Low | Low | Fail |
HOST-KRN-015 | Server Sends ICMP Redirects | Secure Configuration | Low | Low | Fail |
HOST-KRN-016 | Broadcast ICMP Echo Answered | Secure Configuration | Low | Low | Fail |
HOST-KRN-017 | IPv6 ICMP Redirects Accepted | Secure Configuration | Low | Low | Fail |
HOST-KRN-018 | Performance Events Open to Unprivileged Users | Secure Configuration | Low | Low | Fail |
HOST-KRN-019 | Magic SysRq Key Enabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-020 | FIFO Protection in Shared Directories Disabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-021 | Regular File Protection in Shared Directories Disabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-022 | Unprivileged User Namespaces Allowed | Secure Configuration | Low | Low | Fail |
HOST-KRN-023 | IPv6 Source-Routed Packets Accepted | Secure Configuration | Low | Low | Fail |
HOST-KRN-024 | Secure ICMP Redirects Accepted | Secure Configuration | Low | Low | Fail |
HOST-KRN-025 | IPv6 Router Advertisements Accepted | Secure Configuration | Low | Low | Fail |
HOST-KRN-026 | Bogus ICMP Error Responses Logged | Secure Configuration | Low | Low | Fail |
HOST-KRN-027 | Kexec Kernel Replacement Allowed | Secure Configuration | Low | Low | Fail |
HOST-KRN-028 | Unprivileged userfaultfd Allowed | Secure Configuration | Low | Low | Fail |
HOST-KRN-029 | TTY Line Discipline Autoloading Enabled | Secure Configuration | Low | Low | Fail |
HOST-KRN-030 | BPF JIT Hardening Off | Secure Configuration | Low | Low | Fail |
HOST-KRN-031 | io_uring Open to Unprivileged Users | Secure Configuration | Low | Low | Fail |
HOST-LOG-001 | System Logging Not Persistent | Logging and Monitoring | Low | Low | Fail |
HOST-LOG-002 | Security Audit Daemon Not Running | Logging and Monitoring | Medium | Low | Fail |
HOST-LOG-003 | Security Logs Readable by All Users | Logging and Monitoring | Low | Low | Fail |
HOST-LOG-004 | Log Rotation Not Configured | Logging and Monitoring | Low | Low | Fail |
HOST-MAC-001 | No Mandatory Access Control Enforced | Secure Configuration | High | Low | Fail |
HOST-PAM-001 | Password Quality Module Not Enforced | Identity and Authentication | Low | Low | Fail |
HOST-PAM-002 | Account Lockout Releases Too Quickly | Identity and Authentication | Low | Low | Fail |
HOST-PAM-003 | su Not Restricted to an Administrative Group | Identity and Authentication | Low | Low | Fail |
HOST-PAM-004 | Password History Not Enforced | Identity and Authentication | Low | Low | Fail |
HOST-PAM-005 | Minimum Password Age Not Set | Identity and Authentication | Low | Low | Fail |
HOST-PAM-007 | Inactive Accounts Never Locked | Identity and Authentication | Low | Low | Fail |
HOST-PAM-009 | No Shell Idle Timeout | Identity and Authentication | Low | Low | Fail |
HOST-PKG-004 | Many Old Kernels Retained | Patch and Vulnerability Management | Low | Low | Fail |
HOST-PKG-006 | Package Lists Not Refreshed Automatically | Patch and Vulnerability Management | Low | Low | Fail |
HOST-PWD-003 | Short Minimum Password Length | Identity and Authentication | Low | Low | Fail |
HOST-SSH-005 | SSH X11 Forwarding Enabled | Secure Configuration | Low | Low | Fail |
HOST-SSH-006 | SSH Allows Many Authentication Attempts | Identity and Authentication | Low | Low | Fail |
HOST-SSH-008 | SSH Authentication Controls Too Permissive | Identity and Authentication | Low | Low | Fail |
HOST-SSH-012 | SSH Logging Level Too Low | Logging and Monitoring | Low | Low | Fail |
HOST-SSH-013 | SSH Authorized Keys Without Restrictions or Protection | Identity and Authentication | Low | Low | Fail |
HOST-SUDO-001 | Sudo Commands Not Logged to a Dedicated File | Logging and Monitoring | Low | Low | Fail |
HOST-SVC-001 | Unnecessary Legacy Services Running | Secure Configuration | Low | Low | Fail |
HOST-SVC-007 | Avahi or CUPS Installed or Enabled | Secure Configuration | Low | Low | Fail |
HOST-SVC-008 | NFS Server or rpcbind Installed or Enabled | Secure Configuration | Low | Low | Fail |
HOST-SVC-009 | DHCP or DNS Server Installed or Enabled | Secure Configuration | Low | Low | Fail |
HOST-SVC-010 | Samba File Server Installed or Enabled | Secure Configuration | Low | Low | Fail |
HOST-SVC-011 | SNMP Agent or Squid Proxy Installed or Enabled | Secure Configuration | Low | Low | Fail |
HOST-SVC-012 | inetd Super-Server Installed or Enabled | Secure Configuration | Low | Low | Fail |
HOST-SYSD-002 | Custom Services Lack Sandboxing | Secure Configuration | Medium | Low | Fail |
HOST-TIME-001 | Time Synchronisation Not Active | Logging and Monitoring | Low | Low | Fail |
HOST-UPD-001 | Automatic Security Updates Not Configured | Patch and Vulnerability Management | Low | Low | Fail |
HOST-USR-005 | System Accounts With Login Shells | Identity and Authentication | Low | Low | Fail |
HOST-USR-010 | Home Directories Accessible to Other Users | Access Control | Low | Low | Fail |
NET-DB-017 | MySQL Error Log Not Configured | Logging and Monitoring | Low | Low | Fail |
NET-DB-018 | MySQL Resolves Client Host Names | Data Services | Low | Low | Fail |
NET-DB-021 | PostgreSQL Connection Logging Off | Logging and Monitoring | Low | Low | Fail |
NET-DNS-001 | BIND Version String Disclosed | Information Exposure | Low | Low | Fail |
NET-FW-004 | Firewall Rules Open Ports With No Service | Network Exposure | Low | Low | Fail |
NET-MAIL-003 | Postfix VRFY Command Enabled | Information Exposure | Low | Low | Fail |
WEB-APA-001 | Apache Reveals Version in Header and Footer | Information Exposure | Low | Low | Fail |
WEB-APA-002 | Apache TRACE Method Enabled | Secure Configuration | Low | Low | Fail |
WEB-APA-004 | Apache AllowOverride All Permits .htaccess Control | Secure Configuration | Low | Low | Fail |
WEB-APA-007 | Apache OCSP Stapling Not Enabled | Cryptography and TLS | Low | Low | Fail |
WEB-APA-009 | Apache ETag Reveals Inode Numbers | Information Exposure | Low | Low | Fail |
WEB-APA-010 | Apache Serves Repository and Environment Files | Information Exposure | Low | Low | Fail |
WEB-APP-007 | Flask Debug Mode Enabled in Application Code | Secure Configuration | Low | Low | Fail |
WEB-CMS-001 | WordPress Version Disclosed | Information Exposure | Low | Low | Fail |
WEB-CMS-002 | WordPress XML-RPC Interface Enabled | Web Application Security | Low | Low | Fail |
WEB-CMS-003 | WordPress User Accounts Enumerable | Information Exposure | Low | Low | Fail |
WEB-CMS-007 | WordPress Dashboard File Editor Enabled | Secure Configuration | Low | Low | Fail |
WEB-CMS-010 | Joomla Version Disclosed | Information Exposure | Low | Low | Fail |
WEB-CMS-011 | Drupal Version Disclosed by Changelog | Information Exposure | Low | Low | Fail |
WEB-CMS-018 | WordPress Author Archive Reveals Login Names | Information Exposure | Low | Low | Fail |
WEB-EXP-009 | Dependency Manifests Exposed | Information Exposure | Low | Low | Fail |
WEB-EXP-010 | Default Web Server Page Served | Information Exposure | Low | Low | Fail |
WEB-HDR-004 | Missing X-Content-Type-Options | Web Application Security | Low | Low | Fail |
WEB-HDR-005 | Missing Referrer-Policy | Web Application Security | Low | Low | Fail |
WEB-HDR-006 | Missing Permissions-Policy | Web Application Security | Low | Low | Fail |
WEB-HDR-007 | Server Software Version Disclosed | Information Exposure | Low | Low | Fail |
WEB-NGX-001 | nginx Version Shown in Server Header | Information Exposure | Low | Low | Fail |
WEB-NGX-005 | nginx OCSP Stapling Off or Session Tickets On | Cryptography and TLS | Low | Low | Fail |
WEB-NODE-003 | Node.js Service Not Running in Production Mode | Secure Configuration | Low | Low | Fail |
WEB-PHP-002 | PHP Version Exposed in Headers | Information Exposure | Low | Low | Fail |
HOST-CTR-009 | Docker Not Running in Rootless Mode | Secure Configuration | High | Info | Fail |
HOST-PAM-006 | Password Expiry Warning Too Short | Identity and Authentication | Low | Info | Fail |
HOST-PKG-003 | Third-Party Package Repositories Present | Patch and Vulnerability Management | Medium | Info | Fail |
HOST-PWD-005 | Forced Periodic Password Rotation Configured | Identity and Authentication | Low | Info | Fail |
WEB-APA-008 | Apache Has No Request Filtering Module | Secure Configuration | Low | Info | Fail |
WEB-APP-008 | Dependency Lock Files Older Than a Year | Patch and Vulnerability Management | Medium | Info | Fail |
WEB-CMS-017 | WordPress Cron Reachable by Visitors | Secure Configuration | Low | Info | Fail |
WEB-NGX-006 | nginx Request Limits Not Configured | Secure Configuration | Low | Info | Fail |
WEB-SEC-001 | No security.txt Contact File | Web Application Security | Low | Info | Fail |
NET-FW-006 | Firewall Exposure Map of Listening Services | Network Exposure | Low | Info | Pass |
NET-LSN-001 | Inventory of Listening Network Services | Network Exposure | Low | Info | Pass |
Methodology
- Scope: this machine only. Every network connection is restricted in code to loopback addresses (127.0.0.0/8, ::1). No other host was contacted.
- Approach: automated, non-intrusive vulnerability assessment following the Planning, Discovery and Reporting phases of NIST SP 800-115 (its four phases are Planning, Discovery, Attack and Reporting); the Attack phase is omitted and no exploitation was attempted.
- Discovery: configuration files, /proc and /sys were read; a short allow-list of read-only commands was run (for example sshd -T and apt-get -s upgrade, which only simulates).
- Web: websites were discovered from the local web server configuration and requested through 127.0.0.1 with GET requests for fixed paths only. No forms were submitted and no attack payloads were sent.
- Rating: each check carries a qualitative severity on the CVSS v3.1 scale with a representative base vector. Environmental factors on your network may raise or lower the real risk. Detective gaps such as missing logging, auditing or integrity monitoring carry a local attack vector: a missing record opens no network path, it makes a separate intrusion harder to trace.
- Evidence: secrets (passwords, keys, tokens, hashes) were redacted before writing this report.
Limitations
- An automated self-assessment is not a penetration test. It does not prove that the machine is secure; absence of findings is not proof of absence of vulnerabilities.
- Only the checks listed in this report were performed. Application logic flaws (for example SQL injection, broken access control or business logic errors) require manual testing or code review.
- Some checks need root to read protected files or the real daemon state. A check that could not read what it needed is marked Skipped (it did not apply or could not start) or Incomplete (it ran, but part of its input was unreadable, truncated or missing); neither is a Pass.
- Results reflect the machine at the time of the scan. Configuration drift after the scan is not covered.
- End-of-life and version tables are dated and may be out of date for releases newer than this version of OpenVAPT.
- This report was produced by a pre-release build of OpenVAPT (Unreleased Build, v0.1.0-dev). Pre-release builds may be incomplete or wrong; confirm important findings by hand.
How to Cite
Report generated by OpenVAPT (unreleased build) on 2026-10-16. Using these results in research, teaching or a report? Please cite OpenVAPT.
APA 7: OpenVAPT. (2026). OpenVAPT: An open academic vulnerability assessment tool (Version unreleased build) [Computer software]. https://github.com/OpenVAPT/openvapt
BibTeX:
@software{openvapt_2026,
author = {{OpenVAPT}},
title = {{OpenVAPT: An Open Academic Vulnerability Assessment Tool}},
year = {2026},
version = {unreleased build},
url = {https://github.com/OpenVAPT/openvapt},
note = {Built by AI Cybersecurity Engineers. https://openvapt.com},
license = {LicenseRef-OpenVAPT-SAL-1.3}
}
Credit when you share this report: Produced with OpenVAPT (https://openvapt.com), built by AI Cybersecurity Engineers, used under the OpenVAPT Source-Available Licence 1.3. Use does not imply endorsement.
Generated locally by OpenVAPT. Nothing in this report was sent anywhere.