Information Disclosure in Echo Go with Cockroachdb
Information Disclosure in Echo Go with Cockroachdb — how this specific combination creates or exposes the vulnerability
When building a Go API service with the Echo framework and Cockroachdb as the backend, information disclosure can occur through a combination of framework-level handling of database errors and Cockroachdb-specific error messages. Echo Go applications often bind request parameters directly to database queries, and if errors are not sanitized before being returned to the client, detailed database errors may be exposed.
For example, consider an endpoint that fetches a user by ID from a Cockroachdb table. If the query uses a placeholder that does not match the expected type or if the row does not exist, Cockroachdb returns detailed error messages that include SQL state codes and table/column names. If these errors are passed directly to Echo’s JSON responder, the client receives internal schema details that should remain hidden.
A typical vulnerable pattern in Echo Go looks like this:
func getUser(c echo.Context) error {
id := c.Param("id")
var user User
err := db.Get(&user, "SELECT * FROM users WHERE id = $1", id)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": err.Error(),
})
}
return c.JSON(http.StatusOK, user)
}
In this pattern, if Cockroachdb returns an error such as pq: relation "users" does not exist or pq: column "password_hash" does not exist, the entire error string is surfaced to the API consumer. This exposes table and column names, database driver details, and potentially indicates whether the table exists, which aids reconnaissance for an attacker.
The interaction between Echo Go routing and Cockroachdb’s PostgreSQL-compatible wire protocol plays a role here. Cockroachdb uses PostgreSQL error formats, and Go drivers like pgx or lib/pq surface these as detailed error strings. Echo Go does not automatically sanitize these errors, so developers must explicitly strip sensitive details before logging or responding.
Another vector involves logging. If the Echo Go middleware logs request parameters alongside full Cockroachdb errors, sensitive information may be persisted or exposed through log aggregation systems. Attackers who can influence log retrieval mechanisms may indirectly harvest database structure information.
To align with the scanning behavior of tools like middleBrick, which runs unauthenticated checks and maps findings to frameworks such as OWASP API Top 10, this scenario represents a clear Information Disclosure risk. The scanner may trigger error paths and inspect responses for database metadata, confirming whether detailed errors are returned.
Proper handling requires consistent error abstraction and validation before any database operation, ensuring that generic messages are returned to clients while detailed errors are recorded securely for debugging.
Cockroachdb-Specific Remediation in Echo Go — concrete code fixes
Remediation focuses on preventing raw Cockroachdb errors from reaching the HTTP response. In Echo Go, implement a centralized error handler that inspects database errors and returns uniform messages without schema details.
Use type assertions on Cockroachdb errors to detect specific PostgreSQL error codes, and map them to safe responses. Below is a secure pattern using the pgx driver:
import (
"github.com/labstack/echo/v4"
"github.com/jackc/pgx/v5/pgconn"
"net/http"
)
func safeGetUser(c echo.Context) error {
id := c.Param("id")
var user User
err := db.Get(&user, "SELECT id, username FROM users WHERE id = $1", id)
if err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) {
// Log detailed error securely, never return to client
log.Printf("db error: %s, detail: %s", pgErr.Code, pgErr.Message)
}
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": "unable to fetch user",
})
}
return c.JSON(http.StatusOK, user)
}
This approach uses errors.As to check if the error is a Cockroachdb-specific *pgconn.PgError. The detailed error is logged internally with code and message, but the client receives only a generic failure notice. This prevents exposure of table names, column constraints, or driver-specific hints.
For query construction, always validate and sanitize input before building SQL strings. Avoid concatenating user input directly into statements, even with placeholders, to reduce edge-case information leakage through malformed queries:
// Safe parameterized query example
query := "SELECT id, username FROM users WHERE id = $1"
var user User
err := db.Get(&user, query, userID)
if err != nil {
// Handle as shown above
}
Additionally, configure Echo Go middleware to catch panics and database errors globally, ensuring consistent responses across all endpoints:
func errorMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
defer func() {
if r := recover(); r != nil {
log.Printf("panic: %v", r)
c.JSON(http.StatusInternalServerError, map[string]string{
"error": "internal server error",
})
}
}()
return next(c)
}
}
By combining typed error inspection, centralized logging, and middleware safeguards, the Echo Go + Cockroachdb stack avoids disclosing database structure or operational details through API responses.