@@ -330,6 +330,54 @@ func TestFormatMap(t *testing.T) {
330330 assert .Equal (t , "map('a', 1)" , val )
331331}
332332
333+ func TestTimezoneSQLEscaping (t * testing.T ) {
334+ t .Run ("prevent SQL injection via timezone name" , func (t * testing.T ) {
335+ maliciousLoc := time .FixedZone ("UTC') UNION ALL SELECT 1,2,3 --" , 0 )
336+ time .LoadLocation (maliciousLoc .String ())
337+ maliciousTime := time .Now ().In (maliciousLoc )
338+
339+ val , err := format (time .UTC , Seconds , maliciousTime )
340+ require .Error (t , err )
341+ assert .Equal (t , "" , val )
342+ assert .ErrorIs (t , err , ErrInvalidTimezone )
343+ })
344+
345+ t .Run ("prevent SQL injection via timezone name with milliseconds" , func (t * testing.T ) {
346+ maliciousLoc := time .FixedZone ("America/New_York'); DROP TABLE users; --" , 0 )
347+ maliciousTime := time .Now ().In (maliciousLoc )
348+
349+ val , err := format (time .UTC , MilliSeconds , maliciousTime )
350+ require .Error (t , err )
351+ assert .Equal (t , "" , val )
352+ assert .ErrorIs (t , err , ErrInvalidTimezone )
353+ })
354+
355+ t .Run ("prevent SQL injection via timezone with backslashes" , func (t * testing.T ) {
356+ maliciousLoc := time .FixedZone (`UTC\' OR 1=1 --` , 0 )
357+ maliciousTime := time .Now ().In (maliciousLoc )
358+
359+ val , err := format (time .UTC , Seconds , maliciousTime )
360+ // require.NoError(t, err)
361+ require .Error (t , err )
362+ assert .Equal (t , "" , val )
363+ assert .ErrorIs (t , err , ErrInvalidTimezone )
364+ })
365+
366+ t .Run ("normal timezone names remain unaffected" , func (t * testing.T ) {
367+ // Test that normal, safe timezone names still work correctly
368+ normalLoc := time .FixedZone ("America/New_York" , - 5 * 3600 )
369+ normalTime := time .Now ().In (normalLoc )
370+
371+ val , err := format (time .UTC , Seconds , normalTime )
372+ require .NoError (t , err )
373+
374+ // Should contain the timezone name without any escaping
375+ assert .Contains (t , val , "'America/New_York'" )
376+ assert .NotContains (t , val , `\'` , "Normal timezone names should not have escaped quotes" )
377+ assert .Contains (t , val , "toDateTime(" )
378+ })
379+ }
380+
333381// a simple (non thread safe) ordered map, implementing the column.OrderedMap interface
334382type OrderedMap struct {
335383 keys []any
0 commit comments