fix(mesh): Batch B review fixes — bounded store read, cache poison guard, test hardening

This commit is contained in:
Joseph Doherty
2026-08-06 04:10:03 -04:00
parent 68a416e4fc
commit 24e55d3395
7 changed files with 314 additions and 68 deletions
@@ -31,10 +31,13 @@ public sealed class MeshCommandAuthInterceptorTests
NullLogger<MeshCommandAuthInterceptor>.Instance);
private static ServerCallContext CreateContext(string method, string? authorizationHeader)
=> CreateContext(method, authorizationHeader is null ? [] : [authorizationHeader]);
private static ServerCallContext CreateContext(string method, string[] authorizationHeaders)
{
var headers = new Metadata();
if (authorizationHeader is not null)
headers.Add("authorization", authorizationHeader);
foreach (var value in authorizationHeaders)
headers.Add("authorization", value);
return new FakeServerCallContext(method, headers);
}
@@ -133,6 +136,20 @@ public sealed class MeshCommandAuthInterceptorTests
await Invoke(interceptor, context); // no throw
}
[Fact]
public async Task ExecuteMethod_WithAJunkAuthorizationHeaderBeforeTheRealOne_IsDenied()
{
// First entry wins, and it must parse. This interceptor originally scanned past a non-Bearer
// header for a later Bearer one while its central-side clone took the first entry, so the
// two clones gave OPPOSITE answers to this exact request. Both now share
// GrpcRequestHeaders and both deny it; pinned identically on CentralCommandAuthInterceptor.
var interceptor = CreateInterceptor("the-cluster-psk");
var context = CreateContext(ExecuteMethod, ["junk", "Bearer the-cluster-psk"]);
var ex = await Should.ThrowAsync<RpcException>(() => Invoke(interceptor, context));
ex.StatusCode.ShouldBe(StatusCode.PermissionDenied);
}
[Fact]
public async Task ExecuteMethod_TokenComparison_IsNotAPrefixMatch()
{