{"record":{"id":"05713c88df7a09cd","repo":"docker/cli","slug":"plain-text-password-is-not-supported","errorCode":null,"errorMessage":"plain-text password is not supported","messagePattern":"plain-text password is not supported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/connhelper/ssh/ssh.go","lineNumber":54,"sourceCode":"}\n\nfunc newSpec(u *url.URL) (*Spec, error) {\n\tif u == nil {\n\t\treturn nil, errors.New(\"URL is nil\")\n\t}\n\tif u.Scheme == \"\" {\n\t\treturn nil, errors.New(\"no scheme provided\")\n\t}\n\tif u.Scheme != \"ssh\" {\n\t\treturn nil, errors.New(\"incorrect scheme: \" + u.Scheme)\n\t}\n\n\tvar sp Spec\n\n\tif u.User != nil {\n\t\tsp.User = u.User.Username()\n\t\tif _, ok := u.User.Password(); ok {\n\t\t\treturn nil, errors.New(\"plain-text password is not supported\")\n\t\t}\n\t}\n\tsp.Host = u.Hostname()\n\tif sp.Host == \"\" {\n\t\treturn nil, errors.New(\"hostname is empty\")\n\t}\n\tsp.Port = u.Port()\n\tsp.Path = u.Path\n\tif u.RawQuery != \"\" {\n\t\treturn nil, fmt.Errorf(\"query parameters are not allowed: %q\", u.RawQuery)\n\t}\n\tif u.Fragment != \"\" {\n\t\treturn nil, fmt.Errorf(\"fragments are not allowed: %q\", u.Fragment)\n\t}\n\n\treturn &sp, nil\n}\n","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/connhelper/ssh/ssh.go#L36-L72","documentation":"Returned by newSpec when the URL's userinfo contains a password (u.User.Password() reports one is present). Embedding a plaintext password in DOCKER_HOST would expose it in process listings and shell history, so the SSH helper refuses it and expects key-based or agent-based authentication instead.","triggerScenarios":"Setting DOCKER_HOST='ssh://user:password@host' or passing such a URL to ssh.ParseURL/NewSpec. Any URL of the form scheme://user:pass@host triggers it.","commonSituations":"A user tries to embed SSH credentials directly in the DOCKER_HOST value for convenience in CI. Copying a URL with embedded credentials from a secrets manager.","solutions":["Remove the password from the URL: 'ssh://user@host'.","Use SSH key authentication (configure an SSH key or ssh-agent) instead of a password.","Store credentials in ~/.ssh/config or use an ssh-agent rather than the URL."],"exampleFix":"# before\nDOCKER_HOST=ssh://user:s3cret@remote-host\n# after\nDOCKER_HOST=ssh://user@remote-host\n# (then authenticate via SSH key / agent)","handlingStrategy":"validation","validationCode":"// Strip embedded passwords from DOCKER_HOST before use.\nu, err := url.Parse(host)\nif err == nil && u.User != nil {\n    if _, ok := u.User.Password(); ok {\n        u.User = url.User(u.User.Username()) // drop password\n    }\n    host = u.String()\n}","typeGuard":"func hasNoPassword(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && (u.User == nil || func() bool { _, ok := u.User.Password(); return !ok }())\n}","tryCatchPattern":null,"preventionTips":["Never embed passwords in DOCKER_HOST.","Prefer SSH keys or an ssh-agent.","Configure hosts in ~/.ssh/config instead of the URL."],"tags":["ssh","connhelper","security","credentials","docker-host"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}