{"record":{"id":"b73d8381eb63585b","repo":"apache/hadoop","slug":"tag-not-found-0x-tags","errorCode":null,"errorMessage":"Tag not found: 0x${tags}","messagePattern":"Tag not found: 0x(.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":401,"severity":"error","filePath":"hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/KerberosUtil.java","lineNumber":421,"sourceCode":"        }\n      }\n      return null;\n    }\n\n    DER get(int... tags) {\n      DER der = this;\n      for (int i=0; i < tags.length; i++) {\n        int expectedTag = tags[i];\n        // lookup for exact match, else scan if it's sequenced.\n        if (der.getTag() != expectedTag) {\n          der = der.hasNext() ? der.choose(expectedTag) : null;\n        }\n        if (der == null) {\n          StringBuilder sb = new StringBuilder(\"Tag not found:\");\n          for (int ii=0; ii <= i; ii++) {\n            sb.append(\" 0x\").append(Integer.toHexString(tags[ii]));\n          }\n          throw new IllegalStateException(sb.toString());\n        }\n      }\n      return der;\n    }\n\n    String getAsString() {\n      return new String(bb.array(), bb.arrayOffset() + bb.position(),\n          bb.remaining(), StandardCharsets.UTF_8);\n    }\n\n    @Override\n    public int hashCode() {\n      return 31 * tag + bb.hashCode();\n    }\n\n    @Override\n    public boolean equals(Object o) {\n      return (o instanceof DER) &&","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/KerberosUtil.java#L403-L439","documentation":"The DER.get(int... tags) helper inside KerberosUtil navigates a parsed ASN.1/DER structure tag by tag. When an expected tag cannot be found at a position (and no matching element exists in the enclosing sequence), it builds 'Tag not found:' followed by the hex tag path consumed so far and throws IllegalStateException, meaning the token's DER layout does not match the expected Kerberos/SPNEGO shape.","triggerScenarios":"getTokenServerName() on a token whose SPNEGO/AP-REQ structure omits an expected element — e.g. negTokenInit without the mech-token element, an AP-REQ missing the ticket field, or bytes that decode as valid DER but of a different layout.","commonSituations":"Non-standard or future GSS token layouts; partially corrupted token bytes that still parse as DER; hand-crafted test tokens missing optional-but-expected fields.","solutions":["Log the raw token bytes and decode them with a DER tool (openssl asn1parse) to see which element is absent","Ensure clients use a standard Kerberos/SPNEGO stack (JGSS, browsers with real Kerberos) rather than custom encoders","Catch IllegalStateException around getTokenServerName() and reject the request with 401"],"exampleFix":"// before\nString server = KerberosUtil.getTokenServerName(rawToken);\n\n// after: treat any DER walk failure as an invalid token\ntry {\n  String server = KerberosUtil.getTokenServerName(rawToken);\n} catch (IllegalArgumentException | IllegalStateException e) {\n  LOG.debug(\"Undecodable SPNEGO token\", e);\n  response.sendError(HttpServletResponse.SC_UNAUTHORIZED);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { server = KerberosUtil.getTokenServerName(raw); } catch (IllegalStateException | IllegalArgumentException e) { /* DER layout unexpected: treat as invalid token, 401 */ }","preventionTips":["Decode suspicious tokens with openssl asn1parse before filing bugs","Keep client GSS stacks standard (JGSS / OS Kerberos), not hand-rolled encoders","Include raw token hex in debug logs when this fires"],"tags":["kerberos","spnego","asn1-der","token-parsing"],"backgroundTag":"malformed-spnego-token","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}