Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:goaccess
User: [email protected]
Usertags: pu

[ Reason ]
This update includes 3 upstream patches fixing 3 CVEs published for
goaccess.

[ Impact ]
goaccess is a web server log analysis tool. Specially crafted requests
can explore those vulnerabilities and cause it to overwrite memory or
crash.

[ Tests ]
There is no regression in the (admittedly simple) autopkgtests.

[ Risks ]
The changes were cherry-picked from upstream, applied cleanly over the
trixie branch, and are very targeted and localized.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
The main change is adding 3 upstream patches cherry-picked from the
latest upstream release. The change to debian/salsa-ci.yml is necessary
to prevent a failure on Salsa CI related to uscan (debian/watch is fixed
in the sid/forky version of the package).

[ Other info ]
This was marked as no-DSA by the Security team so I'm going with a
stable update.

I'm attaching both the full diff against the version in trixie, and the
actual patches since those are easier to read than the diff-in-diff
version in the full diff.
diff --git c/debian/changelog w/debian/changelog
index 6a55b588..08592661 100644
--- c/debian/changelog
+++ w/debian/changelog
@@ -1,3 +1,17 @@
+goaccess (1:1.9.3-1+deb13u1) trixie; urgency=high
+
+  * Apply security updates (Closes: #1143181)
+    Includes fixes for the following vulnerabilities:
+    - CVE-2026-54715: Heap Out-of-Bounds Write in GoAccess `parse_browser()`
+    - CVE-2026-55768: GoAccess WebSocket server: signed 32 bit truncation of
+      the 64 bit frame length causes a remote pre authentication denial of
+      service
+    - CVE-2026-55777: Out-of-bounds heap read in parse_ios() via crafted
+      User-Agent (opesys.c:323) lead to remote crash/DoS
+  * debian/salsa-ci.yml: disable uscan test for this branch
+
+ -- Antonio Terceiro <[email protected]>  Mon, 17 Aug 2026 18:49:23 -0300
+
 goaccess (1:1.9.3-1) unstable; urgency=medium
 
   * New upstream version 1.9.3
diff --git c/debian/patches/0001-Fix-heap-buffer-overflow-in-parse_browser-Opera-hand.patch w/debian/patches/0001-Fix-heap-buffer-overflow-in-parse_browser-Opera-hand.patch
new file mode 100644
index 00000000..c6f244ab
--- /dev/null
+++ w/debian/patches/0001-Fix-heap-buffer-overflow-in-parse_browser-Opera-hand.patch
@@ -0,0 +1,37 @@
+From: Gerardo O <[email protected]>
+Date: Sun, 7 Jun 2026 23:13:31 -0500
+Subject: Fix heap buffer overflow in parse_browser() Opera handling
+
+Anchor the offset to the actual 'Opera' position and require the slash to be at
+or after the byte following it (op + 5 <= slh) so the destination can never run
+past the buffer's NUL terminator.
+
+(cherry picked from commit 81f90d9dafd6956c188dea9f944d24946d3d3351)
+---
+ src/browsers.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/browsers.c b/src/browsers.c
+index de0b56b..20f6fa7 100644
+--- a/src/browsers.c
++++ b/src/browsers.c
+@@ -525,7 +525,7 @@ check_http_crawler (const char *str) {
+  * Otherwise the parsed browser is returned. */
+ static char *
+ parse_browser (char *match, char *type, int i, char ***hash) {
+-  char *b = NULL, *ptr = NULL, *slh = NULL;
++  char *b = NULL, *ptr = NULL, *slh = NULL, *op = NULL;
+   size_t cnt = 0, space = 0;
+ 
+   match = char_replace (match, '+', '-');
+@@ -547,8 +547,8 @@ parse_browser (char *match, char *type, int i, char ***hash) {
+     return parse_opera (slh);
+   }
+   /* Opera has the version number at the end */
+-  if (strstr (match, "Opera") && (slh = strrchr (match, '/')) && match < slh) {
+-    memmove (match + 5, slh, strlen (slh) + 1);
++  if ((op = strstr (match, "Opera")) && (slh = strrchr (match, '/')) && op + 5 <= slh) {
++    memmove (op + 5, slh, strlen (slh) + 1);
+   }
+   /* IE Old */
+   if (strstr (match, "MSIE") != NULL) {
diff --git c/debian/patches/0002-Tighten-websocket-payload-length-handling.patch w/debian/patches/0002-Tighten-websocket-payload-length-handling.patch
new file mode 100644
index 00000000..b22792a0
--- /dev/null
+++ w/debian/patches/0002-Tighten-websocket-payload-length-handling.patch
@@ -0,0 +1,46 @@
+From: Gerardo O <[email protected]>
+Date: Mon, 15 Jun 2026 16:56:06 -0500
+Subject: Tighten websocket payload length handling.
+
+(cherry picked from commit ea74b87254d0adc675c087ff49bddd2d60dc01d5)
+---
+ src/websocket.c | 5 ++++-
+ src/websocket.h | 2 +-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/websocket.c b/src/websocket.c
+index 8088921..8da1da9 100644
+--- a/src/websocket.c
++++ b/src/websocket.c
+@@ -2027,7 +2027,7 @@ ws_get_frm_header (WSClient *client) {
+   ws_set_payloadlen ((*frm), (*frm)->buf);
+   ws_set_masking_key ((*frm), (*frm)->buf);
+ 
+-  if ((*frm)->payloadlen > wsconfig.max_frm_size) {
++  if ((*frm)->payloadlen > (uint64_t) wsconfig.max_frm_size) {
+     ws_error (client, WS_CLOSE_TOO_LARGE, "Frame is too big");
+     return ws_set_status (client, WS_ERR | WS_CLOSE, bytes);
+   }
+@@ -2049,6 +2049,9 @@ ws_realloc_frm_payload (WSFrame *frm, WSMessage *msg) {
+   uint64_t newlen = 0;
+ 
+   newlen = msg->payloadsz + frm->payloadlen;
++  if (newlen > (uint64_t) wsconfig.max_frm_size)
++    return 1;
++
+   tmp = realloc (msg->payload, newlen);
+   if (tmp == NULL && newlen > 0) {
+     free (msg->payload);
+diff --git a/src/websocket.h b/src/websocket.h
+index 2846d6b..bd575a0 100644
+--- a/src/websocket.h
++++ b/src/websocket.h
+@@ -195,7 +195,7 @@ typedef struct WSFrame_ {
+   unsigned char mask[4];        /* mask key */
+   uint8_t res;                  /* extensions */
+   int payload_offset;           /* end of header/start of payload */
+-  int payloadlen;               /* payload length (for each frame) */
++  uint64_t payloadlen;          /* payload length (for each frame) */
+ 
+   /* status flags */
+   int reading;                  /* still reading frame's header part? */
diff --git c/debian/patches/0003-Tighten-iOS-user-agent-parsing.patch w/debian/patches/0003-Tighten-iOS-user-agent-parsing.patch
new file mode 100644
index 00000000..21fc3f96
--- /dev/null
+++ w/debian/patches/0003-Tighten-iOS-user-agent-parsing.patch
@@ -0,0 +1,23 @@
+From: Gerardo O <[email protected]>
+Date: Mon, 15 Jun 2026 19:49:17 -0500
+Subject: Tighten iOS user agent parsing
+
+(cherry picked from commit ba813ed97d998dbdcb8d87e178799a4bb2da9e81)
+---
+ src/opesys.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/opesys.c b/src/opesys.c
+index f83d0c3..ca05690 100644
+--- a/src/opesys.c
++++ b/src/opesys.c
+@@ -303,7 +303,8 @@ parse_ios (char *agent, int tlen) {
+     goto out;
+ 
+   *q = 0;
+-  memmove (agent + tlen, agent + offset, offset);
++  /* Move the version suffix to sit immediately after the matched keyword. */
++  memmove (agent + tlen, p, (size_t) (q - p) + 1);
+   return char_replace (agent, '_', '.');
+ 
+ out:
diff --git c/debian/patches/series w/debian/patches/series
new file mode 100644
index 00000000..6453687c
--- /dev/null
+++ w/debian/patches/series
@@ -0,0 +1,3 @@
+0001-Fix-heap-buffer-overflow-in-parse_browser-Opera-hand.patch
+0002-Tighten-websocket-payload-length-handling.patch
+0003-Tighten-iOS-user-agent-parsing.patch
diff --git c/debian/salsa-ci.yml w/debian/salsa-ci.yml
index 33c3a640..9a157201 100644
--- c/debian/salsa-ci.yml
+++ w/debian/salsa-ci.yml
@@ -2,3 +2,6 @@
 include:
   - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
   - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
+
+variables:
+  SALSA_CI_DISABLE_USCAN: 1
From: Gerardo O <[email protected]>
Date: Sun, 7 Jun 2026 23:13:31 -0500
Subject: Fix heap buffer overflow in parse_browser() Opera handling

Anchor the offset to the actual 'Opera' position and require the slash to be at
or after the byte following it (op + 5 <= slh) so the destination can never run
past the buffer's NUL terminator.

(cherry picked from commit 81f90d9dafd6956c188dea9f944d24946d3d3351)
---
 src/browsers.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/browsers.c b/src/browsers.c
index de0b56b..20f6fa7 100644
--- a/src/browsers.c
+++ b/src/browsers.c
@@ -525,7 +525,7 @@ check_http_crawler (const char *str) {
  * Otherwise the parsed browser is returned. */
 static char *
 parse_browser (char *match, char *type, int i, char ***hash) {
-  char *b = NULL, *ptr = NULL, *slh = NULL;
+  char *b = NULL, *ptr = NULL, *slh = NULL, *op = NULL;
   size_t cnt = 0, space = 0;
 
   match = char_replace (match, '+', '-');
@@ -547,8 +547,8 @@ parse_browser (char *match, char *type, int i, char ***hash) {
     return parse_opera (slh);
   }
   /* Opera has the version number at the end */
-  if (strstr (match, "Opera") && (slh = strrchr (match, '/')) && match < slh) {
-    memmove (match + 5, slh, strlen (slh) + 1);
+  if ((op = strstr (match, "Opera")) && (slh = strrchr (match, '/')) && op + 5 <= slh) {
+    memmove (op + 5, slh, strlen (slh) + 1);
   }
   /* IE Old */
   if (strstr (match, "MSIE") != NULL) {
From: Gerardo O <[email protected]>
Date: Mon, 15 Jun 2026 16:56:06 -0500
Subject: Tighten websocket payload length handling.

(cherry picked from commit ea74b87254d0adc675c087ff49bddd2d60dc01d5)
---
 src/websocket.c | 5 ++++-
 src/websocket.h | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/websocket.c b/src/websocket.c
index 8088921..8da1da9 100644
--- a/src/websocket.c
+++ b/src/websocket.c
@@ -2027,7 +2027,7 @@ ws_get_frm_header (WSClient *client) {
   ws_set_payloadlen ((*frm), (*frm)->buf);
   ws_set_masking_key ((*frm), (*frm)->buf);
 
-  if ((*frm)->payloadlen > wsconfig.max_frm_size) {
+  if ((*frm)->payloadlen > (uint64_t) wsconfig.max_frm_size) {
     ws_error (client, WS_CLOSE_TOO_LARGE, "Frame is too big");
     return ws_set_status (client, WS_ERR | WS_CLOSE, bytes);
   }
@@ -2049,6 +2049,9 @@ ws_realloc_frm_payload (WSFrame *frm, WSMessage *msg) {
   uint64_t newlen = 0;
 
   newlen = msg->payloadsz + frm->payloadlen;
+  if (newlen > (uint64_t) wsconfig.max_frm_size)
+    return 1;
+
   tmp = realloc (msg->payload, newlen);
   if (tmp == NULL && newlen > 0) {
     free (msg->payload);
diff --git a/src/websocket.h b/src/websocket.h
index 2846d6b..bd575a0 100644
--- a/src/websocket.h
+++ b/src/websocket.h
@@ -195,7 +195,7 @@ typedef struct WSFrame_ {
   unsigned char mask[4];        /* mask key */
   uint8_t res;                  /* extensions */
   int payload_offset;           /* end of header/start of payload */
-  int payloadlen;               /* payload length (for each frame) */
+  uint64_t payloadlen;          /* payload length (for each frame) */
 
   /* status flags */
   int reading;                  /* still reading frame's header part? */
From: Gerardo O <[email protected]>
Date: Mon, 15 Jun 2026 19:49:17 -0500
Subject: Tighten iOS user agent parsing

(cherry picked from commit ba813ed97d998dbdcb8d87e178799a4bb2da9e81)
---
 src/opesys.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/opesys.c b/src/opesys.c
index f83d0c3..ca05690 100644
--- a/src/opesys.c
+++ b/src/opesys.c
@@ -303,7 +303,8 @@ parse_ios (char *agent, int tlen) {
     goto out;
 
   *q = 0;
-  memmove (agent + tlen, agent + offset, offset);
+  /* Move the version suffix to sit immediately after the matched keyword. */
+  memmove (agent + tlen, p, (size_t) (q - p) + 1);
   return char_replace (agent, '_', '.');
 
 out:

Attachment: signature.asc
Description: PGP signature

Reply via email to