fix(security): stop leaking capability exception messages (#291)

Sanitizes node capability error responses while preserving details in local logs and updates tests for generic responses.\n\nValidation: local ARM64 build passed; Shared tests 1296 passed / 20 skipped; Tray tests 466 passed; remote CI green.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
github-actions[bot] 2026-05-07 18:12:36 -04:00 committed by GitHub
parent 43873c1005
commit ad120cdf70
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 13 additions and 13 deletions

View File

@ -60,7 +60,7 @@ public class CameraCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("Camera list failed", ex);
return Error($"List failed: {ex.Message}");
return Error("List failed");
}
}
@ -106,7 +106,7 @@ public class CameraCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("Camera snap failed", ex);
return Error($"Snap failed: {ex.Message}");
return Error("Snap failed");
}
}
@ -147,7 +147,7 @@ public class CameraCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("Camera clip failed", ex);
return Error($"Clip failed: {ex.Message}");
return Error("Clip failed");
}
}
}

View File

@ -64,7 +64,7 @@ public class LocationCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("location.get failed", ex);
return Error($"Location failed: {ex.Message}");
return Error("Location failed");
}
}
}

View File

@ -84,7 +84,7 @@ public class ScreenCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("Screen capture failed", ex);
return Error($"Capture failed: {ex.Message}");
return Error("Capture failed");
}
}
@ -134,7 +134,7 @@ public class ScreenCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("Screen recording failed", ex);
return Error($"Recording failed: {ex.Message}");
return Error("Recording failed");
}
}

View File

@ -271,7 +271,7 @@ public class SystemCapability : NodeCapabilityBase
{
// Rail 1: no silent fallback — handler exceptions become typed denies.
Logger.Error($"[system.run] corr={correlationId} path=v2 handler threw", ex);
v2Result = ExecApprovalV2Result.ValidationFailed($"Handler exception: {ex.Message}");
v2Result = ExecApprovalV2Result.ValidationFailed("Handler exception");
}
Logger.Info($"[system.run] corr={correlationId} decision={v2Result.Code} reason={v2Result.Reason}");
@ -413,7 +413,7 @@ public class SystemCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("system.run failed", ex);
return Error($"Execution failed: {ex.Message}");
return Error("Execution failed");
}
}
@ -614,7 +614,7 @@ public class SystemCapability : NodeCapabilityBase
catch (Exception ex)
{
Logger.Error("execApprovals.set failed", ex);
return Error($"Failed to update policy: {ex.Message}");
return Error("Failed to update policy");
}
}

View File

@ -2082,7 +2082,7 @@ public class ScreenCapabilityTests
var req = new NodeInvokeRequest { Id = "s5", Command = "screen.snapshot", Args = Parse("""{}""") };
var res = await cap.ExecuteAsync(req);
Assert.False(res.Ok);
Assert.Contains("Display access denied", res.Error);
Assert.Equal("Capture failed", res.Error);
}
[Fact]
@ -2327,7 +2327,7 @@ public class ScreenCapabilityTests
var req = new NodeInvokeRequest { Id = "s15", Command = "screen.record", Args = Parse("""{}""") };
var res = await cap.ExecuteAsync(req);
Assert.False(res.Ok);
Assert.Contains("Capture permission denied", res.Error);
Assert.Equal("Recording failed", res.Error);
}
}
@ -2457,7 +2457,7 @@ public class CameraCapabilityTests
var req = new NodeInvokeRequest { Id = "cam6", Command = "camera.snap", Args = Parse("""{}""") };
var res = await cap.ExecuteAsync(req);
Assert.False(res.Ok);
Assert.Contains("Camera access blocked", res.Error);
Assert.Equal("Snap failed", res.Error);
}
[Fact]
@ -2892,7 +2892,7 @@ public class LocationCapabilityTests
var req = new NodeInvokeRequest { Id = "loc6", Command = "location.get", Args = Parse("""{}""") };
var res = await cap.ExecuteAsync(req);
Assert.False(res.Ok);
Assert.Contains("GPS unavailable", res.Error);
Assert.Equal("Location failed", res.Error);
}
[Fact]