What happened
A widely used .NET cache library rebuilds objects from data read out of Redis without restricting which types are allowed. If an attacker can write to Redis — via an unauthenticated instance, via SSRF, or via your own application — they choose which classes get constructed when your app reads the cache. From there to remote code execution is a short step.
Why it is worse than it looks
Deserialization is often treated as a problem that only appears "when you accept strange input". But the cache is input — and it is the input most developers do not think of as input:
- Redis rarely appears in the application threat model
- It frequently has no auth on internal networks
- The data in it is treated as "ours"
This is exactly A08 Software or Data Integrity Failures in Top 10:2025 — trusting data because of where it came from rather than because it was validated.
What to do
- Upgrade the library to the patched release.
- Add a type allowlist to the serializer.
System.Text.Jsonis safe by default; the danger sits inBinaryFormatterand serializers withTypeNameHandling. - Enable Redis auth and place it on a network unreachable from outside.
// ❌ TypeNameHandling.All lets the payload declare its own classvar settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; // ✓ Types come from your code, never from the datavar opts = new JsonSerializerOptions { /* defaults are safe */ };var value = JsonSerializer.Deserialize<CacheEntry>(json, opts);Verifying
Write a payload that declares its own type into the cache, then read it back — the application must reject it, not construct it:
[Fact]public async Task Cache_Rejects_SelfDeclaringPayload(){ await _redis.StringSetAsync("k", """{"$type":"System.Diagnostics.Process, System","x":1}"""); var act = () => _cache.GetAsync<CacheEntry>("k"); await act.Should().ThrowAsync<JsonException>();}
Comments
Commenting needs an account with at least one completed lesson. That condition is what keeps this thread worth reading: every point belongs to someone who can be asked back, and reputation accrues over time.
You can still read every comment below without an account. Signing in brings you back to this exact spot, not to the top of the page.
Loading comments…