{"record":{"id":"a043db6e21fd3484","repo":"gravitational/teleport","slug":"malformed-rdns-w","errorCode":null,"errorMessage":"malformed RDNs: %w","messagePattern":"malformed RDNs: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/utils/pkixname/parser.go","lineNumber":71,"sourceCode":"\tconst maxDNLength = 4096 // arbitrary-ish upper value\n\tswitch {\n\tcase dn == \"\": // Early exit.\n\t\treturn &pkix.Name{}, nil\n\tcase len(dn) > maxDNLength:\n\t\treturn nil, errors.New(\"distinguished name too large, refusing to parse\")\n\t}\n\n\ttokens, err := tokenize(dn)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tdst := &pkix.Name{}\n\tif tokens.Len() == 0 {\n\t\treturn dst, nil\n\t}\n\tif err := parseRDNSequence(dst, *tokens); err != nil {\n\t\treturn nil, fmt.Errorf(\"malformed RDNs: %w\", err)\n\t}\n\treturn dst, nil\n}\n\n// parseRDNSequence parses a RelativeDistinguishedName sequence, ie, a sequence\n// of AttributeTypeAndValue separated by commas or pluses.\nfunc parseRDNSequence(dst *pkix.Name, tokens tokenList) error {\n\tseenAttrs := make(map[string]struct{})\n\tmarkAttr := func(attr string) error {\n\t\tif _, ok := seenAttrs[attr]; ok {\n\t\t\treturn fmt.Errorf(\"repeated attributeType %q, remaining tokens: %s\", attr, tokens)\n\t\t}\n\t\tseenAttrs[attr] = struct{}{}\n\t\treturn nil\n\t}\n\n\tprevAttr, err := parseATV(dst, tokens)\n\tif err != nil {","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/api/utils/pkixname/parser.go#L53-L89","documentation":"ParseDistinguishedName parses an RFC 2253-like DN string (e.g. 'C=US,O=Teleport,CN=Teleport CA') into a pkix.Name. When the low-level parseRDNSequence fails on any attribute-type-and-value in the sequence, the error is wrapped as 'malformed RDNs' — meaning the DN string does not conform to the expected ATTR=VALUE[,ATTR=VALUE...] structure or uses unsupported attributes.","triggerScenarios":"Calling ParseDistinguishedName with a DN containing repeated attribute types in separate RDNs, mismatched multi-valued RDNs, truncated components, invalid attribute names, or unknown attribute types — any sub-error from parseRDNSequence gets this wrapper.","commonSituations":"Users paste DNs copied from OpenSSL output (with '/C=US/O=Org' slash separators, which fail tokenization), use RFC 4514 numeric OIDs for common attributes (2.5.4.3=... instead of CN=...), or supply values with unescaped special characters.","solutions":["Read the wrapped cause (%w) for the exact failing token/component and fix that specific part of the DN","Use comma-separated RFC 2253 syntax: 'C=US,O=Teleport,CN=Teleport CA', not OpenSSL's slash format","Use short attribute names (CN, O, OU, C, ST, L, SERIALNUMBER, POSTALCODE, STREET) instead of common numeric OIDs","Escape special characters (',', '+', '=', '#', ';', etc.) with a backslash inside values"],"exampleFix":"// before\nParseDistinguishedName(\"/C=US/O=Teleport\")\n// after\nParseDistinguishedName(\"C=US,O=Teleport\")","handlingStrategy":"validation","validationCode":"func looksLikeDN(dn string) error {\n\tif dn == \"\" { return nil }\n\tif strings.Contains(dn, \"/\") { return errors.New(\"slash-separated DN; use comma-separated RFC2253 form\") }\n\tfor _, part := range strings.Split(dn, \",\") {\n\t\tkv := strings.SplitN(part, \"=\", 2)\n\t\tif len(kv) != 2 || kv[0] == \"\" || kv[1] == \"\" { return fmt.Errorf(\"component %q is not ATTR=VALUE\", part) }\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"name, err := pkixname.ParseDistinguishedName(dn)\nif err != nil {\n\tvar detail string\n\tif errors.Unwrap(err) != nil { detail = errors.Unwrap(err).Error() }\n\treturn fmt.Errorf(\"invalid DN %q: %v (%v)\", dn, err, detail)\n}","preventionTips":["Write DNs as comma-separated ATTR=VALUE pairs; never OpenSSL slash format","Escape ',', '+', '=', '#', ';', '<', '>', '\"' inside values with backslash or quotes","Check errors.Unwrap for the specific failing component","Keep DNs under 4096 characters (hard parser limit)"],"tags":["x509","parsing","distinguished-name","configuration"],"backgroundTag":"malformed-distinguished-name","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}