REFACTOR: disable_warnings(InsecureRequestWarning) for the legacy DISABLE_SSL_ERRORS toggle now lives once in application.modules.plugin (Plugin base) instead of being duplicated across the Checkmk CMK2, Netbox networks, i-doit and Cisco DNA plugins — every plugin imports Plugin, so the suppression runs before any HTTP call without the per-plugin copies. VMware keeps its own ssl.create_unverified_context() because pyVmomi does not go through urllib3
FIX: i-doit sync now actually honors the account-level verify_cert, ca_cert_chain and ca_root_cert settings — the syncer was instantiated without an account so the shared HTTP path read no SSL config and silently fell back to the class default verify=True, ignoring custom CAs and disabled-verify configurations
FEAT: MSSQL/ODBC and MySQL importers optionally permit table-creation in custom_query — setting the new allow_ddl account flag lets a single custom_query do CREATE TABLE IF NOT EXISTS …; SELECT … FROM … so the importer can bootstrap its target table. Destructive keywords (DROP, TRUNCATE, DELETE, UPDATE, INSERT, EXEC, GRANT, REVOKE, REPLACE, MERGE) stay blocked even with the flag on, and the query must still contain a SELECT so the importer has rows to iterate
PERF: "Calculating Hostrules and Attributes" is fast again on large installations — the per-run Checkmk caches that were moved to instance state in the previous release made every multiprocessing worker dispatch pickle the full prefetched host/folder tables, growing pipe traffic quadratically with the host count. The worker pickle now strips the caches the worker does not read (host, folder and bulk queues), cutting per-task pickle payload from kilobytes-per-host to a few hundred bytes — roughly the difference between "stalled" and "done" at 10k-140k-host scale
FIX: Checkmk rule export no longer re-pushes rules on every run when Checkmk enriches the stored value with schema defaults — the rule comparison now treats stored-value keys that were not part of our configured value as server-side defaults instead of drift, ending the UPDATE/DELETE churn users reported on otherwise untouched rules
FIX: Jinja-rendered rule values (Checkmk rule conditions, regex patterns, passwords and other API payloads) are no longer HTML-escaped — characters like &, <, >, ' and " are passed through unchanged again, so regex conditions on service descriptions keep matching
FIX: Checkmk rule export no longer crashes with KeyError: 'value_template' after the first matching host — the speed-up in 3.12.12 made rule outcomes shared across hosts, and the export now works on its own copy instead of mutating the shared rule
FIX: Checkmk inventorize no longer crashes on labels whose name embeds a FQDN (for example piggyback_source_<host.example.com>) — dots in label-derived inventory keys are flattened to underscores, matching the HW/SW inventory path
FIX: MySQL/ODBC custom queries accept CTE (WITH ... SELECT ...) statements again — the read-only check no longer rejects valid analytical queries
FIX: Checkmk downtime sync with weekday offsets that wrap into the next week (for example Friday + 3 days) no longer crashes — the offset now rolls into the following week instead of aborting the downtime run
FIX: Checkmk host and rule syncs no longer carry state across accounts or repeated runs in one process — version info, host caches, bulk create/update queues, counters, inventorize caches, DCD rules and password IDs all start empty for each sync, preventing wrong cleanup, duplicate create/update actions and stale inventory writes
FIX: Imported Checkmk sites now receive the same source-account metadata as any other imported object, so they are covered by conflict protection, inventory sync attribution, and account lifecycle cleanup
FIX: First-time import of a host via the Checkmk v1 importer no longer crashes with AttributeError — the initial-add path now calls the existing import-sync helper
FIX: Password changes and password resets now update the last_login audit timestamp correctly (previously written to a non-existent lastLogin field, so the audit stayed stale)
FIX: POST /api/v1/objects/<hostname> now returns 403 account_conflict when a host is claimed by a different source account, and only returns 200 saved on a successful save — previously it silently returned 200 for every request regardless of the conflict state
FIX: Admin bulk actions for assigning a CMDB template and a Checkmk version no longer fail with a CSRF error — the forms now include the CSRF token like every other admin form
FIX: cmdbsyncer user create_user re-enables a previously disabled admin account again — a typo (disable vs. disabled) kept disabled accounts locked after password reset
FIX: 2FA enrollment form now includes the CSRF token, so saving a new TOTP secret works again with global CSRF protection enabled
FIX: Plugin upgrades are now atomic — a broken .syncerplugin archive no longer deletes the previously installed plugin; the installer extracts into a staging directory and only swaps in the new copy once the archive has been fully unpacked
FIX: Cached state gate in StateFile.need_update works as intended again — a typo (last_udpate) made every entry look like "never updated", bypassing the cache
FIX: Syncer rule automation re-reads host attributes on every run instead of reusing a process-wide cache, so rules are generated from the current database state and not from a stale snapshot
SEC: Logout is now POST-only with CSRF protection — a GET to /logout returns a confirmation page instead of silently ending the session, closing the trivial CSRF-logout vector
SEC: License information view is restricted to global admins — enterprise load status, registered features and hooks are no longer exposed to every authenticated user
SEC: Debug views (debug_host, debug) no longer render the hostname query parameter as an unquoted HTML attribute, closing a reflected attribute-injection / XSS vector for authenticated users
SEC: HTTP plugin debug log now redacts response bodies (access/refresh tokens, passwords, secrets) and omits non-JSON response bodies; JDisc login passes the password as a GraphQL variable instead of embedding it in the query text, so credentials no longer leak into debug logs
FIX: NetBox Dataflow sync no longer crashes with KeyError: 'custom_fields' on field-only updates — the update path only merges custom_fields when the payload actually contains custom-field changes
FIX: NetBox virtual-machine sync logs the real error on early failures again instead of masking it with an UnboundLocalError
FIX: NetBox device and virtual-machine cleanup correctly decommissions objects whose create/update call failed — the hostname is now recorded as "synced" only after the NetBox API confirmed the change
FIX: Classic on-prem Jira Insight importer now honors the account-level SSL / CA settings (verify_cert, ca_cert_chain, ca_root_cert) like every other plugin, because it routes requests through the shared HTTP path
FIX: Classic on-prem Jira importer pages through /environments and /servers until all entries are fetched, so large Jira inventories are imported completely instead of being truncated at the first page
FIX: Jira Cloud asset import now pages through AQL results until the workspace is exhausted, so large workspaces are imported completely
FIX: Jira Cloud asset import no longer aborts with IndexError when an asset attribute has an empty objectAttributeValues list — such attributes are skipped
FIX: Jira Cloud attribute-name cache is now per importer instance, so repeated Jira Cloud imports in one process can no longer carry attribute ids from one workspace into hosts imported from another
FIX: LDAP import no longer aborts when an LDAP attribute is present but has no values — such attributes are skipped and the rest of the entry is imported normally
FIX: LDAP account-level rewrite_hostname setting now actually rewrites imported hostnames (previously exposed in the UI but never applied)
FIX: YML plugin is no longer silently disabled — the trailing comma in plugin.json that made the metadata invalid JSON is removed, so plugin discovery and CLI registration pick it up again
SEC: REST and YML plugins no longer log raw request_headers to the debug log; only the header count is logged, and the actual header values still flow through the redacting shared HTTP path
FIX: REST plugin honors its path account setting again — when configured, the importer reads data from the local file instead of always going over HTTP
FIX: rewrite_hostname is now applied consistently during inventorize in CSV, MySQL, ODBC, REST, YML and JDisc — inventory data lands on the same host key as the matching import instead of diverging
FIX: JDisc inventorize covers the same nameless-device fallback as import_devices, so hosts created as unnamed-<serial> by the importer receive inventory data too
FIX: i-doit sync routes requests through the shared Plugin HTTP path, so account-level verify_cert, CA certificates, timeouts and retries are honored like in every other plugin
FIX: i-doit category cache is now per importer instance, so repeated runs or multiple accounts in one process cannot reuse stale category payloads from an earlier target
SEC: Cisco DNA plugin no longer prints raw error bodies and now applies a 60-second HTTP timeout to inventory, device and auth requests so runs cannot hang indefinitely on an unresponsive DNA Center
FIX: PRTG importer pages through /api/table.json until all devices have been fetched instead of truncating installations with more than 5000 devices
FIX: Checkmk rule export no longer deletes-and-recreates a rule when only the value drifted — if exactly one of the configured rules matches the existing Checkmk rule's condition, the value is updated in place, preserving the rule id and audit history. A delete still happens for truly orphaned rules or when multiple configured rules collide on the same condition.
FIX: BMC Remedy importer now actually creates and updates Syncer hosts from the configured Remedy class query instead of printing "Not yet implemented"; account-level verify_cert and custom CA settings are honored like in every other plugin because the request path runs through the shared HTTP client
FIX: Ansible cmk-server-source single-host lookup returns site variables again — the query now filters on the existing enabled field instead of a non-existent available field, so --host responses match --list
FIX: Ansible syncer source only returns available hosts in --list output, matching the single-host --host lookup — stale or unavailable hosts are no longer shipped in the full inventory
FIX: VMware custom-attribute export no longer crashes with UnboundLocalError when a VM's previous value is missing or falsy; the old value is looked up directly and referenced consistently in the change log
SEC: VMware cron and CLI wrappers now log exceptions and re-raise so failed syncs fail visibly with a non-zero exit status instead of silently succeeding
SEC: JDisc cron and CLI wrappers log exceptions and re-raise so failed JDisc jobs fail visibly instead of silently reporting success
FIX: JDisc handle_object() no longer masks errors with UnboundLocalError when an exception occurs before the object name has been extracted; the log entry now references the object type and a safe placeholder when the name is still unknown
FIX: JDisc application and executable imports key their Syncer objects by the owning device as well as the software name, so identically named applications or executables from different devices no longer collapse onto the same Syncer object and overwrite each other
FIX: JDisc executable import now iterates the per-device installedExecutableFiles list and uses executableFile as the object type instead of passing the entire device dict into handle_object() with the wrong key
FIX: JDisc application and executable sync skip devices whose operatingSystem block is missing or None instead of crashing the whole import/inventorize run
FIX: JDisc application and executable inventorize cover the same nameless-device fallback as the device importer when import_unnamed_devices is enabled, so software data for those devices is stored too
FEAT: Checkmk rule export is notably faster on large installations — rule updates first try a wildcard If-Match header, saving one HTTP round-trip per updated rule. The importer transparently falls back to a GET+PUT with the real ETag for Checkmk versions that reject the wildcard.
FEAT: Admin index changelog is now compact — previous version sections are collapsed by default (click to expand) and a row of links to older v*.md changelog files is shown below, so the landing page is no longer a scroll wall
FEAT: Admin header and cmdbsyncer CLI append a -dev suffix to the version while the changelog still has unreleased entries, so running off main between releases is immediately visible
Version 3.12.12
FAT: Rule engine and Checkmk host export have been heavily speed-optimized — large sync runs are dramatically faster across every plugin that goes through the rule engine
FIX: First-matching tag/value state is reset per host, so FIRST_MATCHING_TAG/FIRST_MATCHING_VALUE in custom-attribute templates never inherit a value from a previously processed host
FIX: Admin-index notices are now shown on pip-installed instances as well, not only on source checkouts
FEAT: rules export_all_rules can now also dump user accounts (including hashed passwords and roles) via --include-users, so a full instance backup is possible from a single command
Version 3.12.11
FIX: Malformed folder option suffixes in Checkmk move_folder/create_folder rules now skip the bad segment with a log entry instead of aborting the host export
FIX: Checkmk BI rule and aggregation export skips individual malformed rule templates with a log entry instead of aborting the whole run
FIX: Empty and whitespace-only label keys are rejected, and labels that normalize down to an invalid key are caught before they are persisted
FIX: Bulk inventory updates pre-validate every item before writing, so a malformed key later in the payload cannot leave earlier items persisted
SEC: Inventory API endpoints no longer implicitly create hosts — missing hosts return 404 (single) or are listed as not-found (bulk), closing an unauthenticated-ownership/hostname-validation bypass
FIX: Host label and inventory updates reject empty, $-prefixed, or dotted keys everywhere (API, plugins, importers) with a clear error instead of crashing at save time
FIX: Deleting a host whose Checkmk folder pool entry no longer exists now succeeds instead of crashing with 500
FIX: /api/v1/objects/all now rejects non-integer or negative pagination parameters with a clean 400 instead of crashing with 500
SEC: Checkmk site version-filename setting is rendered in a sandboxed Jinja environment, blocking code execution through the admin-editable template
SEC: i-doit custom rule templates run in a sandboxed Jinja environment, blocking code execution through rule parameters
FIX: API authentication no longer returns 500 when multiple users share the same name; the candidate whose password matches is used
SEC: API users with no roles configured are now rejected instead of being granted full API access
SEC: LDAP imports now require an encrypted channel — plain ldap:// connections are upgraded via StartTLS before the bind, and unencrypted binds are only performed if explicitly opted in per account
SEC: Admin actions that change state (activating pending changes, cloning an entry) now require a POST and a CSRF token; cloning asks for confirmation before running
SEC: ODBC plugin no longer writes account passwords to the debug log
SEC: ODBC/MSSQL connections now validate the server's TLS certificate by default; the previous "trust any certificate" behaviour is now opt-in per account
SEC: ODBC plugin no longer writes account passwords to the debug log
SEC: Admin actions that change state (activating pending changes, cloning an entry) now require a POST and a CSRF token; cloning asks for confirmation before running
Version 3.12.10
FIX: cmdbsyncer sys self_configure now runs on a PyPI install and seeds local_config.py and the plugins/ directory from any working directory
FIX: PyPI installs can now read the local_config.py in the current working directory
FIX: PyPI installs show the current version's changelog on the admin index again (shipped with the wheel instead of only the source checkout)
FIX: run_tests.sh discovers plugin test suites again — each tests/ directory is now passed as its own top_level_dir so the tests/__init__.py bootstrap that stubs application is no longer re-shadowed by auto-discovery
FIX: Test suite discovers plugin tests again
Version 3.12.9
FIX: PyPI installs no longer crash on first start when no custom plugins folder exists
Version 3.12.8
FIX: PyPI installs no longer crash at startup when no custom plugins folder exists
FEAT: cmdbsyncer sys self_configure creates the plugins/ directory automatically so custom plugins can be dropped in without manual setup
Version 3.12.7
SEC: Password reset tokens are now bound to the password timestamp, carry a purpose claim, and include jti/iat; a token becomes invalid as soon as the password is changed and cannot be reused for other actions
SEC: Remote-user and LDAP login errors are no longer shown to the user; details (including traceback) are written to the system log instead
SEC: Syncer REST API (/logs, /services/<name>) no longer returns the Python traceback field — internal file paths and stack frames are no longer exposed to API clients
SEC: Login and password-reset POST requests are now rate-limited per client IP (default 3 per minute, 10 per hour) via Flask-Limiter; configurable via AUTH_RATE_LIMIT and RATELIMIT_STORAGE_URI
SEC: REST API authentication is now rate-limited per client IP against failed attempts — only 401 responses count, so legitimate high-volume API traffic is unaffected while brute-force and credential-stuffing attempts are throttled (shares the AUTH_RATE_LIMIT setting)
SEC: Plugin HTTP request debug logging (logger.debug) now masks sensitive fields — Authorization/API-key headers, auth tuples, client certs, and body/param keys like password, token, api_key, secret, refresh_token. The save_requests file dump still contains the full payload by design (debug replay) and must be protected on the filesystem.
SEC: HTML-escape changelog text in the admin index before rendering
SEC: Re-enable CSRF protection for the File Admin
SEC: API HTTPS gate no longer trusts X-Forwarded-Proto directly; added TRUSTED_PROXIES config (default 0) that enables proxy-header rewriting only when explicitly set — prevents header-spoofing bypass of the HTTPS requirement for password-based API auth
SEC: API HTTPS gate no longer treats the client-supplied Host: localhost header as trusted local traffic; password-based API authentication now stays blocked on plain HTTP unless the request really comes from loopback or ALLOW_INSECURE_API_AUTH is enabled
SEC: Host log preview in the admin detail view now HTML-escapes log entries before rendering, preventing stored XSS when imported or API-supplied values contain HTML/JavaScript