aws / aws/aws-advanced-go-wrapper
MySQL DSN containing a space in the user or password is detected as a Postgres key/value DSN
- Dominant language
- Go
- Stars
- 78
- Forks
- 12
- Avg merge
- 3d 20h
- Merged PRs (30d)
- 13
Description
### Describe the bug
A MySQL DSN whose user name or password contains a space is parsed as a Postgres key/value DSN.
[`isDsnMySql`](https://github.com/aws/aws-advanced-go-wrapper/blob/877b430/awssql/property_util/dsn_parser.go#L209-L211) rejects any DSN with whitespace between tokens, so MySQL is ruled out before `mySqlDsnPattern` is even evaluated. Detection then falls through to `isDsnPgxKeyValueString`, and that pattern is unanchored, so a trailing `?parseTime=true` is enough to match.
`go-sql-driver/mysql` does not unescape the user or password, so `%20` stays literal. The space has to be a real space, which leaves no way to connect with those credentials through the wrapper.
### Expected Behavior
The same result as the DSN without the space. Protocol `mysql`, with user, password, host, port and database parsed out. `go-sql-driver/mysql` accepts these DSNs, and `Config.FormatDSN()` emits the space unescaped.
### What plugins are used? What other connection properties were set?
No plugins. No extra connection properties.
### Current Behavior
`ParseDsn` returns no error and two properties, with the front of the DSN swallowed into a single key:
| DSN | protocol | properties |
|---|---|---|
| `user:pass@tcp(myhost:3306)/db?parseTime=true` | `mysql` | 8, correct |
| `user:pa ss@tcp(myhost:3306)/db?parseTime=true` | `postgresql` | `{protocol: "postgresql", "user:pa ss@tcp(myhost:3306)/db?parseTime": "true"}` |
Host, port and credentials are gone and nothing reports a failure, so `GetHostsFromDsn` and `ParseUserFromDsn` just return empty values. `MaskSensitiveInfoFromDsn` branches on the same predicates in the same order, so credentials in an affected DSN also end up unmasked.
### Reproduction Steps
No database needed.
```go
package main
import (
"fmt"
"github.com/aws/aws-advanced-go-wrapper/awssql/v2/property_util"
)
func main() {
dsn := "user:pa ss@tcp(myhost:3306)/db?parseTime=true"
proto, _ := property_util.GetProtocol(dsn)
props, err := property_util.ParseDsn(dsn)
fmt.Println(proto, err, props.GetAllEntries())
}
```
On awssql/v2 v2.0.3:
```
postgresql map[protocol:postgresql user:pa ss@tcp(myhost:3306)/db?parseTime:true]
```
Removing the space from the password gives `mysql` and the eight expected properties.
### Possible Solution
Detect pgx key/value DSNs with an anchored match rather than ruling MySQL out by whitespace, and check pgx key/value before MySQL, since `mySqlDsnPattern`'s groups are all optional and it matches almost anything.
One catch: simply wrapping the current pattern in `^(...)+$` is not enough. Its value class has no space or backslash, so it would then reject pgx DSNs that quote a value because it contains a space, like `host=localhost password='my pass' dbname=x`. Those would fall through to `mySqlDsnPattern` and get misdetected as MySQL instead. The value grammar needs to accept what `parsePgxKeywordValueSettings` already accepts.
I have this working locally with the existing unit tests passing, and can send a PR if the approach looks right.
### Additional Information/Context
The whitespace check was added in #130 to stop pgx key/value DSNs from matching `mySqlDsnPattern`. Anchoring handles that case without the side effect.
`.test/test/dsn_parser_test.go` covers trailing spaces but not a space inside the credentials.
### The AWS Advanced Go Wrapper version used
`awssql/v2` v2.0.3, `mysql-driver` v1.1.3
### Go version used
go1.26.4 darwin/arm64
### Operating System and version
macOS 26.5 (arm64)
Contributor guide
Research direction
Start in awssql/property_util/dsn_parser.go by reading the DSN detection predicates, ParseDsn, MaskSensitiveInfoFromDsn, and parsePgxKeywordValueSettings. Run .test/test/dsn_parser_test.go and add coverage for spaces in MySQL credentials and quoted pgx values. Done means both DSN forms are detected correctly, parsed properties and protocol are preserved, and affected credentials remain masked.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, mysql, postgresql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100