apereo/cas · critical · IllegalArgumentException
JWKS cannot contain expressions
Error message
JWKS cannot contain expressions
What it means
OidcJsonWebKeyStoreJacksonDeserializer rejects any JWKS JSON value containing Spring expression markers (e.g. #{...}) while deserializing the keystore. Because JWKS content may be written to storage and later resolved, embedding Spring EL would allow expression injection; CAS fails fast with this IllegalArgumentException. It is a security guard, not a format problem.
Solutions
- Remove any #{...} (or other Spring expression markers) from the JWKS JSON values.
- Store literal base64url key material; resolve configuration placeholders before generating the JWKS.
- Validate the JWKS file with a scan for '#{' before loading it into CAS.
- Treat an occurrence as potential injection and audit where the JWKS came from.
Example fix
// before
{"kty":"RSA","kid":"#{keyId}","n":"..."}
// after
{"kty":"RSA","kid":"my-key-1","n":"..."} Defensive patterns
Strategy: validation
Validate before calling
if (jwksJson.contains("#{") || jwksJson.contains("${")) {
throw new IllegalArgumentException("JWKS contains expression markers");
} Try / catch
try { keystore.load(inputStream); } catch (IllegalArgumentException e) {
LOGGER.error("Rejected JWKS with expression content: {}", e.getMessage());
} Prevention
- Never paste configuration templates into JWKS files
- Resolve placeholders in a pre-processing step before key generation
- Lint JWKS files in CI for '#{'/'${' markers
- Treat expression markers in JWKS as a security incident
When it happens
Trigger: Loading or storing a JWKS JSON document whose keys' string values (kty, n, e, kid, x5c entries, etc.) contain expression markers like '#{' resolved by SpringExpressionLanguageValueResolver.
Common situations: Administrators pasting template-style values into a JWKS file; YAML/properties templating leaking #{...} placeholders into the keystore; malicious JWKS payloads in multi-tenant setups.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Service with client id is configured to encrypt tokens, yet…
- Invalid access token
- Unsupported key type:
- Invalid signature
- Unable to locate JSON web key for
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/cc45fb4289cecbba.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-oidc-core-api/src/main/java/org/apereo/cas/oidc/jwks/OidcJsonWebKeyStoreJacksonDeserializer.java:45
});
}
private static void rejectSpringExpressions(final JsonNode node) {
if (node.isObject()) {
node.properties().forEach(entry -> {
rejectSpringExpression(entry.getKey());
rejectSpringExpressions(entry.getValue());
});
} else if (node.isArray()) {
node.values().forEach(OidcJsonWebKeyStoreJacksonDeserializer::rejectSpringExpressions);
} else if (node.isString()) {
rejectSpringExpression(node.asString());
}
}
private static void rejectSpringExpression(final String value) {
if (SpringExpressionLanguageValueResolver.getInstance().hasExpressionMarkers(value)) {
throw new IllegalArgumentException("JWKS cannot contain expressions");
}
}
}
View on GitHub (pinned to e7288fc434)