Injection

Injection in Go (Gin): Safe DDL Identifiers [CVE-2026-33122]

[Fixed month year] Updated CVE-2026-33122

Overview

DataEase CVE-2026-33122 exposed a SQL injection in an API data source update path where an input field deTableName was passed into a CREATE TABLE statement without sanitization. In Go projects using Gin, similar patterns can occur when user-supplied identifiers are embedded directly into SQL or DDL, enabling an attacker to craft payloads that alter queries or extract metadata. The vulnerability, classified under CWE-89 (SQL Injection), highlights how interpolating untrusted data into DDL can lead to information disclosure or schema manipulation, especially when the input governs identifiers rather than data values. The real-world impact for DataEase included the ability to perform error-based injections to reveal database details before fixes (e.g., upgrade to 2.10.21). In a Go (Gin) context, this risk remains if developer code concatenates or formats user-provided identifiers into CREATE/ALTER statements without validation or proper scoping. The remediation pattern should be to treat identifiers as a separate, validated surface and never interpolate raw user input into SQL strings. This guide provides concrete Go (Gin) code patterns to prevent such injections and aligns with the specifics of CVE-2026-33122.

Affected Versions

DataEase: 2.10.20 and below; fixed in 2.10.21

Code Fix Example

Go (Gin) API Security Remediation
package main

import (
  "database/sql"
  "fmt"
  _ "github.com/lib/pq"
  "regexp"
)

// Vulnerable pattern: interpolating user input directly into SQL/DDL
func createTableVulnerable(db *sql.DB, deTableName string) error {
  // Potentially dangerous: user-controlled identifier is inserted raw
  q := fmt.Sprintf("CREATE TABLE %s (id INT)", deTableName)
  _, err := db.Exec(q)
  return err
}

// Validation helper: simple whitelist for identifiers
func isValidIdentifier(s string) bool {
  re := regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]{0,63}$`)
  return re.MatchString(s)
}

// Safe pattern: validate then quote the identifier
func createTableFixed(db *sql.DB, deTableName string) error {
  if !isValidIdentifier(deTableName) {
    return fmt.Errorf("invalid table name: %s", deTableName)
  }
  // Safe: identifier is validated, then safely quoted
  q := fmt.Sprintf("CREATE TABLE \"%s\" (id INT)", deTableName)
  _, err := db.Exec(q)
  return err
}

CVE References

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