Daptin CVE-2026-41422
HIGHSeverity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:L
Lifecycle Timeline
4DescriptionGitHub Advisory
Summary
The /aggregate/:typename endpoint accepted column and group query parameters that were passed verbatim to goqu.L() - a raw SQL literal expression builder - without any validation. This bypassed all parameterization and allowed authenticated users with any valid session to inject arbitrary SQL expressions.
Impact
An authenticated low-privilege user could:
- Extract data from any table via subquery:
(SELECT group_concat(email) FROM user_account) as leak - Disclose database internals:
sqlite_version(),(SELECT sql FROM sqlite_master) - Exfiltrate cross-table data via correlated subqueries
The vulnerability was confirmed locally; user_account.email values were extracted via a crafted column parameter by a non-admin user.
Root Cause
goqu.L(userInput) in server/resource/resource_aggregate.go inserted user-supplied query parameters directly into the SQL string with no validation.
Fix (v0.11.4)
All goqu.L() calls on user-controlled input were eliminated and replaced with:
- Structural expression parsing supporting all documented API forms
- Schema-based column validation (column names checked against entity schema via
TableInfo().GetColumnByName()) - Exact-match allowlist for aggregate functions (
count,sum,avg,min,max,first,last) and scalar functions (date,strftime,upper,lower, etc.) - Safe goqu constructors (
goqu.I(),goqu.SUM(),goqu.Func()) for all generated expressions allowedTablesscope enforcement: qualified column refs (table.col) validated against root entity + explicitly joined tables only
Two additional DoS bugs were fixed in the same commit: uuid.MustParse panic on malformed UUID input and an index-out-of-range panic in ToOrderedExpressionArray on empty sort expressions.
Credits
Reported by @VashuVats.
AnalysisAI
SQL injection in Daptin's /aggregate/:typename endpoint allows authenticated low-privilege users to extract arbitrary database content via unsanitized query parameters. The column and group parameters are passed directly to raw SQL literal expressions without validation, enabling data exfiltration from any table including user credentials, database schema disclosure, and cross-table correlation attacks. Patched in version 0.11.4 which replaces all raw SQL construction with parameterized queries and schema-based validation. No evidence of active exploitation or public POC at time of analysis, though exploitation is straightforward for authenticated users.
Technical ContextAI
Daptin is a Go-based headless CMS and API server (pkg:go/github.com_daptin_daptin) that provides dynamic REST endpoints for database operations. The vulnerability exists in the aggregation endpoint handler at server/resource/resource_aggregate.go, which uses the goqu query builder library. The flaw is a classic CWE-89 SQL injection resulting from passing user-controlled input directly to goqu.L(), a raw literal expression constructor designed for trusted SQL fragments. Unlike goqu's safe constructors (goqu.I() for identifiers, goqu.SUM() for functions), goqu.L() treats its argument as a literal SQL string fragment that is embedded verbatim into the generated query. This bypasses all parameterization-the primary defense against SQL injection in prepared statements. The vulnerability is particularly severe because aggregate endpoints often run with elevated database privileges to support cross-table analytics. The fix demonstrates proper defense by replacing raw literals with structural parsing: user input is decomposed into validated components (table names checked against schema, column names verified via TableInfo().GetColumnByName(), function names matched against an exact allowlist), then reassembled using safe constructors that enforce proper escaping and quoting.
RemediationAI
Upgrade immediately to Daptin v0.11.4 or later, released at https://github.com/daptin/daptin/releases/tag/v0.11.4. This version eliminates all unsafe goqu.L() calls in the aggregation endpoint, replacing them with schema-validated column name checking, function name allowlisting, and parameterized query construction using safe goqu methods. The patch also fixes two denial-of-service bugs (uuid.MustParse panic and index-out-of-range in sort expression parsing). If immediate upgrade is not feasible, implement these compensating controls with noted trade-offs: (1) Disable the /aggregate/:typename endpoint entirely via reverse proxy URL filtering or API gateway rules-this breaks any application features depending on aggregation queries; (2) Restrict /aggregate endpoint access to admin-only via authentication middleware or network segmentation (allowlist source IPs)-this limits blast radius but does not eliminate risk from compromised admin accounts; (3) Deploy a web application firewall with rules blocking common SQL injection patterns in column/group query parameters (parentheses, SELECT/UNION keywords, sqlite_master references)-this is easily bypassed by obfuscation and provides false security. None of these workarounds are substitutes for patching; all have significant operational or security limitations.
Same weakness CWE-89 – SQL Injection
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-rw2c-8rfq-gwfv