fix(cache): let a cache mask its keys in the log - #160
Open
cosmin-staicu wants to merge 1 commit into
Open
Conversation
cosmin-staicu
requested review from
alinahornet,
cosminvlad,
litheon,
lucianaparaschivei and
razvalex
as code owners
September 8, 2026 15:17
|
🔎 Maintainer heads-up: automated triage flagged this PR as potentially material, so it may need a signed CLA in addition to the DCO sign-off. Strong signals
This is advisory only — the bot does not decide. Please judge against the CLA criteria (material, product-critical, patent-sensitive, corporate contributor, broad commercial use). Note that thresholds can be gamed by splitting PRs, so use your judgement.
|
cosmin-staicu
force-pushed
the
fix/log-keys-redaction
branch
7 times, most recently
from
September 8, 2026 16:31
f7b63fa to
5a8db68
Compare
ICacheOptions.LogKeys (default true) on the three options classes. Off, every log line that named a key keeps the prefix the key strategy composed and masks the caller's key to its first three characters (myapp:s:cos****); a key not under a recognizable prefix is masked whole. Each layer learns its prefix by composing a probe key through its own strategy, the Redis layer adds the cache-key prefix on top, and the adapter hands its own prefix to the tier copies it configures. Masking runs only when the line is written. The generated log methods take a LoggedKey and keep a CacheKey/RedisKey wrapper beside them, so no call site changes and a raw key cannot reach them by accident. AddDistributedCache turns the switch off for its own provider and masks the key in its own two messages, because IDistributedCache keys are the consumer's and can be secrets. Closes #129 Signed-off-by: Cosmin Staicu <cosmin.staicu@uipath.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9jRarnMLeZRZ5rYySRhkh
cosmin-staicu
force-pushed
the
fix/log-keys-redaction
branch
from
September 8, 2026 16:55
5a8db68 to
078dc8f
Compare
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Closes #129.
Problem
Cache keys are written to logs, several of them at
Warning. For the application's own caches that is usually harmless. For theIDistributedCacheadapter it is not: those keys are the consumer's and can be secrets, such as the ASP.NET Core session id. A Redis blip raised the inner-cache warning paths and wrote session identifiers to the log (CWE-532).Change
ICacheOptions.LogKeys, defaulttrue, onInMemoryCacheOptions,InMemoryRedisCacheOptionsandRedisCacheOptions. The interface member has a default implementation, so hand-writtenICacheOptionsimplementers keep compiling.****:d:ses****at the cache layer,myapp:dh:d:ses****at the Redis layer. Each layer learns its prefix by composing a probe key through its own strategy; a custom strategy whose output does not end with the key yields no prefix, and the whole value is masked, since nothing in it is known to be safe. The Redis layer adds the cache-key prefix on top of its own. The adapter hands its ownd:prefix to the tier copies it configures, because it neutralizes their key strategy.LoggedKey, an internal struct whoseToStringdoes the masking. TheLoggerMessagegenerator only callsToStringwhen the level is enabled, so a masked Trace site on a hot path costs nothing when Trace is off.CacheKeyorRedisKeynow takes aLoggedKeyand is namedLog…Core; a same-namedLog…(CacheKey)wrapper beside it applies the cache's switch. The 100-odd call sites are untouched, and a new call site cannot bypass the switch: a raw key does not convert toLoggedKey. Applied mechanically toMultilayerCache(22 methods),MultilayerHashCache(16),RedisCache(5),RedisHashCache(3) andCacheEventPublisher(1); the four joined-keys sites go through the same helper. Not done viaCacheKey.ToString(), which the issue rules out because the implicit string conversion is used to compose physical keys.LogKeys = falseon the private copies of its tier's options, next to the existingCacheKeyStrategyneutralization, and masks the key in its own two messages.Tests
LoggedKeyTests: verbatim, prefix kept and key masked, case-insensitive prefix match, whole-value masking without a matching prefix, short keys, prefix learning for the Redis and cache-key strategies including one that does not keep the key as a tail, join.KeyLoggingTests: real caches through the container with a Trace-level capturing logger. With the switch off, no line contains the key and lines showsec****; with it on, the reverse. Same for the hash cache. The distributed adapter on theInMemorytier logsd:Sec****even with the tier's own switch left at its default.RedisCacheTestsandRedisHashCacheTests: the miss line follows the switch, using the mocked logger.UiPathDistributedCacheTests: the failed-write warning asserts the masked key and the absence of the raw one.Docs:
LogKeysrows in the three provider tables, the distributed-cache note rewritten from "keys appear in logs" to what now happens,appsettings.all.jsongains the setting, changelog under Fixed.🤖 Generated with Claude Code
https://claude.ai/code/session_01V9jRarnMLeZRZ5rYySRhkh