HIGH sql injectionfibercockroachdb

Sql Injection in Fiber with Cockroachdb

Sql Injection in Fiber with Cockroachdb — how this specific combination creates or exposes the vulnerability

SQL injection in a Fiber application using CockroachDB arises when user-controlled input is concatenated into SQL strings rather than passed as parameterized values. CockroachDB, like other SQL databases, treats literal values and SQL syntax distinctly; failing to separate them allows an attacker to alter query structure. For example, an endpoint that builds a query by string interpolation can allow an attacker to append always-true conditions or additional statements, bypassing authentication or extracting data.

Consider a login handler that interpolates a username directly into a SQL string:

query := "SELECT id, password FROM users WHERE username = '" + username + "'"

If username is admin' --, the resulting query comments out the password check, potentially granting unauthorized access. CockroachDB’s SQL compatibility with PostgreSQL means common injection patterns such as UNION SELECT or nested subqueries work the same way. Because Fiber does not enforce any SQL safety layer, it is the developer’s responsibility to ensure queries are parameterized. The risk is not in CockroachDB itself but in how the driver is used: string concatenation or incorrect usage of the database/sql interface enables injection. In a black-box scan, middleBrick tests endpoints that accept input in URLs, headers, and JSON bodies, attempting to inject payloads such as ' OR 1=1 -- to see if authentication or data boundaries are bypassed.

Additional exposure occurs when dynamic database names or table names are constructed from user input, which cannot be parameterized with prepared statements. In such cases, strict allow-listing and schema validation are required. middleBrick’s checks for input validation and property authorization highlight these weaknesses by analyzing request surfaces and, where possible, inspecting OpenAPI specs to identify parameters that flow into query construction.

Cockroachdb-Specific Remediation in Fiber — concrete code fixes

Remediation centers on using parameterized queries and prepared statements so that user input is never interpreted as SQL. With CockroachDB and the pgx driver (or any database/sql-compatible driver), always use placeholders and pass arguments separately. Below are concrete, working examples for Fiber handlers.

Parameterized query with placeholders

Use $1, $2 style placeholders (PostgreSQL-compatible) and pass values as arguments. This ensures input is treated strictly as data.

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/gofiber/fiber/v2"
	"github.com/jackc/pgx/v5/pgxpool"
)

func main() {
	pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:26257/dbname?sslmode=disable")
	if err != nil {
		log.Fatalf("unable to connect: %v", err)
	}
	defer pool.Close()

	app := fiber.New()

	app.Get("/user/:id", func(c *fiber.Ctx) error {
		var userID string = c.Params("id")
		var name, email string
		// Safe: parameterized query
		row := pool.QueryRow(c.Context(), "SELECT name, email FROM users WHERE id = $1", userID)
		if err := row.Scan(&name, &email); err != nil {
			return c.Status(http.StatusNotFound).SendString("not found")
		}
		return c.JSON(fiber.Map{"name": name, "email": email})
	})

	log.Fatal(app.Listen(":3000"))
}

Prepared statement with db.Prepare

Prepare a statement once and reuse it; this is efficient and safe. Avoid preparing statements per request in high-load scenarios, but it remains correct.

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/gofiber/fiber/v2"
	"github.com/jackc/pgx/v5/pgxpool"
)

func main() {
	pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:26257/dbname?sslmode=disable")
	if err != nil {
		log.Fatalf("unable to connect: %v", err)
	}
	defer pool.Close()

	// Prepare once, reuse
	stmt, err := pool.Prepare(context.Background(), "get_user", "SELECT name, email FROM users WHERE id = $1")
	if err != nil {
		log.Fatalf("prepare failed: %v", err)
	}
	defer stmt.Close(context.Background())

	app := fiber.New()

	app.Get("/user/:id", func(c *fiber.Ctx) error {
		var userID string = c.Params("id")
		var name, email string
		row := pool.QueryRow(c.Context(), stmt, userID)
		if err := row.Scan(&name, &email); err != nil {
			return c.Status(http.StatusNotFound).SendString("not found")
		}
		return c.JSON(fiber.Map{"name": name, "email": email})
	})

	log.Fatal(app.Listen(":3000"))
}

INSERT with multiple values

When inserting, use placeholders for each value and avoid building column lists dynamically from user input. If dynamic columns are unavoidable, use an allow-list and quote identifiers carefully (not via placeholders, which are for values only).

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/gofiber/fiber/v2"
	"github.com/jackc/pgx/v5/pgxpool"
)

func main() {
	pool, err := pgxpool.New(context.Background(), "postgres://user:pass@localhost:26257/dbname?sslmode=disable")
	if err != nil {
		log.Fatalf("unable to connect: %v", err)
	}
	defer pool.Close()

	app := fiber.New()

	app.Post("/user", func(c *fiber.Ctx) error {
		var body struct {
			Name  string `json:"name"`
			Email string `json:"email"`
		}
		if err := c.BodyParser(&body); err != nil {
			return c.SendStatus(http.StatusBadRequest)
		}
		// Safe: placeholders for values
		_, err = pool.Exec(c.Context(), "INSERT INTO users (name, email) VALUES ($1, $2)", body.Name, body.Email)
		if err != nil {
			return c.SendStatus(http.StatusInternalServerError)
		}
		return c.SendStatus(http.StatusCreated)
	})

	log.Fatal(app.Listen(":3000"))
}

Additional remediation steps include validating and allow-listing identifiers (table/column names) if dynamic SQL is required, and using the principle of least privilege for the database user used by Fiber. middleBrick’s checks for authentication, input validation, and property authorization can help surface remaining injection risks in unauthenticated and authenticated scans.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Can parameterized queries completely prevent SQL injection in Fiber with CockroachDB?
Yes, when used consistently for all values. Parameterized queries ensure user input is never interpreted as SQL syntax. However, identifiers (table/column names) cannot be parameterized and must be validated via allow-listing and careful quoting.
Does middleBrick test for SQL injection in unauthenticated scans?
Yes, middleBrick runs unauthenticated black-box tests, attempting common injection payloads in URL paths, query parameters, headers, and JSON bodies to detect whether inputs influence SQL execution.