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:
parent
03c9d97b90
commit
a40a61d801
1 changed files with 73 additions and 0 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue