{"record":{"id":"559840a608865a6d","repo":"projectdiscovery/nuclei","slug":"invalid-connection-string-v","errorCode":null,"errorMessage":"invalid connection string: %v","messagePattern":"invalid connection string: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/js/utils/pgwrap/pgwrap.go","lineNumber":89,"sourceCode":"\tconnector.Dialer(&pgDial{executionId: executionId, ctx: ctx})\n\treturn sql.OpenDB(connector), nil\n}\n\n// Unfortunately lib/pq does not provide easy to customize or\n// replace dialer so we need to hijack it by wrapping it in our own\n// driver and register it as postgres driver\n\n// PgDriver is the Postgres database driver.\ntype PgDriver struct{}\n\n// Open opens a new connection to the database. name is a connection string.\n// Most users should only use it through database/sql package from the standard\n// library.\nfunc (d PgDriver) Open(name string) (driver.Conn, error) {\n\t// Parse the connection string to get executionId\n\tu, err := url.Parse(name)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid connection string: %v\", err)\n\t}\n\tvalues := u.Query()\n\texecutionId := values.Get(\"executionId\")\n\t// Remove executionId from the connection string\n\tvalues.Del(\"executionId\")\n\tu.RawQuery = values.Encode()\n\n\treturn pq.DialOpen(&pgDial{executionId: executionId}, u.String())\n}\n\nfunc init() {\n\tsql.Register(PGWrapDriver, &PgDriver{})\n}\n","sourceCodeStart":71,"sourceCodeEnd":103,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/utils/pgwrap/pgwrap.go#L71-L103","documentation":"Returned by the pgwrap Postgres driver's Open when url.Parse fails on the connection string passed to sql.Open. pgwrap wraps pq and expects a URL-style DSN (scheme://user:pass@host:port/db?...) carrying an executionId query parameter that it strips out before delegating to pq.DialOpen. Anything that is not a parseable URL — keyword/value DSNs, spaces, or unencoded special characters — fails here.","triggerScenarios":"Passing a libpq keyword DSN like 'host=db port=5432 user=...' instead of a URL; unencoded symbols in the password (#, %, @, spaces) breaking the URL grammar; missing scheme; malformed percent-encoding anywhere in the string.","commonSituations":"Copy-pasting DSNs from pq/psql configs into nuclei' Postgres JS library; passwords generated with URL-reserved characters; forgetting the executionId parameter required by the wrapped driver.","solutions":["Use URL-form DSN: postgres://user:pass@host:5432/dbname?executionId=<id>","URL-encode the password and any values containing reserved characters (use encodeURIComponent in JS or url.URL in Go)","Build the DSN programmatically instead of string concatenation"],"exampleFix":"// before\nsql.Open('postgreswrap', \"postgres://user:p@ss word@db:5432/app?executionId=\" + execId);\n\n// after\nconst dsn = `postgres://user:${encodeURIComponent(password)}@db:5432/app?executionId=${encodeURIComponent(execId)}`;\nsql.Open('postgreswrap', dsn);","handlingStrategy":"validation","validationCode":"import net/url\n\nfunc buildDSN(user, pass, host string, port int, db, execID string) (string, error) {\n\tu := url.URL{Scheme: \"postgres\", User: url.UserPassword(user, pass), Host: net.JoinHostPort(host, strconv.Itoa(port)), Path: db}\n\tq := u.Query(); q.Set(\"executionId\", execID); u.RawQuery = q.Encode()\n\treturn u.String(), nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-concatenate DSNs; build them with url.URL / URLSearchParams","Always URL-encode passwords (reserved chars: @ : / # % ?)","Keep the executionId query parameter — pgwrap requires it"],"tags":["postgres","go","database","dsn","url-parsing"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}