Injection

Injection in Go (Gin) - Remediation [Apr 2026] [CVE-2026-34825]

[Updated Apr 2026] Updated CVE-2026-34825

Overview

CVE-2026-34825 describes an injection flaw in NocoBase where the plugin-workflow-sql component substituted template variables directly into raw SQL strings via getParsedValue() without parameterization or escaping. Before version 2.0.30, this allowed an attacker triggering a workflow containing a SQL node with user-controlled template variables to inject arbitrary SQL, leading to data exfiltration, modification, or even takeover if the attacker could craft state-changing statements. This is a classic SQL Injection (CWE-89) risk and was mitigated by patching in NocoBase version 2.0.30. In Go (Gin) applications, the same risk manifests when developers build SQL queries by concatenating user input or template substitutions into strings; such patterns enable attackers to alter the intended query logic, not just its data, with potentially severe consequences. The remediation guidance here maps the same protective principles to Go (Gin) code to prevent injection in custom service routes and handlers. In practice, an unsafe Gin handler could read user input and interpolate it directly into a SQL string, e.g., selecting or updating records based on untrusted values. Attackers can embed SQL fragments into input fields, query parameters, or JSON payloads that are then concatenated into SQL statements. The result is an attacker-controlled query that can bypass authentication, read or mutate data, or damage the database. The fix is to eliminate string interpolation of user data in SQL, and use parameterized queries or prepared statements with proper placeholders. To fix this in Go (Gin) code, always parameterize user input in SQL statements. Use placeholders appropriate to your driver (for MySQL, use ?; for PostgreSQL, use $1, etc.) and pass user data as separate arguments to db.Query/Exec or prepared statements. Prefer db.QueryRow/db.Exec with parameterized queries, or a small SQL builder/ORM that enforces parameterization. Validate inputs where feasible, employ least-privilege DB accounts, and add tests to ensure inputs never end up in raw SQL strings. The example codeFixExample demonstrates both a vulnerable pattern and a safe alternative in a Gin context.

Affected Versions

NocoBase <= 2.0.29; plugin-workflow-sql before 2.0.30

Code Fix Example

Go (Gin) API Security Remediation
package main

import (
  "database/sql"
  "log"
  "net/http"

  "github.com/gin-gonic/gin"
  _ "github.com/go-sql-driver/mysql"
)

// Vulnerable: builds SQL by concatenating user input into the query string
func vulnerableUserHandler(db *sql.DB) gin.HandlerFunc {
  return func(c *gin.Context) {
    email := c.Query("email")
    // Vulnerable: direct string interpolation of user input into SQL
    query := "SELECT id, name FROM users WHERE email = '" + email + "'"
    rows, err := db.Query(query)
    if err != nil {
      c.String(http.StatusInternalServerError, "DB error")
      return
    }
    defer rows.Close()
    c.String(http.StatusOK, "vulnerable path executed")
  }
}

// Safe: parameterized query using placeholders
func safeUserHandler(db *sql.DB) gin.HandlerFunc {
  return func(c *gin.Context) {
    email := c.Query("email")
    // Safe: parameterized query to prevent injection
    rows, err := db.Query("SELECT id, name FROM users WHERE email = ?", email)
    if err != nil {
      c.String(http.StatusInternalServerError, "DB error")
      return
    }
    defer rows.Close()
    c.String(http.StatusOK, "safe path executed")
  }
}

func main() {
  dsn := "user:password@tcp(127.0.0.1:3306)/testdb"
  db, err := sql.Open("mysql", dsn)
  if err != nil {
    log.Fatal(err)
  }
  defer db.Close()

  r := gin.Default()
  r.GET("/vuln/user", vulnerableUserHandler(db))
  r.GET("/safe/user", safeUserHandler(db))
  r.Run(":8080")
}

CVE References

Choose which optional cookies to allow. You can change this any time.