Attached is a debdiff update for nagios4 in trixie addressing the
CSRF vulnerability in cmd.cgi reported in #1136340.  No CVE has been
assigned upstream.

    Package: nagios4
    Version: 4.4.6-4.1+deb13u1
    Target distribution: trixie-security
    Closes: #1136340
Upstream fix: https://github.com/NagiosEnterprises/nagioscore/commit/e5ed38e Upstream disclosure: https://www.nagios.com/security-disclosures/nagios-core/4-5-12/

This could break some installations, so I've also backported
upstream PR #1055, which adds a `cgi_cookie_fail_open` cgi.cfg
option (default 0 = secure) so there is a documented escape hatch,
and added a section to README.Debian explaining this.

Build-tested in pbuilder against trixie.

The debian source package is available here: https://www.stuart.id.au/russell/private/nagios4_4.4.6-4.1.tar

Let me know what you would like me to do next.

--
Regards
Russell Stuart
[email protected]

diff -Nru nagios4-4.4.6/debian/changelog nagios4-4.4.6/debian/changelog
--- nagios4-4.4.6/debian/changelog      2024-06-03 08:57:17.000000000 +1000
+++ nagios4-4.4.6/debian/changelog      2026-05-22 20:45:00.000000000 +1000
@@ -1,3 +1,17 @@
+nagios4 (4.4.6-4.1+deb13u1) trixie-security; urgency=high
+
+  * CSRF Security Fix backported from upstream 4.5.12 commit
+    e5ed38e53a5d65721520c7c67be0746d63da28cb (cgi/cmd.c and
+    html/index.php.in).  See
+    https://www.nagios.com/security-disclosures/nagios-core/4-5-12/
+    for the upstream disclosure.  No CVE assigned.
+    Closes: #1136340.
+  * This can break third party integrations that POST to cmd.cgi
+    without first setting NagFormId (the CSRF check fails).  Upstream
+    PR 1055 has been added as a workaround - see README.Debian.
+
+ -- Russell Stuart <[email protected]>  Fri, 22 May 2026 20:45:00 
+1000
+
 nagios4 (4.4.6-4.1) unstable; urgency=medium
 
   * Non-maintainer upload.
diff -Nru nagios4-4.4.6/debian/patches/95_CSRF-cookie-security-fix.patch 
nagios4-4.4.6/debian/patches/95_CSRF-cookie-security-fix.patch
--- nagios4-4.4.6/debian/patches/95_CSRF-cookie-security-fix.patch      
1970-01-01 10:00:00.000000000 +1000
+++ nagios4-4.4.6/debian/patches/95_CSRF-cookie-security-fix.patch      
2026-05-22 20:12:49.000000000 +1000
@@ -0,0 +1,86 @@
+Author: Emmett Kapsner <[email protected]>
+Origin: upstream, 
https://github.com/NagiosEnterprises/nagioscore/commit/e5ed38e53a5d65721520c7c67be0746d63da28cb
+Description: CSRF security fix backported from upstream 4.5.12.
+ .
+ cgi/cmd.c: make the CSRF cookie mandatory (default formid_ok=ERROR,
+ not OK), generate a pseudo-random NagFormId cookie server-side in
+ cmd.cgi's document_header() and emit it via Set-Cookie with
+ SameSite=Strict.  Previously the cookie was generated client-side
+ by JavaScript in html/index.php, which is bypassed by attacker pages.
+ html/index.php.in: remove the now-redundant client-side cookie setter.
+ .
+ See upstream's disclosure at
+ https://www.nagios.com/security-disclosures/nagios-core/4-5-12/ .
+
+--- a/cgi/cmd.c
++++ b/cgi/cmd.c
+@@ -112,7 +112,7 @@
+ 
+ int main(void) {
+       int result = OK;
+-      int formid_ok = OK;
++      int formid_ok = ERROR;
+ 
+       /* Initialize shared configuration variables */                         
    
+       init_shared_cfg_vars(1);
+@@ -219,7 +219,6 @@
+         }
+ 
+       if (cookie_form_id && *cookie_form_id) {
+-              formid_ok = ERROR;
+               if (form_id && *form_id) {
+                       if (!strcmp(form_id, cookie_form_id))
+                               formid_ok = OK;
+@@ -241,7 +240,7 @@
+       /* the user wants to commit the command */
+       else if(command_mode == CMDMODE_COMMIT) {
+               if (formid_ok == ERROR) /* we're expecting an id but it wasn't 
there... */
+-                      printf("<p>Error: Invalid form id!</p>\n");
++                      printf("<p>Error: Invalid or missing CSRF 
cookie!</p>\n");
+               else
+                       commit_command_data(command_type);
+       }
+@@ -280,9 +279,29 @@
+       strip_html_brackets(ecmd->default_comment);
+ }
+ 
++/* generates and sets a pseudo-random cookie if one is not already set */
++void set_cookie() {
++      if (!(cookie_form_id && *cookie_form_id)) {
++              unsigned long long n = ((unsigned long long)rand() << 32) | 
rand();
++              char buffer[32];
++
++              snprintf(buffer, sizeof(buffer), "%llx", n);
++
++              cookie_form_id = strdup(buffer);
++              if (!cookie_form_id) {
++                      fprintf(stderr, "Memory allocation failed\n");
++                      exit(1);
++              }
++
++              printf("Set-Cookie: NagFormId=%s; SameSite=Strict\r\n", 
cookie_form_id);
++      }
++}
++
+ 
+ void document_header(int use_stylesheet) {
+ 
++      set_cookie();
++
+       if(content_type == WML_CONTENT) {
+ 
+               printf("Content-type: text/vnd.wap.wml\r\n\r\n");
+--- a/html/index.php.in
++++ b/html/index.php.in
+@@ -35,11 +35,6 @@
+       <meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
+       <title>Nagios: <?php echo $_SERVER['SERVER_NAME']; ?></title>
+       <link rel="shortcut icon" href="images/favicon.ico" type="image/ico">
+-
+-      <script LANGUAGE="javascript">
+-              var n = Math.round(Math.random() * 10000000000);
+-              document.cookie = "NagFormId=" + n.toString(16);
+-      </script>
+ </head>
+ 
+ <frameset cols="180,*" style="border: 0px; framespacing: 0px">
diff -Nru nagios4-4.4.6/debian/patches/96_CSRF-cookie-fail-open-option.patch 
nagios4-4.4.6/debian/patches/96_CSRF-cookie-fail-open-option.patch
--- nagios4-4.4.6/debian/patches/96_CSRF-cookie-fail-open-option.patch  
1970-01-01 10:00:00.000000000 +1000
+++ nagios4-4.4.6/debian/patches/96_CSRF-cookie-fail-open-option.patch  
2026-05-22 20:28:55.000000000 +1000
@@ -0,0 +1,97 @@
+Author: Emmett Kapsner <[email protected]>
+Origin: upstream, https://github.com/NagiosEnterprises/nagioscore/pull/1055
+Description: Add `cgi_cookie_fail_open` config option for the CSRF cookie 
check.
+ .
+ The security fix in 95_CSRF-cookie-security-fix.patch unconditionally
+ rejects any request to cmd.cgi that arrives without a valid NagFormId
+ cookie.  That is the secure default, but it also breaks legitimate
+ third-party integrations (custom dashboards, automation scripts,
+ add-ons like NagiosBP) that POST commands to cmd.cgi without first
+ visiting the web UI in the same browser session.
+ .
+ This patch (upstream PR 1055, merged 2026-04-03, scheduled for the
+ next upstream release after 4.5.12) adds a cgi.cfg option:
+ .
+   cgi_cookie_fail_open=0   (default: secure -- reject without cookie)
+   cgi_cookie_fail_open=1   (insecure: revert to pre-fix behaviour)
+ .
+ Setting it to 1 reopens the CSRF window, but is the only way to keep
+ those third-party integrations working without rewriting them to
+ authenticate via the UI first.
+ .
+ NOTE for Debian: this option is *not* in upstream 4.5.12, only in
+ the unreleased 4.5.13+.  It is present in this 4.4.6-4.1+deb12u1
+ stable security update so that bookworm users can opt back to the
+ old behaviour locally; it will disappear when the package is
+ upgraded to 4.5.12+ds via bookworm -> trixie.
+
+--- a/cgi/cgiutils.c
++++ b/cgi/cgiutils.c
+@@ -72,6 +72,7 @@
+ int           ack_no_sticky  = FALSE;
+ int           ack_no_send    = FALSE;
+ int           tac_cgi_hard_only = FALSE;
++int           cgi_cookie_fail_open = FALSE;
+ 
+ time_t          this_scheduled_log_rotation = 0L;
+ time_t          last_scheduled_log_rotation = 0L;
+@@ -448,6 +449,8 @@
+                       ack_no_send = (atoi(val) > 0) ? TRUE : FALSE;
+               else if(!strcmp(var, "tac_cgi_hard_only"))
+                       tac_cgi_hard_only = (atoi(val) > 0) ? TRUE : FALSE;
++              else if (!strcmp(var, "cgi_cookie_fail_open"))
++                      cgi_cookie_fail_open = (atoi(val) > 0) ? TRUE : FALSE;
+               else if (callback)
+                       (*callback)(var,val);
+               }
+--- a/cgi/cmd.c
++++ b/cgi/cmd.c
+@@ -44,6 +44,7 @@
+ 
+ extern int ack_no_sticky;
+ extern int ack_no_send;
++extern int cgi_cookie_fail_open;
+ 
+ #define MAX_AUTHOR_LENGTH     64
+ #define MAX_COMMENT_LENGTH    1024
+@@ -112,7 +113,6 @@
+ 
+ int main(void) {
+       int result = OK;
+-      int formid_ok = ERROR;
+ 
+       /* Initialize shared configuration variables */                         
    
+       init_shared_cfg_vars(1);
+@@ -218,6 +218,8 @@
+               return OK;
+         }
+ 
++      int formid_ok = cgi_cookie_fail_open ? OK : ERROR;
++
+       if (cookie_form_id && *cookie_form_id) {
+               if (form_id && *form_id) {
+                       if (!strcmp(form_id, cookie_form_id))
+--- a/sample-config/cgi.cfg.in
++++ b/sample-config/cgi.cfg.in
+@@ -404,6 +404,21 @@
+ 
+ 
+ 
++# CGI CSRF COOKIE CHECK BEHAVIOR
++# This option controls how the CGI handles a missing CSRF Cookie.
++# 0 (default): Fail closed - reject the request if the CSRF cookie is
++# missing or invalid. This is more secure.
++# 1: Fail open - allow the request even if the CSRF cookie check fails.
++# This reduces CSRF protection but may be required for some third-party
++# integrations.
++#
++# WARNING: Enabling fail open weakens security and should only be used
++# if you fully understand the risk.
++
++#cgi_cookie_fail_open=0
++
++
++
+ # COMMAND COMMENTS
+ # These options control whether or not comments are required, optional,
+ # or not allowed for specific commands. The format for each line is:
diff -Nru nagios4-4.4.6/debian/patches/series 
nagios4-4.4.6/debian/patches/series
--- nagios4-4.4.6/debian/patches/series 2020-08-19 21:36:35.000000000 +1000
+++ nagios4-4.4.6/debian/patches/series 2026-05-22 20:28:20.000000000 +1000
@@ -5,3 +5,5 @@
 80_no_phone_home.patch
 90_turn-off-use-authentication.path
 9103-fix-unknown-rpm-arch.patch
+95_CSRF-cookie-security-fix.patch
+96_CSRF-cookie-fail-open-option.patch
diff -Nru nagios4-4.4.6/debian/README.Debian nagios4-4.4.6/debian/README.Debian
--- nagios4-4.4.6/debian/README.Debian  2018-01-11 11:50:34.000000000 +1000
+++ nagios4-4.4.6/debian/README.Debian  2026-05-22 20:45:00.000000000 +1000
@@ -25,6 +25,44 @@
   /etc/nagios4/cgi.cfg and /etc/nagios4/apache2.conf.
 
 
+CSRF cookie in cmd.cgi
+======================
+
+  The 4.4.6-4.1+deb13u1 security update (Debian bug #1136340)
+  backports the upstream CSRF fix from Nagios Core 4.5.12.  cmd.cgi
+  now requires every command-submission request to carry a NagFormId
+  cookie that was previously issued by cmd.cgi itself; cookies
+  generated client-side in JavaScript (the pre-4.5.12 behaviour) are
+  no longer trusted.
+
+  This change can break legitimate third-party integrations that
+  POST to /cgi-bin/nagios4/cmd.cgi without first visiting the Nagios
+  web UI in the same browser session.  Typical examples are custom
+  dashboards, automation/orchestration scripts that submit external
+  commands via curl, mobile status panels, and add-ons such as
+  NagiosBP.
+
+  The symptom is: instead of the command being passed to the Nagios
+  pipe at /var/lib/nagios4/rw/nagios.cmd, cmd.cgi returns an HTTP
+  200 response whose body contains literally:
+
+    Error: Invalid or missing CSRF cookie!
+
+  Apache access logs show 200s (the error is HTML, not an HTTP
+  status), and /var/log/nagios4/nagios.log shows no incoming
+  command.
+
+  If you cannot easily rewrite the integration to authenticate
+  through the UI first, you can opt back into the pre-fix behaviour
+  by setting the following in /etc/nagios4/cgi.cfg:
+
+    cgi_cookie_fail_open=1
+
+  WARNING: this reopens the CSRF vulnerability that the fix was
+  intended to close.  Use only as a transitional measure, and
+  restrict access to cmd.cgi at the apache2 layer in the meantime.
+
+
 Default Install
 ===============
 

Attachment: OpenPGP_0xF5231C62E7843A8C.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to