Documentation / Monitoring and security
Security Checks
The full catalogue of automated security checks calmo.cloud runs against each Odoo service, with the points each one deducts.
calmo.cloud runs the following checks against every running live and test Odoo service. Each check is a black-box probe of the service's platform hostname, or of its server's address for the port checks. Nothing is installed inside your Odoo. How the points add up to a grade is explained in the Security overview.
The public Odoo Security Check runs the same catalogue, with one difference: it tests login brute-force protection instead of checking for fail2ban.
Critical #
Each critical check deducts 40 points, except the default admin password, which deducts all 100.
Default admin password changed (−100) #
Tries to log in as admin with the password admin. A successful login means anyone on the internet can take over the database. The check needs the database name. If that is unknown, the result is Not confirmed and deducts nothing.
Fix: log in to Odoo and change the admin user's password to a strong, unique value.
Fail2ban protection active (−40) #
Checks that fail2ban is enabled and running on the service's server. Without it, nothing stops an attacker from guessing SSH and Odoo passwords. This check only runs in the panel.
Fix: enable fail2ban on the server's Fail2ban tab. See Fail2ban.
TLS certificate (−40) #
Checks for TLS 1.2 or newer with a valid certificate for the hostname. The check fails if the certificate is invalid, expires within 14 days or uses a weak key (RSA below 2048 bits, EC below 256 bits). Check details shows a grade from A to D for the certificate itself.
Fix: check that the hostname points at the server so the certificate can renew. See Adding a domain.
HTTPS enforced (−40) #
Sends a plain HTTP request to the login page. It must redirect to HTTPS on the same host or be refused. Otherwise credentials and session cookies can be intercepted.
Fix: check that the server's proxy is healthy and the service has a valid certificate.
Legacy TLS protocols rejected (−40) #
TLS 1.0 and 1.1 must be refused. This check only runs once the certificate check has passed.
Deprecated TLS ciphers rejected (−40) #
A sample of broken cipher suites (null, anonymous, export, RC4, DES and 3DES) must be refused.
Database manager not exposed (−40) #
Requests /web/database/manager and /web/database/selector. Both must be refused. The database manager can create, drop and back up databases behind the master password, and the selector hands out the list of databases on the host. Odoo serves both behind the same list_db setting, so they count as one check.
Fix: set list_db = False and a strong admin_passwd in the Odoo configuration, then redeploy the service. On calmo.cloud, the proxy blocks both pages.
Database list RPC disabled (−40) #
Calls the JSON-RPC endpoint /web/database/list. Even when the selector page is blocked, the endpoint can still leak database names.
Fix: configure dbfilter and set list_db = False.
Private attachment protected (−40) #
Fetches a sample attachment (/web/content/10) without logging in. If the attachment is public anyway, the check is skipped rather than failed, because a public attachment is not a leak.
PostgreSQL port protected (−40) #
Checks whether PostgreSQL answers on port 5432 from the internet. Only a TLS handshake request is sent. No login is attempted.
Direct Odoo port protected (−40) #
Odoo must not answer directly on port 8069, bypassing the proxy and its protections.
Traefik dashboard protected (−40) #
The proxy's dashboard must not answer on port 8080.
Docker API protected (−40) #
The unencrypted Docker API must not answer on port 2375. Anyone who reaches it controls the server.
Warning #
Odoo version in standard support (−6) #
Reads the Odoo version and checks that Odoo still supports it. Each version is supported for three years: 18.0 until October 2027, 19.0 until October 2028 and 20.0 until October 2029. 17.0 and older have left standard support. A version that cannot be read is Not confirmed.
Fix: upgrade to a supported release. Try the upgrade on a copy first.
Login brute-force protection (−6) #
Public check only. Sends up to 50 failed logins with a random test account, one per second, and passes as soon as the Odoo starts blocking them. It fails only if all 50 are rejected without a block. These attempts may show up in your logs. Odoos on calmo.cloud servers with fail2ban pass without the test. In the panel, the fail2ban check above takes its place.
HSTS header present (−3) #
The login page must send a Strict-Transport-Security header with a max-age of at least six months (15552000 seconds). HSTS tells browsers to always use HTTPS for your domain.
Clickjacking protection (−2) #
The login page must send X-Frame-Options: DENY or SAMEORIGIN, or a restrictive frame-ancestors directive in its Content-Security-Policy. Without one, the login page can be embedded in a malicious page.
Session cookie protected from scripts (−2) #
Every session_id cookie must be marked HttpOnly, so scripts injected into a page cannot read it.
Login cross-origin access restricted (−2) #
The login page must not allow any website to send credentialed requests to it, which would happen if it echoes back any Origin together with Access-Control-Allow-Credentials: true.
Website info not disclosed (−1) #
Requests /website/info, which shows the exact Odoo version and installed modules on some versions. It must be refused. On calmo.cloud, the proxy blocks it.
Server header does not leak version (−1) #
The Server and X-Powered-By headers must not name the software behind the site (Werkzeug, Odoo, Python, PHP, ASP.NET) or a version number. Hiding them does not stop an attack but slows automated scanners.
MIME-sniffing protection (−1) #
The login page must send X-Content-Type-Options: nosniff.
Referrer policy (−1) #
The login page must send a Referrer-Policy that keeps full URLs from leaking to other sites, for example strict-origin-when-cross-origin.
Internal errors hidden (−1) #
The login page and a missing page must not show a Python traceback or a database error.
Login resources use HTTPS (−1) #
The login page must not load scripts, styles or images over plain HTTP.
Direct websocket port protected (−1) #
Odoo's websocket port 8072 must not answer from the internet.
Info #
Login page reachable #
Confirms that /web/login answers and looks like Odoo. It deducts no points, but no other check is meaningful until it passes: if the login page is not reachable, the service gets no grade.
Skipped and unconfirmed checks #
A check is skipped when it does not apply, and not confirmed when it could not be verified, for example the default password check without a database name. Neither deducts points, but the rating is marked as incomplete. The public check skips the five port checks when the Odoo sits behind a CDN, because only the CDN would answer.