Caffeine provides high-performance in-memory caching where developers must explicitly manage resource boundaries, key/value integrity, and safe class instantiation. While built-in primitives control sizing and time-to-live, shared mutable states, configuration sources, and dynamic class loads remain security-sensitive surfaces. Developers should enforce strict bounds, reject null inputs, and validate untrusted configuration or instantiation pathways to fail closed against potential resource exhaustion and injection risks.
Essential implementation rules
Validate Cache Arguments and Configure Mandatory Options
When configuring weighted eviction via maximumWeight(long), explicitly provide a Weigher instance that returns non-negative integer weights without throwing unhandled exceptions. Never pass null keys to cache operations or null values to put, putAll, or the asMap() view, as Caffeine throws NullPointerException for these inputs.
Enforce Store-by-Value Semantics or Immutability for Shared Caches
Ensure mutable objects placed in JCache use store-by-value semantics by configuring a CopierFactory or enforce strict immutability for all key and value types. When store-by-value is disabled, direct object references return via identity copying, risking cross-tenant data corruption if mutated.
Restrict and Validate Configuration Source URIs for JCache
Ensure that CacheManager URIs originate from trusted file paths or trusted classpaths. Override configSource using TypesafeConfigurator.setConfigSource() to enforce safe location resolving and reject unexpected or untrusted schemes.
Allowlist Class Names During JCache Configuration Instantiation
Register a custom FactoryCreator using TypesafeConfigurator.setFactoryCreator() to validate requested class names against an approved allowlist before any reflection-based instantiation occurs.
Configure Bounded Cache Capacities and Timeouts
Use maximumSize to limit the cache’s number of entries and expireAfterWrite when entries should be automatically removed after a fixed duration. Apply explicit timeout bounds to asynchronous computations using methods like orTimeout before storing them in an AsyncCache to prevent permanent heap occupation.
caffeine: All Security Cards
Approximately 1,144 tokens
On this card
Category: api contract misuse
Validate Cache Arguments and Configure Mandatory Options Correctly
Use when
Use when constructing caches, configuring custom weighers, and interacting with cache methods or map views to ensure required arguments, non-null values, and valid signatures are correctly provided.
Secure rules
Rule 1: Pair maximum weight settings with explicit weigher implementations and ensure weighers return non-negative weights.
When configuring weighted eviction via maximumWeight(long), you must explicitly provide a Weigher instance and pair them together to avoid startup exceptions. Ensure custom Weigher implementations return non-negative integer weights and do not throw unhandled exceptions.
Do not pass null keys to cache operations or null keys or values to put, putAll, or the asMap() view. Caffeine throws NullPointerException for these inputs. A loading or mapping function may return null only when the cache declares a nullable value type; that result represents no mapping and is not stored.
public String getValueSafely(Cache<String, String> cache, String key) { if (key == null) { return null; } return cache.getIfPresent(key);}
Category: boundary control
Enforce Store-by-Value Semantics or Immutability for Shared Caches
Use when
Sharing JCache instances across application security boundaries where mutable objects are stored and accessed.
Secure rules
Rule 1: Configure store-by-value semantics or use strictly immutable cache values when sharing JCache instances across security boundaries.
When store-by-value is disabled, CacheProxy returns direct object references to callers via identity copying. If cached values are mutable, changes made by one caller will mutate shared state for all other users, leading to cross-tenant data corruption. Ensure mutable objects placed in JCache use store-by-value by configuring a CopierFactory or enforce immutability for all key and value types.
CaffeineConfiguration<String, MyData> config = new CaffeineConfiguration<>();config.setStoreByValue(true);config.setCopierFactory(() -> new JavaSerializationCopier());Cache<String, MyData> cache = cacheManager.createCache("secureCache", config);
Category: configuration source integrity
Restrict and validate configuration source URIs for JCache
Use when
When loading external configuration resources for Caffeine JCache using CacheManager.getURI() and TypesafeConfigurator.
Secure rules
Rule 1: Validate external configuration source URIs before parsing them.
Ensure that CacheManager URIs originate from trusted file paths or trusted classpaths. Override configSource using TypesafeConfigurator.setConfigSource() to enforce safe location resolving and reject unexpected or untrusted schemes.
TypesafeConfigurator.setConfigSource((uri, classloader) -> { if (uri != null && !"classpath".equalsIgnoreCase(uri.getScheme())) { throw new IllegalArgumentException("Only classpath configuration URIs are allowed"); } return ConfigFactory.load(classloader);});
Category: dangerous execution
Validate Class Names During JCache Configuration Instantiation
Use when
Configuring JCache integrations that dynamically instantiate classes from configuration settings using TypesafeConfigurator.
Secure rules
Rule 1: Allowlist class names before instantiation in TypesafeConfigurator.
Register a custom FactoryCreator using TypesafeConfigurator.setFactoryCreator() to validate requested class names against an approved allowlist before reflection-based instantiation.
TypesafeConfigurator.setFactoryCreator(className -> { if (!className.startsWith("com.example.cache.")) { throw new SecurityException("Unauthorized class instantiation: " + className); } return FactoryBuilder.factoryOf(className);});
Category: resource exhaustion
Configure Bounded Cache Capacities and Timeouts to Prevent Resource Exhaustion
Use when
When building caches or handling asynchronous computations in Caffeine to prevent unbounded heap memory consumption and thread starvation.
Secure rules
Rule 1: Configure cache eviction according to the required size and lifetime limits
Use maximumSize to limit the cache’s number of entries and expireAfterWrite when entries should be automatically removed after a fixed duration following creation or replacement.
Rule 2: Enforce explicit application-level timeouts on pending asynchronous computations in AsyncCache.
Apply explicit timeout bounds to asynchronous computations using methods like orTimeout before storing them in an AsyncCache so that unresolved futures do not permanently occupy heap memory.
Validate Cache Arguments and Configure Mandatory Options Correctly
Approximately 380 tokens
Use when
Use when constructing caches, configuring custom weighers, and interacting with cache methods or map views to ensure required arguments, non-null values, and valid signatures are correctly provided.
Secure rules
Rule 1: Pair maximum weight settings with explicit weigher implementations and ensure weighers return non-negative weights.
When configuring weighted eviction via maximumWeight(long), you must explicitly provide a Weigher instance and pair them together to avoid startup exceptions. Ensure custom Weigher implementations return non-negative integer weights and do not throw unhandled exceptions.
Do not pass null keys to cache operations or null keys or values to put, putAll, or the asMap() view. Caffeine throws NullPointerException for these inputs. A loading or mapping function may return null only when the cache declares a nullable value type; that result represents no mapping and is not stored.
public String getValueSafely(Cache<String, String> cache, String key) { if (key == null) { return null; } return cache.getIfPresent(key);}
Enforce Store-by-Value Semantics or Immutability for Shared Caches
Approximately 240 tokens
Use when
Sharing JCache instances across application security boundaries where mutable objects are stored and accessed.
Secure rules
Rule 1: Configure store-by-value semantics or use strictly immutable cache values when sharing JCache instances across security boundaries.
When store-by-value is disabled, CacheProxy returns direct object references to callers via identity copying. If cached values are mutable, changes made by one caller will mutate shared state for all other users, leading to cross-tenant data corruption. Ensure mutable objects placed in JCache use store-by-value by configuring a CopierFactory or enforce immutability for all key and value types.
CaffeineConfiguration<String, MyData> config = new CaffeineConfiguration<>();config.setStoreByValue(true);config.setCopierFactory(() -> new JavaSerializationCopier());Cache<String, MyData> cache = cacheManager.createCache("secureCache", config);
Restrict and validate configuration source URIs for JCache
Approximately 205 tokens
Use when
When loading external configuration resources for Caffeine JCache using CacheManager.getURI() and TypesafeConfigurator.
Secure rules
Rule 1: Validate external configuration source URIs before parsing them.
Ensure that CacheManager URIs originate from trusted file paths or trusted classpaths. Override configSource using TypesafeConfigurator.setConfigSource() to enforce safe location resolving and reject unexpected or untrusted schemes.
TypesafeConfigurator.setConfigSource((uri, classloader) -> { if (uri != null && !"classpath".equalsIgnoreCase(uri.getScheme())) { throw new IllegalArgumentException("Only classpath configuration URIs are allowed"); } return ConfigFactory.load(classloader);});
Validate Class Names During JCache Configuration Instantiation
Approximately 175 tokens
Use when
Configuring JCache integrations that dynamically instantiate classes from configuration settings using TypesafeConfigurator.
Secure rules
Rule 1: Allowlist class names before instantiation in TypesafeConfigurator.
Register a custom FactoryCreator using TypesafeConfigurator.setFactoryCreator() to validate requested class names against an approved allowlist before reflection-based instantiation.
TypesafeConfigurator.setFactoryCreator(className -> { if (!className.startsWith("com.example.cache.")) { throw new SecurityException("Unauthorized class instantiation: " + className); } return FactoryBuilder.factoryOf(className);});
Configure Bounded Cache Capacities and Timeouts to Prevent Resource Exhaustion
Approximately 261 tokens
Use when
When building caches or handling asynchronous computations in Caffeine to prevent unbounded heap memory consumption and thread starvation.
Secure rules
Rule 1: Configure cache eviction according to the required size and lifetime limits
Use maximumSize to limit the cache’s number of entries and expireAfterWrite when entries should be automatically removed after a fixed duration following creation or replacement.
Rule 2: Enforce explicit application-level timeouts on pending asynchronous computations in AsyncCache.
Apply explicit timeout bounds to asynchronous computations using methods like orTimeout before storing them in an AsyncCache so that unresolved futures do not permanently occupy heap memory.