github mickem/nscp 0.12.2

pre-release3 hours ago

What's Changed

This release follows 0.12.1 and is a security-hardening release. Many listener-side defaults are now safer, several long-standing bugs are fixed, and a handful of new modules and commands ship. Read the breaking changes section before upgrading — a few defaults changed in ways that can refuse connections or fail startup if your existing configuration relied on the old behaviour.


⚠️ Breaking changes

Empty allowed hosts now rejects all connections (fail-closed)

Previously an empty allowed hosts = setting was treated as "allow any source". It now rejects every connection and logs the reason.

If you genuinely want to expose the agent to any source, set it explicitly:

allowed hosts = 0.0.0.0/0,::/0

The change is to prevent configurations from drifting to empty by mistake silently turning into open listeners.

Scheduler cron expressions now evaluate in local time by default (fixes #570)

The Scheduler module previously used UTC as its reference clock, so a cron entry like 40 15 * * * fired at 15:40 UTC regardless of the host time zone. The default has changed to local time, which matches standard cron semantics — that entry now fires at 15:40 host-local time. Hour and minute fields in cron schedules will shift accordingly on non-UTC hosts.

A new timezone setting under the [/settings/scheduler] section controls the reference clock:

[/settings/scheduler]
timezone = local                          ; default — standard cron semantics
; timezone = utc                          ; restore the pre-0.12 behaviour
; timezone = EST-05EDT,M3.2.0,M11.1.0     ; any POSIX TZ string is honoured

Accepted values match the existing NSClient++ timezone semantics (shared with check_uptime): local (default), utc/gmt, or any POSIX TZ string parseable by Boost. IANA names such as Europe/Stockholm are not supported — use the POSIX form. Unparseable values fall back to UTC and surface as UTC? in any timezone label so the misconfiguration is visible.

check_nt (NSClientServer): TLS is on by default

The legacy check_nt protocol carries the password in every request, so the listener now defaults to ssl = true. The server does not refuse to start if TLS is off — check_nt's SSL path has always been best-effort and many third-party clients never implemented it — but it will log a startup warning when TLS is off and another when a password is configured, suggesting a switch to NRPE or NSCA-ng.

If you need to keep the old plaintext behaviour for legacy clients, set ssl = false explicitly in the [/settings/NSClient/server] section.
The change is intentionally an opt-out: defaulting on makes "no transport security" a deliberate, visible choice rather than a silent
default.

check_nt: the literal password None no longer authenticates

Previously, if no server password was configured, a client sending the literal word None was accepted. An empty server password now rejects all requests outright. Configure a password (or, preferably, switch to a modern protocol such as NRPE or NSCA-ng).

The listener now also returns a generic ERROR: Bad request. instead of distinct Invalid password / No command specified errors, removing the oracle that allowed online password guessing.

WEBServer: /auth/token and /auth/logout removed (HTTP 410)

These legacy endpoints accepted the password and session token as URL query parameters, which leaked credentials into browser history, proxy logs, and Referer headers. They now return 410 Gone.

Migrate to:

  • POST /api/v2/login with Authorization: Basic to obtain a token
  • DELETE /api/v2/login with Authorization: Bearer to log out

WEBServer: ?TOKEN= / ?__TOKEN= query-string token auth removed

For the same reason, supplying the session token as a URL query parameter on any other endpoint is no longer accepted. The server logs the rejection and returns 403. Send the token in one of the header-based forms instead:

  • Authorization: Bearer <token>
  • TOKEN: <token>
  • X-Auth-Token: <token>

WEBServer: anonymous access is now opt-in

A role named anonymous registered in settings is silently ignored unless the new allow_anonymous flag is enabled. Two knobs are required to expose endpoints without authentication; one accidental setting is no longer enough.

CheckExternalScripts: malformed alias commands are refused at startup

The fallback "split-on-space" parser used when the principal command parser failed has been removed. Aliases whose command line does not parse cleanly are now refused with an error in the log instead of being silently registered with surprising tokenisation. Review your logs after upgrading and fix any flagged alias definitions.

WEBServer: existing admin user is no longer overwritten

If you manually configured the admin user, it will no longer be overwritten on subsequent boots. This may change behaviour for
deployments that relied on the password being reset to the default on restart.


✨ New modules and features

NSCA-ng client (#1255)

A new NSCAngClient module ships, providing a hardened NSCA-ng submission client with PSK support, AEAD-first cipher selection, and connection retry logic.

SMTPClient module rewrite

The SMTPClient module has been substantially rewritten with proper SMTP handling, integration tests, and a Python-based test harness.

check_nscp_update command

A new check command that queries the GitHub releases API (with caching) and reports whether the running NSClient++ is up to date. The User-Agent includes the current version.

nscp settings --sort

The settings CLI gained a --sort flag to produce stable, sorted output — useful for diffing exported settings between hosts.

Performance threshold min/max bounds

Performance data threshold expressions can now declare minimum and maximum bounds, propagated into the emitted perfdata.

check_pdh "counter=\\Processor(_Total)\\% Processor Time"  "perf-config=*(minimum:0;maximum:100)"

CheckDisk: filesystem filtering for drive size checks

check_drivesize can now filter drives by filesystem type (for example, to exclude tmpfs or nfs mounts).

check_drivesize drive=* "filter=fs = 'NTFS'"

Timezone-aware check_uptime

check_uptime now correctly applies a timezone cache on both Windows and Unix, so absolute boot-time output and filter expressions agree with the host's local time.

WEBServer: cookie attribute support

Cookies can now declare Secure, HttpOnly, SameSite, Path, Domain, Expires, and Max-Age attributes.

WEBServer: password hashing with constant-time verification

User passwords are now hashed and verified with a constant-time comparison, removing the timing oracle on the previous plaintext
equality check.

WEBServer: authentication rate limiter

A new per-source rate limiter throttles failed authentication attempts to slow online brute-force attacks. Two settings tune (or disable) it:

[/settings/WEB/server]
auth rate limit max failures   = 10   ; 0 disables the limiter
auth rate limit block seconds  = 60

🐛 Bug fixes

  • #581CheckLogFile now honours the line-split argument (previously hard-coded to \n); multi-character delimiters such as
    \r\n are also handled correctly.
  • #589 — Time/duration arguments such as time=3000foobar or time=3000mfoobar are no longer silently accepted; malformed inputs are now rejected with a clear error.
  • #669 — The literal U (Nagios "undefined") in performance data is preserved end-to-end instead of being coerced to 0. Only an exact U, u, U%, or u% token matches; values like Unknown or Unicorn no longer trigger the marker.
  • #570 — Scheduler cron expressions now run in local time (see breaking change above).
  • #419, #595, #370, #205 — Several long-standing settings/format issues, fixed alongside nscp settings --sort.
  • CheckLogFile real-time seek behaviour fixed; CRLF handling harmonised.
  • Metrics collection regression fixed (some metrics were silently dropped).
  • NSCA wire timestamps are now correctly built in UTC. Previously both the server (IV packet) and client (data packet) emitted
    seconds-since-epoch derived from second_clock::local_time(), which drifted by the host's TZ offset. The new replay-window check exposed the bug as skew=-7200s-style errors on non-UTC senders; the wire format itself was always supposed to be Unix time.
    A timezone setting is available on both ends for legacy interop:
    • [/settings/NSCA/server] timezone = utc (default)
    • [/settings/NSCA/client/targets/<target>] timezone = utc (default;
      also --timezone on the CLI)
      Set both ends to local (or any POSIX TZ string) only when peering with an old agent that emits local-clock-as-Unix-time stamps. Both
      ends must agree.
  • Connection and process logging is more verbose at error/timeout boundaries to aid traceability.

🔒 Security hardening (defense in depth)

These do not change documented behaviour for well-formed traffic but close down attacker-controlled edge cases.

DoS / resource-exhaustion limits

  • Authorization header capped at 8 KiB to mitigate amplification.
  • Per-connection parser buffer cap to prevent memory pinning from oversized or never-completed requests.
  • Session token cap with eviction to prevent unbounded memory growth.
  • Payload lengths below the protocol minimum are rejected before allocation.
  • Path expansion now detects cycles and refuses to recurse, preventing stack overflow on pathological configurations.

NSCA hardening

  • Packet version is checked.
  • Timestamp validation tightened to mitigate replay attacks.

Log/output injection prevention

Control characters are stripped from values before they are written to external sinks, removing log/protocol-injection vectors:

  • Log file entries (file names and messages)
  • syslog messages (CR/LF/NUL stripped)
  • Graphite metric paths and values
  • HTTP response headers (header keys and values)
  • log_status is now JSON-serialised so attacker-controlled fields cannot inject extra structured fields

Filesystem / process safety

  • PID file creation hardened against symlink attacks; exclusive access enforced.
  • Archive extraction now has a zip-slip guard that validates entry paths and refuses traversal sequences.
  • Module and script names are validated to prevent path traversal at load time.
  • Argument substitution in external scripts is isolated to prevent command injection through user-controlled tokens.

Cryptography / TLS

  • HTTPS now logs explicitly when no certificate is present and warns on HTTP fallback in production.
  • SSL connections enable hostname verification by default.
  • Auto-generated passwords use OpenSSL RAND_bytes (cryptographically secure) instead of the previous predictable generator.
  • Sensitive values are no longer logged at debug level.

Other

  • simpleini.h switched from sprintf to snprintf.
  • Windows credential blob size now correctly accounts for wchar_t width.
  • check_nt password compare is constant-time (see breaking changes).

Upgrading

  1. Audit allowed hosts on every node — empty values now reject everything.
  2. check_nt (NSClientServer) now defaults to ssl = true. If your clients don't speak TLS, set ssl = false explicitly. Either way the listener will log a warning at startup if TLS is off or a password is configured, recommending a switch to REST or NRPE — informational, not a hard failure.
  3. Replace any client that calls /auth/token or /auth/logout with the /api/v2/login flow.
  4. If you use the Scheduler module with cron expressions on a non-UTC host, expect schedules to shift to local time. Either update them to the host's local time, or set [/settings/scheduler] timezone = utc to restore the previous behaviour.
  5. Restart the service and review the log for new "refused alias" or "rejected connection" warnings — these flag configurations that were previously silently accepted.

Full Changelog: 0.12.1...0.12.2

Don't miss a new nscp release

NewReleases is sending notifications on new releases.