GHSA-f46q-3v67-fmm4: SQL Injection
Summary The V4StatisticsQuery handler passes the user-supplied rawquery field directly to DuckDB without calling the sqlvalidator.ValidateRawSQL function used throughout the rest of the codebase. Any authenticated user can execute arbitrary SQL statements against all data accessible through the FlightSQL service.
Details coordinator/handlers/statisticsv4.go lines 74-107 — V4StatisticsQuery: go query := &model.V4StatisticsQuery{} if err = c.Bind(query); err != nil { ... } // No ValidateRawSQL call here — contrast with other handlers: results, err := h.flightService.Query(c.Request().Context(), query.RawQuery)
Contrast with coordinator/handlers/search.go line 194 — secure pattern not followed: go if err := sqlvalidator.ValidateRawSQL(rawQuery); err != nil { return c.JSON(http.StatusBadRequest, ...) }
query.RawQuery is whatever the caller submitted; it is passed verbatim to the FlightSQL/DuckDB backend. The handler is registered under the protected group (requires JWT), but given that the default JWT secret is empty (see related advisory), this is effectively pre-authentication on a default deployment.
PoC bash With a valid JWT (or empty JWT secret bypass): curl -s -X POST http://<homer-host>/api/v4/statistics/query \ -H "Authorization: Bearer <jwt>" \ -H "Content-Type: application/json" \ -d '{ "param": { "query": [{"rawquery": "SELECT FROM informationschema.tables"}] } }' Returns all table names accessible to the DuckDB FlightSQL service
Exfiltrate all stored call records: "rawquery": "SELECT FROM hep LIMIT 1000" Arbitrary DuckDB SQL is accepted including INSTALL/LOAD for extension-based exfiltration
Impact SQL Injection / Improper Neutralization of Special Elements (CWE-89). Any authenticated user can execute arbitrary SQL against all data accessible to the FlightSQL/DuckDB backend — including all stored VoIP call records, SIP messages, and metadata. Combined with the authentication bypass when JWT secret is empty, this is exploitable without credentials.
Fix Apply sqlvalidator.ValidateRawSQL() to query.RawQuery before passing it to h.flightService.Query(), matching the pattern already used in search.go and transactionsv4.go.
If possible, please apply for a CVE number when posting.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
go/github.com/sipcapture/homer-appto a version that resolves this vulnerability.Fixed in 0.0.0-20260625085520-a7d027dc684b - Compensating control
In the V4StatisticsQuery handler, call sqlvalidator.ValidateRawSQL() on query.RawQuery before passing it to h.flightService.Query(), matching the validation pattern used in search.go and transactions_v4.go.
Event History
Frequently Asked Questions
Who can exploit this issue in practice?
The handler is in a JWT-protected route, so an attacker needs a valid JWT. However, the advisory states that the default JWT secret is empty, making default deployments effectively exposed before authentication is meaningfully enforced.
What level of access does successful exploitation provide?
An attacker can submit arbitrary SQL statements to DuckDB through the FlightSQL service. This can affect all data that the FlightSQL service can access, with high confidentiality and integrity impact.
How can I determine whether an installation is affected?
Check whether the deployed code's V4StatisticsQuery handler passes the supplied rawquery directly to flightService.Query without first calling sqlvalidator.ValidateRawSQL. Also assess whether the deployment uses the default empty JWT secret, which can make the protected endpoint accessible without a properly secured JWT configuration.
What can be done if the fix cannot be deployed immediately?
Ensure the JWT secret is explicitly configured to a strong non-empty value so the protected route cannot be accessed using the default authentication configuration. Restrict access to the FlightSQL service and the affected endpoint to trusted users and networks.