spring-projects/spring-security · warning

Your keytab is in the classpath. This file needs special…

Error message

Your keytab is in the classpath. This file needs special protection and shouldn't be in the classpath. JAAS may also not be able to load this file from classpath.

What it means

SunJaasKrb5LoginConfig.afterPropertiesSet logs this warning when the configured keyTabLocation is a ClassPathResource. A keytab holds long-lived Kerberos keys and must be protected on disk with restricted permissions; packaging it inside the classpath (JAR/WAR) both exposes it to anyone with the artifact and prevents JAAS from reliably reading it via Krb5LoginModule.

Solutions

  1. Move the keytab outside the classpath (e.g. /etc/security/myapp.keytab) and reference it with a FileSystemResource or a file: URL.
  2. Restrict file permissions to the service user (chown root:myapp && chmod 600 /etc/security/myapp.keytab).
  3. Externalize the location via configuration (application.yml / K8s secret-mounted volume) instead of bundling the file in the artifact.
  4. Regenerate the keytab with ktpass/kadmin if it was committed to source control, since it is now compromised.

Example fix

// before
config.setKeyTabLocation(new ClassPathResource("krb5.keytab"));

// after
config.setKeyTabLocation(new FileSystemResource("/etc/security/myapp.keytab"));
// or application.yml: key-tab-location: file:/etc/security/myapp.keytab
Defensive patterns

Strategy: validation

Validate before calling

Resource keytab = config.getKeyTabLocation();
if (keytab instanceof ClassPathResource) {
    throw new IllegalStateException("keyTabLocation must point outside the classpath (use FileSystemResource or file: URL)");
}

Type guard

boolean isExternalKeytab(Resource r) { return r != null && !(r instanceof ClassPathResource); }

Try / catch

This is only a LOG.warn, not an exception — afterPropertiesSet proceeds; catch nothing, instead fail your own startup validation if you detect a ClassPathResource.

Prevention

When it happens

Trigger: Configuring SunJaasKrb5LoginConfig.setKeyTabLocation(new ClassPathResource("krb5.keytab")) — or Spring Security Kerberos properties like spring.security.kerberos.service-principal/key-tab-location resolving to a classpath: location — then calling afterPropertiesSet (typically via the loginConfig bean factory method).

Common situations: Setting key-tab-location: classpath:krb5.keytab in application.yml; dropping the keytab in src/main/resources so it lands in the JAR; copying sample configs verbatim in Docker/Kubernetes deployments.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/231c60d5453b1360. Report an issue: GitHub.

Appendix: source

Thrown at kerberos/kerberos-client/src/main/java/org/springframework/security/kerberos/client/config/SunJaasKrb5LoginConfig.java:81

	public void setUseTicketCache(Boolean useTicketCache) {
		this.useTicketCache = useTicketCache;
	}

	public void setIsInitiator(Boolean isInitiator) {
		this.isInitiator = isInitiator;
	}

	public void setDebug(Boolean debug) {
		this.debug = debug;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.hasText(this.servicePrincipal, "servicePrincipal must be specified");

		if (this.keyTabLocation != null && this.keyTabLocation instanceof ClassPathResource) {
			LOG.warn(
					"Your keytab is in the classpath. This file needs special protection and shouldn't be in the classpath. JAAS may also not be able to load this file from classpath.");
		}

		if (!this.useTicketCache) {
			Assert.notNull(this.keyTabLocation, "keyTabLocation must be specified when useTicketCache is false");
		}

		if (this.keyTabLocation != null) {
			this.keyTabLocationAsString = this.keyTabLocation.getURL().toExternalForm();
			if (this.keyTabLocationAsString.startsWith("file:")) {
				this.keyTabLocationAsString = this.keyTabLocationAsString.substring(5);
			}
		}
	}

	@Override
	public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
		HashMap<String, String> options = new HashMap<>();

View on GitHub (pinned to 96852e8860)