Spaces:
Running
Running
fix: ruff lint — import sorting, unused imports, line length, naming
Browse filesCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
agent_bench/security/pii_redactor.py
CHANGED
|
@@ -65,9 +65,13 @@ class PIIRedactor:
|
|
| 65 |
self._nlp = spacy.load("en_core_web_sm")
|
| 66 |
self.use_ner = True
|
| 67 |
except ImportError:
|
| 68 |
-
logger.warning(
|
|
|
|
|
|
|
| 69 |
except OSError:
|
| 70 |
-
logger.warning(
|
|
|
|
|
|
|
| 71 |
|
| 72 |
def redact(self, text: str) -> RedactionResult:
|
| 73 |
"""Detect and optionally redact PII in the given text."""
|
|
|
|
| 65 |
self._nlp = spacy.load("en_core_web_sm")
|
| 66 |
self.use_ner = True
|
| 67 |
except ImportError:
|
| 68 |
+
logger.warning(
|
| 69 |
+
"pii.use_ner=true but spaCy not installed, falling back to regex-only"
|
| 70 |
+
)
|
| 71 |
except OSError:
|
| 72 |
+
logger.warning(
|
| 73 |
+
"pii.use_ner=true but en_core_web_sm not found, falling back to regex-only"
|
| 74 |
+
)
|
| 75 |
|
| 76 |
def redact(self, text: str) -> RedactionResult:
|
| 77 |
"""Detect and optionally redact PII in the given text."""
|
agent_bench/serving/routes.py
CHANGED
|
@@ -133,7 +133,10 @@ async def ask(body: AskRequest, request: Request) -> AskResponse:
|
|
| 133 |
"violations": out_verdict.violations,
|
| 134 |
}
|
| 135 |
if not out_verdict.passed and out_verdict.action == "block":
|
| 136 |
-
answer =
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
# Store Q+A if session_id provided
|
| 139 |
if body.session_id and conversation_store:
|
|
@@ -215,7 +218,7 @@ async def ask_stream(body: AskRequest, request: Request) -> StreamingResponse:
|
|
| 215 |
output_validator = getattr(request.app.state, "output_validator", None)
|
| 216 |
|
| 217 |
async def event_generator():
|
| 218 |
-
from agent_bench.serving.schemas import StreamEvent
|
| 219 |
|
| 220 |
# Buffer all events so we can validate before sending to client.
|
| 221 |
# The orchestrator emits the final answer as a single chunk (not
|
|
@@ -260,7 +263,7 @@ async def ask_stream(body: AskRequest, request: Request) -> StreamingResponse:
|
|
| 260 |
# Now yield events to the client — safe content only
|
| 261 |
for event in buffered_events:
|
| 262 |
if output_blocked and event.type == "chunk":
|
| 263 |
-
yield
|
| 264 |
else:
|
| 265 |
yield event.to_sse()
|
| 266 |
|
|
|
|
| 133 |
"violations": out_verdict.violations,
|
| 134 |
}
|
| 135 |
if not out_verdict.passed and out_verdict.action == "block":
|
| 136 |
+
answer = (
|
| 137 |
+
"I'm unable to provide a response to this query. "
|
| 138 |
+
"The output was filtered for safety."
|
| 139 |
+
)
|
| 140 |
|
| 141 |
# Store Q+A if session_id provided
|
| 142 |
if body.session_id and conversation_store:
|
|
|
|
| 218 |
output_validator = getattr(request.app.state, "output_validator", None)
|
| 219 |
|
| 220 |
async def event_generator():
|
| 221 |
+
from agent_bench.serving.schemas import StreamEvent
|
| 222 |
|
| 223 |
# Buffer all events so we can validate before sending to client.
|
| 224 |
# The orchestrator emits the final answer as a single chunk (not
|
|
|
|
| 263 |
# Now yield events to the client — safe content only
|
| 264 |
for event in buffered_events:
|
| 265 |
if output_blocked and event.type == "chunk":
|
| 266 |
+
yield StreamEvent(type="chunk", content=filtered_answer).to_sse()
|
| 267 |
else:
|
| 268 |
yield event.to_sse()
|
| 269 |
|
tests/test_audit_logger.py
CHANGED
|
@@ -4,9 +4,6 @@ from __future__ import annotations
|
|
| 4 |
|
| 5 |
import json
|
| 6 |
import os
|
| 7 |
-
from pathlib import Path
|
| 8 |
-
|
| 9 |
-
import pytest
|
| 10 |
|
| 11 |
from agent_bench.security.audit_logger import AuditLogger
|
| 12 |
|
|
|
|
| 4 |
|
| 5 |
import json
|
| 6 |
import os
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
from agent_bench.security.audit_logger import AuditLogger
|
| 9 |
|
tests/test_output_validator.py
CHANGED
|
@@ -5,7 +5,6 @@ from __future__ import annotations
|
|
| 5 |
import pytest
|
| 6 |
|
| 7 |
from agent_bench.security.output_validator import OutputValidator
|
| 8 |
-
from agent_bench.security.types import OutputVerdict
|
| 9 |
|
| 10 |
|
| 11 |
class TestPIILeakage:
|
|
|
|
| 5 |
import pytest
|
| 6 |
|
| 7 |
from agent_bench.security.output_validator import OutputValidator
|
|
|
|
| 8 |
|
| 9 |
|
| 10 |
class TestPIILeakage:
|
tests/test_pii_redactor.py
CHANGED
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
| 4 |
|
| 5 |
import pytest
|
| 6 |
|
| 7 |
-
from agent_bench.security.pii_redactor import PIIRedactor
|
| 8 |
|
| 9 |
|
| 10 |
class TestRegexPatterns:
|
|
|
|
| 4 |
|
| 5 |
import pytest
|
| 6 |
|
| 7 |
+
from agent_bench.security.pii_redactor import PIIRedactor
|
| 8 |
|
| 9 |
|
| 10 |
class TestRegexPatterns:
|
tests/test_security_integration.py
CHANGED
|
@@ -4,14 +4,13 @@ from __future__ import annotations
|
|
| 4 |
|
| 5 |
import json
|
| 6 |
import time
|
| 7 |
-
from pathlib import Path
|
| 8 |
|
| 9 |
import pytest
|
| 10 |
from httpx import ASGITransport, AsyncClient
|
| 11 |
|
|
|
|
| 12 |
from agent_bench.core.config import AppConfig, ProviderConfig, SecurityConfig
|
| 13 |
from agent_bench.core.provider import MockProvider
|
| 14 |
-
from agent_bench.agents.orchestrator import Orchestrator
|
| 15 |
from agent_bench.rag.store import HybridStore
|
| 16 |
from agent_bench.serving.middleware import MetricsCollector, RequestMiddleware
|
| 17 |
from agent_bench.tools.calculator import CalculatorTool
|
|
@@ -49,10 +48,10 @@ def _make_security_app(tmp_path, security_config=None):
|
|
| 49 |
app.state.metrics = MetricsCollector()
|
| 50 |
|
| 51 |
# Security components
|
|
|
|
| 52 |
from agent_bench.security.injection_detector import InjectionDetector
|
| 53 |
-
from agent_bench.security.pii_redactor import PIIRedactor
|
| 54 |
from agent_bench.security.output_validator import OutputValidator
|
| 55 |
-
from agent_bench.security.
|
| 56 |
|
| 57 |
sec = config.security
|
| 58 |
app.state.injection_detector = InjectionDetector(
|
|
@@ -163,8 +162,6 @@ class TestStreamInjectionBlocking:
|
|
| 163 |
@pytest.mark.asyncio
|
| 164 |
async def test_stream_output_validation_runs(self, tmp_path):
|
| 165 |
"""Output containing PII should trigger output validation on stream."""
|
| 166 |
-
from unittest.mock import AsyncMock, patch
|
| 167 |
-
from agent_bench.core.types import TokenUsage
|
| 168 |
from agent_bench.serving.schemas import StreamEvent
|
| 169 |
|
| 170 |
app = _make_security_app(tmp_path)
|
|
|
|
| 4 |
|
| 5 |
import json
|
| 6 |
import time
|
|
|
|
| 7 |
|
| 8 |
import pytest
|
| 9 |
from httpx import ASGITransport, AsyncClient
|
| 10 |
|
| 11 |
+
from agent_bench.agents.orchestrator import Orchestrator
|
| 12 |
from agent_bench.core.config import AppConfig, ProviderConfig, SecurityConfig
|
| 13 |
from agent_bench.core.provider import MockProvider
|
|
|
|
| 14 |
from agent_bench.rag.store import HybridStore
|
| 15 |
from agent_bench.serving.middleware import MetricsCollector, RequestMiddleware
|
| 16 |
from agent_bench.tools.calculator import CalculatorTool
|
|
|
|
| 48 |
app.state.metrics = MetricsCollector()
|
| 49 |
|
| 50 |
# Security components
|
| 51 |
+
from agent_bench.security.audit_logger import AuditLogger
|
| 52 |
from agent_bench.security.injection_detector import InjectionDetector
|
|
|
|
| 53 |
from agent_bench.security.output_validator import OutputValidator
|
| 54 |
+
from agent_bench.security.pii_redactor import PIIRedactor
|
| 55 |
|
| 56 |
sec = config.security
|
| 57 |
app.state.injection_detector = InjectionDetector(
|
|
|
|
| 162 |
@pytest.mark.asyncio
|
| 163 |
async def test_stream_output_validation_runs(self, tmp_path):
|
| 164 |
"""Output containing PII should trigger output validation on stream."""
|
|
|
|
|
|
|
| 165 |
from agent_bench.serving.schemas import StreamEvent
|
| 166 |
|
| 167 |
app = _make_security_app(tmp_path)
|