{"record":{"id":"bf7854dc2de2e6b6","repo":"gravitational/teleport","slug":"unknown-attributetype-q-remaining-tokens-s","errorCode":null,"errorMessage":"unknown attributeType %q, remaining tokens: %s","messagePattern":"unknown attributeType %q, remaining tokens: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/utils/pkixname/parser.go","lineNumber":200,"sourceCode":"\t\tdst.SerialNumber = value\n\tcase \"CN\":\n\t\tdst.CommonName = value\n\tcase \"OU\":\n\t\tdst.OrganizationalUnit = append(dst.OrganizationalUnit, value)\n\tcase \"O\":\n\t\tdst.Organization = append(dst.Organization, value)\n\tcase \"POSTALCODE\":\n\t\tdst.PostalCode = append(dst.PostalCode, value)\n\tcase \"STREET\":\n\t\tdst.StreetAddress = append(dst.StreetAddress, value)\n\tcase \"L\":\n\t\tdst.Locality = append(dst.Locality, value)\n\tcase \"ST\":\n\t\tdst.Province = append(dst.Province, value)\n\tcase \"C\":\n\t\tdst.Country = append(dst.Country, value)\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"unknown attributeType %q, remaining tokens: %s\", attr, tokens)\n\t}\n\treturn attr, nil\n}\n\nfunc parseOIDExtraName(dst *pkix.Name, attr, value string) error {\n\tparts := strings.Split(attr, \".\")\n\toid := make(asn1.ObjectIdentifier, 0, len(parts))\n\tfor _, val := range parts {\n\t\tnum, err := strconv.Atoi(val)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\n\t\t\t\t\"cannot parse OID component %q as int, OID=%q: %w\", val, attr, err)\n\t\t}\n\t\toid = append(oid, num)\n\t}\n\n\tdst.ExtraNames = append(dst.ExtraNames, pkix.AttributeTypeAndValue{\n\t\tType:  oid,","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/api/utils/pkixname/parser.go#L182-L218","documentation":"After passing charset validation, the attribute type must be one of the explicitly supported short names: SERIALNUMBER, CN, OU, O, POSTALCODE, STREET, L, ST, C (common numeric OIDs are also rejected by design — 'use C instead of 2.5.4.6'). Any other well-formed name falls into the default case and produces 'unknown attributeType'.","triggerScenarios":"ParseDistinguishedName('DC=example,DC=com') — DC is not in the switch. Also 'UID=user', 'EMAILADDRESS=a@b.c', 'SN=SurName', or full-word names like 'COMMONNAME=x'.","commonSituations":"Users copy AD/LDAP-style DNs ('DC=corp,DC=example,DC=com') or RFC 4514 DNs using UID/serialNumber/emailAddress into Teleport config where only the short set is supported.","solutions":["Rewrite the DN using only supported attributes: CN, O, OU, C, ST, L, STREET, POSTALCODE, SERIALNUMBER","Replace DC components with O/OU (e.g. 'DC=example,DC=com' -> 'O=example,OU=com' or a single 'O=example.com')","Replace UID/EMAILADDRESS with a custom numeric OID form (e.g. '0.9.2342.19200300.100.1.1=user') which goes through parseOIDExtraName","Consult the parser's documented deviations before porting DNs from other tools"],"exampleFix":"// before\nParseDistinguishedName(\"DC=example,DC=com,CN=proxy\")\n// after\nParseDistinguishedName(\"O=example.com,CN=proxy\")","handlingStrategy":"validation","validationCode":"var supportedAttrs = map[string]bool{\"SERIALNUMBER\": true, \"CN\": true, \"OU\": true, \"O\": true, \"POSTALCODE\": true, \"STREET\": true, \"L\": true, \"ST\": true, \"C\": true}\nfunc attrsSupported(dn string) error {\n\tfor _, part := range strings.Split(dn, \",\") {\n\t\tkv := strings.SplitN(strings.TrimSpace(part), \"=\", 2)\n\t\tif len(kv) == 2 && !supportedAttrs[kv[0]] {\n\t\t\treturn fmt.Errorf(\"attribute %q not supported; use CN, O, OU, C, ST, L, STREET, POSTALCODE, SERIALNUMBER or a numeric OID\", kv[0])\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if err := attrsSupported(dn); err != nil { return err }\nname, err := pkixname.ParseDistinguishedName(dn)\nif err != nil { return fmt.Errorf(\"invalid DN %q: %w\", dn, err) }","preventionTips":["Restrict DN authoring to the nine supported short attribute names","Convert LDAP-style DC components to O/OU before parsing","For rare attributes, use the full numeric OID form so the value lands in ExtraNames"],"tags":["x509","distinguished-name","parsing","configuration"],"backgroundTag":"unsupported-dn-attribute","analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}