{"record":{"id":"30360df0c2b981e2","repo":"apache/hadoop","slug":"not-an-ap-req-token","errorCode":null,"errorMessage":"Not an AP-REQ token","messagePattern":"Not an AP-REQ token","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":401,"severity":"error","filePath":"hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/KerberosUtil.java","lineNumber":327,"sourceCode":"    if (oid.equals(DER.SPNEGO_MECH_OID)) {\n      // NegotiationToken ::= CHOICE {\n      //     neg-token-init[0] NegTokenInit\n      // }\n      // NegTokenInit ::= SEQUENCE {\n      //     mech-token[2]     InitialContextToken\n      // }\n      token = token.next().get(0xa0, 0x30, 0xa2, 0x04).next();\n      oid = token.next();\n    }\n    if (!oid.equals(DER.KRB5_MECH_OID)) {\n      throw new IllegalArgumentException(\"Malformed gss token\");\n    }\n    // InnerContextToken ::= {\n    //     token-id[1]\n    //     AP-REQ\n    // }\n    if (token.next().getTag() != 1) {\n      throw new IllegalArgumentException(\"Not an AP-REQ token\");\n    }\n    // AP-REQ ::= [APPLICATION 14] SEQUENCE {\n    //     ticket[3]      Ticket\n    // }\n    DER ticket = token.next().get(0x6e, 0x30, 0xa3, 0x61, 0x30);\n    // Ticket ::= [APPLICATION 1] SEQUENCE {\n    //     realm[1]       String\n    //     sname[2]       PrincipalName\n    // }\n    // PrincipalName ::= SEQUENCE {\n    //     name-string[1] SEQUENCE OF String\n    // }\n    String realm = ticket.get(0xa1, 0x1b).getAsString();\n    DER names = ticket.get(0xa2, 0x30, 0xa1, 0x30);\n    StringBuilder sb = new StringBuilder();\n    while (names.hasNext()) {\n      if (sb.length() > 0) {\n        sb.append('/');","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/KerberosUtil.java#L309-L345","documentation":"Inside KerberosUtil.getTokenServerName(), after the mechanism OID check passes, the first inner-context byte (token-id) must be 1, which identifies an AP-REQ — the message a client sends when presenting a Kerberos ticket. Any other tag (e.g. 0x0a KRB-ERROR, or a TGT-REQ) triggers IllegalArgumentException('Not an AP-REQ token').","triggerScenarios":"Passing a GSS token that wraps a KRB-ERROR (typical when the KDC rejected the client) or an AS-REQ/TGS-REQ instead of the AP-REQ a server receives during SPNEGO authentication.","commonSituations":"Replaying captured Kerberos traffic of the wrong message type into a test harness; server-side code invoked on error responses after clock skew or unknown-principal failures; protocol-level fuzzing.","solutions":["Only feed tokens taken from the Authorization header of a genuine client SPNEGO handshake (always an AP-REQ)","Handle upstream Kerberos errors (clock skew, unknown principal) so KRB-ERROR tokens never reach this parser","Catch IllegalArgumentException and fail the authentication request with 401 rather than crashing the handler"],"exampleFix":"// before\nString server = KerberosUtil.getTokenServerName(rawToken);\n\n// after: guard with the documented unchecked exception\ntry {\n  String server = KerberosUtil.getTokenServerName(rawToken);\n} catch (IllegalArgumentException e) {\n  response.sendError(HttpServletResponse.SC_UNAUTHORIZED, \"Invalid SPNEGO token\");\n}","handlingStrategy":"try-catch","validationCode":"// token-id byte must be 1 (AP-REQ); cheap pre-check after mech OID acceptance is impractical — validate at capture instead:\nif (rawToken == null || rawToken.length < 10) throw new AuthenticationException(\"token too short\");","typeGuard":null,"tryCatchPattern":"try { KerberosUtil.getTokenServerName(raw); } catch (IllegalArgumentException e) { /* KRB-ERROR or wrong message type: 401 + Negotiate, log at debug */ }","preventionTips":["Only parse tokens from genuine client SPNEGO handshakes","Fix upstream Kerberos failures (clock skew, unknown principal) so KRB-ERROR never reaches parsing","Never replay captured non-AP-REQ traffic into this API"],"tags":["kerberos","spnego","gss-api","token-parsing"],"backgroundTag":"malformed-spnego-token","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}