{"record":{"id":"65cc25baf4a747c4","repo":"spring-projects/spring-security","slug":"gsscontext-name-of-the-context-initiator-is-null","errorCode":null,"errorMessage":"GSSContext name of the context initiator is null","messagePattern":"GSSContext name of the context initiator is null","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":null,"severity":"error","filePath":"kerberos/kerberos-core/src/main/java/org/springframework/security/kerberos/authentication/sun/SunJaasKerberosTicketValidator.java","lineNumber":263,"sourceCode":"\t */\n\tprivate final class KerberosValidateAction implements PrivilegedExceptionAction<KerberosTicketValidation> {\n\n\t\tbyte[] kerberosTicket;\n\n\t\tprivate KerberosValidateAction(byte[] kerberosTicket) {\n\t\t\tthis.kerberosTicket = kerberosTicket;\n\t\t}\n\n\t\t@Override\n\t\tpublic KerberosTicketValidation run() throws Exception {\n\t\t\tbyte[] responseToken = new byte[0];\n\t\t\tGSSName gssName = null;\n\t\t\tGSSContext context = GSSManager.getInstance().createContext((GSSCredential) null);\n\t\t\twhile (!context.isEstablished()) {\n\t\t\t\tresponseToken = context.acceptSecContext(this.kerberosTicket, 0, this.kerberosTicket.length);\n\t\t\t\tgssName = context.getSrcName();\n\t\t\t\tif (gssName == null) {\n\t\t\t\t\tthrow new BadCredentialsException(\"GSSContext name of the context initiator is null\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tGSSCredential delegationCredential = null;\n\t\t\tif (context.getCredDelegState()) {\n\t\t\t\tdelegationCredential = context.getDelegCred();\n\t\t\t}\n\n\t\t\tif (!SunJaasKerberosTicketValidator.this.holdOnToGSSContext) {\n\t\t\t\tcontext.dispose();\n\t\t\t}\n\t\t\tif (gssName == null) {\n\t\t\t\tthrow new BadCredentialsException(\"GSSContext name of the context initiator is null\");\n\t\t\t}\n\t\t\tString servicePrincipal = SunJaasKerberosTicketValidator.this.servicePrincipal;\n\t\t\tif (servicePrincipal == null) {\n\t\t\t\tthrow new IllegalStateException(\"servicePrincipal must be set\");\n\t\t\t}","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/kerberos/kerberos-core/src/main/java/org/springframework/security/kerberos/authentication/sun/SunJaasKerberosTicketValidator.java#L245-L281","documentation":"Inside the KerberosValidateAction.run() executed via Subject.doAs, after acceptSecContext processes the ticket, context.getSrcName() returned null, meaning GSS could not determine the initiator's identity. This BadCredentialsException indicates the ticket bytes were not a valid/complete GSS context token.","triggerScenarios":"The kerberosTicket byte array passed to acceptSecContext is malformed, empty, truncated, or not a valid SPNEGO/Kerberos AP-REQ token, so the context never establishes an initiator name; the loop then throws this exception.","commonSituations":"Sending the raw 'Authorization: Negotiate xxx' header value without Base64 decoding, headers stripped or modified by proxies/load balancers, browser sending NTLM instead of Kerberos tokens, or an empty token body on a first-leg SPNEGO handshake being treated as a ticket.","solutions":["Verify the token is Base64-decoded and includes the full SPNEGO wrapper; log token length before validation.","Handle the initial empty/first-leg SPNEGO challenge separately instead of passing an empty token to validateTicket.","Check intermediate proxies/load balancers are not stripping or rewriting the Authorization header.","Confirm the browser/client actually obtained a Kerberos (not NTLM) token; check client-side SPN/realm configuration.","Enable sun.security.krb5.debug and JGSS debugging (-Dsun.security.jgss.debug=true) to see where token parsing fails."],"exampleFix":"// before\nbyte[] ticket = authHeader.getBytes(); // \"Negotiate YII...\" as raw bytes\nvalidator.validateTicket(ticket);\n\n// after\nif (!authHeader.startsWith(\"Negotiate \")) throw new BadCredentialsException(\"no kerberos token\");\nbyte[] ticket = Base64.getDecoder().decode(authHeader.substring(\"Negotiate \".length()));\nif (ticket.length == 0) throw new BadCredentialsException(\"empty token\");\nvalidator.validateTicket(ticket);","handlingStrategy":"validation","validationCode":"// reject non-kerberos or empty tokens before validation\nString header = request.getHeader(\"Authorization\");\nif (header == null || !header.startsWith(\"Negotiate \")) throw new BadCredentialsException(\"not a kerberos token\");\nbyte[] token = Base64.getDecoder().decode(header.substring(10));\nif (token.length < 10) throw new BadCredentialsException(\"token too short\");","typeGuard":"static boolean isPlausibleSpnegoToken(byte[] t) {\n    // SPNEGO AbstractSyntaxNotification tag or NTLMSSP signature check\n    if (t == null || t.length < 8) return false;\n    boolean ntlm = t.length > 7 && t[0]=='N' && t[1]=='T' && t[2]=='L' && t[3]=='M';\n    return !ntlm;\n}","tryCatchPattern":"try {\n    KerberosTicketValidation v = validator.validateTicket(token);\n} catch (BadCredentialsException e) {\n    LOGGER.warn(\"unparseable GSS token (len={})\", token.length);\n    response.setHeader(\"WWW-Authenticate\", \"Negotiate\");\n    response.sendError(401);\n}","preventionTips":["Never pass the raw Authorization header bytes; always decode Base64.","Reject NTLMSSP tokens (NTLMSSP signature) before invoking GSS validation.","Ensure proxies/load balancers preserve the Authorization header.","Handle the empty first-leg SPNEGO challenge before validation."],"tags":["kerberos","gss","spnego","invalid-token"],"backgroundTag":"invalid-argument-format","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}