{"record":{"id":"93c44a7e3a7a38f3","repo":"shadow1ng/fscan","slug":"mysql-username-contains-unsupported-dsn-delimiter","errorCode":null,"errorMessage":"mysql username contains unsupported DSN delimiter","messagePattern":"mysql username contains unsupported DSN delimiter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/mysql.go","lineNumber":128,"sourceCode":"\t\t\tSuccess:   false,\n\t\t\tErrorType: classifyMySQLErrorType(err),\n\t\t\tError:     err,\n\t\t}\n\t}\n\n\tstate.IncrementTCPSuccessPacketCount()\n\n\treturn &AuthResult{\n\t\tSuccess:   true,\n\t\tConn:      &SQLDBWrapper{db},\n\t\tErrorType: ErrorTypeUnknown,\n\t\tError:     nil,\n\t}\n}\n\nfunc mySQLConnString(username, password string, info *common.HostInfo, timeout time.Duration) (string, error) {\n\tif strings.ContainsAny(username, \":@/\") {\n\t\treturn \"\", fmt.Errorf(\"mysql username contains unsupported DSN delimiter\")\n\t}\n\tcfg := mysql.NewConfig()\n\tcfg.User = username\n\tcfg.Passwd = password\n\tcfg.Net = \"tcp\"\n\tcfg.Addr = net.JoinHostPort(info.Host, strconv.Itoa(info.Port))\n\tcfg.DBName = \"information_schema\"\n\tcfg.Params = map[string]string{\"charset\": \"utf8\"}\n\tcfg.Timeout = timeout\n\treturn cfg.FormatDSN(), nil\n}\n\n// classifyMySQLErrorType MySQL错误分类\nfunc classifyMySQLErrorType(err error) ErrorType {\n\tif err == nil {\n\t\treturn ErrorTypeUnknown\n\t}\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/mysql.go#L110-L146","documentation":"mySQLConnString builds a go-sql-driver DSN. The username is interpolated into the DSN where ':', '@', and '/' are delimiters (user:pass@host/db), and unescaped occurrences would corrupt the DSN. To avoid ambiguous or wrong DSNs, the function rejects usernames containing any of those characters outright.","triggerScenarios":"Calling doMySQLAuth (or mySQLConnString directly) with a Credential whose Username contains ':', '@', or '/' — e.g. usernames like 'admin:root', 'a@b', 'domain/user' pulled from a brute-force wordlist.","commonSituations":"Wordlists containing UPN-style names ('user@domain') or Windows-style 'DOMAIN/user'; copy-pasted connection strings used as usernames; fuzzed credential lists.","solutions":["Remove or replace delimiter characters in the username (e.g. strip '@domain' from UPN-form entries).","Percent-encode the username before building the DSN (go-sql-driver accepts URL-encoded credentials in DSNs).","Filter wordlists at load time to drop entries containing ':@/'.","If the server truly requires such a username, construct the mysql.Config directly and use sql.OpenDB instead of a formatted DSN string."],"exampleFix":"// before\nusername := \"svc@corp.local\"\nconnStr, err := mySQLConnString(username, password, info, timeout) // error\n// after\nlocalUser := strings.SplitN(username, \"@\", 2)[0]\nconnStr, err := mySQLConnString(localUser, password, info, timeout)","handlingStrategy":"validation","validationCode":"if strings.ContainsAny(username, \":@/\") {\n    return fmt.Errorf(\"skipping credential %q: contains DSN delimiter\", username)\n}","typeGuard":null,"tryCatchPattern":"connStr, err := mySQLConnString(user, pass, info, timeout)\nif err != nil {\n    if strings.Contains(err.Error(), \"unsupported DSN delimiter\") {\n        return skipCredential(user) // filter bad entry, keep scanning\n    }\n}","preventionTips":["Sanitize or skip wordlist entries containing ':@/'.","Convert UPN usernames ('user@domain') to the local part for MySQL.","Percent-encode credentials if you must embed unusual characters in a DSN.","Prefer mysql.Config + sql.OpenDB over string DSNs for arbitrary usernames."],"tags":["mysql","dsn","input-validation","credentials"],"backgroundTag":"invalid-argument-format","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}