GHSA-47r2-v3x6-wff9: ShellHub has crash-DoS via field injection in filter and sort-by parameters
SummaryThe 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 `name` field of each filter property in the base64-encoded `filter`
query parameter.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 versionsShellHub Community v0.24.1 (validated). All versions sharing the same filter and sort pipeline (`api/store/mongo/query-options.go`).Root causeVector 1 — Filter field name`api/store/mongo/query-options.go:140`:`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 fieldSimilar 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.Proof of concept (validated live against v0.24.1)**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:**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**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.**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)**Validate `value` shape.** For `contains`/`eq`/`ne` operators, 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.
CVSS v3.1: 5.4