TimeZone is matched anywhere in the DSN, so a password containing "TimeZone=" breaks the connection and appears in its error

Open Beginner friendly
#358 1 comment 0 reactions 0 assignees View on GitHub

@anggakrnwn is already working on this.

Since Nov 6, 2026.

  • #359 by @anggakrnwn — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
go, postgresql
Domain
backend, database

Research direction

Read Dialector.Initialize and timeZoneMatcher in postgres.go, then inspect how pgx.ParseConfig stores RuntimeParams for URL and keyword/value DSNs. Use the reproducer to check that an ordinary password containing TimeZone= still connects and that explicit TimeZone, timezone, and time_zone parameters set the session time zone. Done means the connection works without exposing credential text in the error.

Written by the indexing model from the issue text.

Description

Versions

  • gorm.io/driver/postgres v1.6.3 (also master, 1a2d67b) and v1.5.9
  • gorm.io/gorm v1.31.2, github.com/jackc/pgx/v5 v5.10.0
  • PostgreSQL 18.6

Problem

Dialector.Initialize parses the DSN with pgx.ParseConfig and then runs timeZoneMatcher over the raw DSN string (postgres.go, line 105 in v1.6.3). Whatever follows the first TimeZone=, timezone= or time_zone= anywhere in the string becomes RuntimeParams["timezone"].

The match is not limited to a DSN parameter. A password, user name or database name that contains one of those strings sets the session time zone to the rest of the DSN. In a URL DSN the captured value runs to the end of the string, so:

  • the connection fails, although pgx alone connects with the same DSN;
  • the server rejects the value and its error repeats it: the tail of the password, then the host, port, database and query. Applications usually log that error. pgx itself redacts passwords in its own errors.

Reproducer

Synthetic credentials on a local PostgreSQL:

CREATE ROLE repro LOGIN PASSWORD 'TimeZone=Synthetic42';
package main

import (
	"context"
	"fmt"
	"os"

	"github.com/jackc/pgx/v5"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

func main() {
	dsn := fmt.Sprintf("postgres://repro:[email protected]:%s/postgres?sslmode=disable", os.Getenv("PGPORT"))

	conn, err := pgx.Connect(context.Background(), dsn)
	fmt.Println("pgx.Connect:", err)
	if conn != nil {
		_ = conn.Close(context.Background())
	}

	_, err = gorm.Open(postgres.Open(dsn), &gorm.Config{Logger: logger.Discard})
	fmt.Println("gorm.Open:  ", err)
}

Output:

pgx.Connect: <nil>
gorm.Open:   failed to connect to `user=repro database=postgres`: 127.0.0.1:59712 (127.0.0.1): server error: FATAL: invalid value for parameter "TimeZone": "[email protected]:59712/postgres?sslmode=disable" (SQLSTATE 22023)

A database name containing TimeZone= fails the same way.

Expected

Only a TimeZone, timezone or time_zone connection parameter sets the time zone. pgx.ParseConfig already separates them: for ?TimeZone=Asia/Shanghai, ?time_zone=Asia/Shanghai or a keyword/value TimeZone=Asia/Shanghai, it leaves the setting in config.RuntimeParams under the key as written. For the DSN above, RuntimeParams is empty. Reading the time zone from config.RuntimeParams, with a case-insensitive key lookup, instead of matching the raw DSN would avoid both the false match and the leak.

Dominant language
Go
Stars
298
Forks
158
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from go-gorm/postgres

All issues in go-gorm/postgres

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.