fix(backend): add table name whitelist in testutils/db.go

- Add allowedTestTables map containing all known database tables
- Add validateTableName() function that panics if table name is not
  in the whitelist
- Call validateTableName() before all fmt.Sprintf("DELETE FROM %s")
  and fmt.Sprintf("TRUNCATE TABLE %s CASCADE") statements
- Prevents potential SQL injection via table name interpolation,
  even though the risk is low (test-only code, table names come from
  hardcoded lists or DB introspection)

Addresses audit finding: A03 (Injection) — minor risk in test utilities.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
senke 2026-02-11 22:57:40 +01:00
parent 03c9d97b90
commit a40a61d801

View file

@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"fmt"
"strings"
"testing"
"gorm.io/driver/postgres"
@ -11,6 +12,72 @@ import (
"gorm.io/gorm/logger"
)
// allowedTestTables is a whitelist of table names that are safe to use
// in DELETE FROM / TRUNCATE statements in test utilities.
// This prevents SQL injection via table name interpolation in fmt.Sprintf.
var allowedTestTables = map[string]bool{
"users": true,
"user_sessions": true,
"user_profiles": true,
"user_settings": true,
"user_roles": true,
"user_blocks": true,
"roles": true,
"role_permissions": true,
"permissions": true,
"tracks": true,
"track_likes": true,
"track_plays": true,
"track_comments": true,
"track_shares": true,
"track_versions": true,
"track_history": true,
"playlists": true,
"playlist_tracks": true,
"playlist_collaborators": true,
"playlist_follows": true,
"playlist_share_links": true,
"messages": true,
"rooms": true,
"room_members": true,
"notifications": true,
"follows": true,
"likes": true,
"comments": true,
"posts": true,
"sessions": true,
"jobs": true,
"audit_logs": true,
"refresh_tokens": true,
"password_reset_tokens": true,
"email_verification_tokens": true,
"federated_identities": true,
"files": true,
"file_uploads": true,
"file_metadata": true,
"file_conversions": true,
"analytics_events": true,
"admin_settings": true,
"webhooks": true,
"webhook_failures": true,
"playback_history": true,
"queues": true,
"queue_items": true,
"hls_streams": true,
"hls_transcode_queue": true,
"bitrate_adaptation_logs": true,
}
// validateTableName checks that a table name is in the allowed whitelist.
// Panics if the name is not allowed, preventing potential SQL injection.
func validateTableName(table string) {
// Strip "public." prefix if present
clean := strings.TrimPrefix(table, "public.")
if !allowedTestTables[clean] {
panic(fmt.Sprintf("SECURITY: table name %q is not in the allowed whitelist for test cleanup", table))
}
}
// SetupTestDB creates a connection to the test container database.
// It ensures the container is running and the schema is migrated.
// The container is shared across tests (singleton in setup.go), so be mindful of data state.
@ -80,6 +147,9 @@ func ResetTestDB(db *gorm.DB) error {
// Also, we need to check if table exists to avoid errors?
// With the container setup, tables should always exist.
// Validate table name against whitelist before interpolation
validateTableName(table)
// For simplicity and safety, we try DELETE or TRUNCATE CASCADE.
// TRUNCATE table_name CASCADE;
if err := db.Exec(fmt.Sprintf("TRUNCATE TABLE %s CASCADE", table)).Error; err != nil {
@ -175,6 +245,9 @@ func cleanupTables(t *testing.T, db *gorm.DB, opts CleanupOptions) error {
}
for _, table := range tables {
// Validate table name against whitelist before interpolation
validateTableName(table)
var query string
if opts.Cascade && isPostgreSQL {
// CASCADE est supporté par PostgreSQL