{"record":{"id":"2870df6bf6204844","repo":"apereo/cas","slug":"certificate-path-length-s-exceeds-maximum-value","errorCode":null,"errorMessage":"Certificate path length %s exceeds maximum value %s.","messagePattern":"Certificate path length (.+?) exceeds maximum value (.+?)\\.","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-x509-core/src/main/java/org/apereo/cas/adaptors/x509/authentication/handler/support/X509CredentialsAuthenticationHandler.java","lineNumber":254,"sourceCode":"                val msg = \"Certificate subject does not match pattern \" + this.regExSubjectDnPattern.pattern();\n                LOGGER.error(msg);\n                throw new FailedLoginException(msg);\n            }\n            if (this.checkKeyUsage && !isValidKeyUsage(cert)) {\n                val msg = \"Certificate keyUsage constraint forbids SSL client authentication.\";\n                LOGGER.error(msg);\n                throw new FailedLoginException(msg);\n            }\n        } else {\n            if (pathLength == Integer.MAX_VALUE && !this.maxPathLengthAllowUnspecified) {\n                val msg = \"Unlimited certificate path length not allowed by configuration.\";\n                LOGGER.error(msg);\n                throw new FailedLoginException(msg);\n            }\n            if (pathLength > this.maxPathLength && pathLength < Integer.MAX_VALUE) {\n                val msg = String.format(\"Certificate path length %s exceeds maximum value %s.\", pathLength, this.maxPathLength);\n                LOGGER.error(msg);\n                throw new FailedLoginException(msg);\n            }\n        }\n    }\n\n    /**\n     * Checks if is valid key usage. <p>\n     * KeyUsage ::= BIT STRING { digitalSignature (0), nonRepudiation (1),\n     * keyEncipherment (2), dataEncipherment (3), keyAgreement (4),\n     * keyCertSign (5), cRLSign (6), encipherOnly (7), decipherOnly (8) }\n     *\n     * @param certificate the certificate\n     * @return true, if  valid key usage\n     */\n    private boolean isValidKeyUsage(final X509Certificate certificate) {\n        LOGGER.debug(\"Checking certificate keyUsage extension\");\n        val keyUsage = certificate.getKeyUsage();\n        if (keyUsage == null) {\n            LOGGER.warn(\"Configuration specifies checkKeyUsage but keyUsage extension not found in certificate.\");","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-x509-core/src/main/java/org/apereo/cas/adaptors/x509/authentication/handler/support/X509CredentialsAuthenticationHandler.java#L236-L272","documentation":"X509CredentialsAuthenticationHandler.validate() compares a CA certificate's basicConstraints pathLenConstraint with the configured maxPathLength. A finite path length exceeding the configured maximum makes the chain too deep and validation throws FailedLoginException.","triggerScenarios":"A CA certificate with an explicit pathLenConstraint value greater than cas.authn.x509.max-path-length is presented during X.509 authentication.","commonSituations":"maxPathLength left at a small default while the real PKI hierarchy has more intermediate CA levels; after an org merge the new chains are deeper than the configured limit.","solutions":["Increase cas.authn.x509.max-path-length to at least the number of intermediate CA levels in your hierarchy.","Flatten the PKI so client certs are issued from a shallower CA path.","Inspect chain depth with: openssl x509 -in cert.pem -noout -text | grep pathlen.","If chains are legitimately unbounded, combine with max-path-length-allow-unspecified=true."],"exampleFix":"// before\ncas.authn.x509.max-path-length=1\n// after\ncas.authn.x509.max-path-length=5","handlingStrategy":"validation","validationCode":"int pl = cert.getBasicConstraints();\nif (pl >= 0 && pl > configuredMaxPathLength) { reject(\"CA chain deeper than configured max\"); }","typeGuard":"boolean withinMaxPathLength(X509Certificate cert, int max) {\n    int pl = cert.getBasicConstraints();\n    return pl < 0 || pl <= max || pl == Integer.MAX_VALUE;\n}","tryCatchPattern":"try {\n    handler.authenticate(credential);\n} catch (FailedLoginException e) {\n    // path length exceeds max: raise cas.authn.x509.max-path-length\n}","preventionTips":["Size max-path-length to your actual CA hierarchy depth.","Re-inspect depth after PKI reorganizations or mergers.","Check pathlen with openssl x509 -text.","Keep chain depth shallow where possible."],"tags":["x509","certificate","path-length","configuration"],"backgroundTag":"certificate-path-length-too-deep","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}