Repository navigation
Conversation
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…ests Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…equest body The route was reading g.tenant_id and g.subscription_id which are never set by verify_jwt. Fixed to read tenant_id from g.user['tenant'] (matches the principal dict set by auth.py) and subscription_id from the validated request body, consistent with how scans.py handles it. Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…nt isolation test Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…opilot Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…ty, and role access Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.OpenSSF Scorecard
Scanned Files
|
…ial scan false positive Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…quirements-dev Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…enerate locks, reformat code Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…P auth
Critical fixes:
- Sanitize LLM answer through clean_text before returning to API callers
- Validate parsed answer is a string before using it
- Gate scan_subscription to operator/admin roles; viewer bypass via agent route was a privilege escalation
- Add subscription allowlist check to MCP call_tool handler (was missing, HTTP route had it)
- Replace per-call psycopg2.connect in MCP with SimpleConnectionPool to avoid exhausting DB connections
Warning fixes:
- Cap tool result serialization at 4 KB to prevent unbounded prompt growth
- Deduplicate repeated tool calls within one agent loop via seen-set
- Return {"error": "db_error"} from get_findings/explain_finding on DB failure instead of empty list/None so LLM can report the real state
Info fixes:
- Add rationale to nosec B608 comment in tools.py
- Add mcp/__init__.py so local mcp/ package correctly shadows installed SDK for tests
- Expand test_mcp_server.py: subscription allowlist unit tests and call_tool coverage for tenant enforcement and blocked scan
Signed-off-by: Tanvir Farhad <tanvirfarhad007@gmail.com>
Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
…rivy - Remove unused import psycopg2 from mcp/server.py (ruff F401) - Remove unused import os from tests/test_mcp_server.py (ruff F401) - Extract _mcp_mocks variable to shorten two with-patch lines (ruff E501) - Bump certifi 2026.6.17 -> 2026.10.23 (PYSEC-2026-4320, GHSA-6q48-6c7w-9gw2) - Bump multidict 6.8.0 -> 6.9.1 (PYSEC-2026-4244) Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
from tests.conftest import _TEST_JWT_SECRET triggered a second module load, producing a new random secret separate from the one the fixture injected into app.config. Read the secret directly from app.config to guarantee the same value is used for both signing and verification. Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
Use parenthesized context managers instead of backslash continuation, matching the project's ruff format style. Signed-off-by: Tanvir Farhad <tamimtarafder12@gmail.com>
parthrohit22
left a comment
There was a problem hiding this comment.
Reviewed 641b928. The overall shape is good: tenant and subscription come from the request rather than the model, scanning needs an operator role, and there’s a cap on iterations. But the tools can’t work against our database yet.
- The queries target tables and columns that don’t exist. dev has no finding_lifecycles, finding_fingerprints, scan_rule_outcomes or compliance_scores table, and no tenant_id column anywhere. #326 · feat(automation): finding…’s schema doesn’t match either. It has fl.id, ff.id and resource_id_normalized, and no fl.finding_id, fl.outcome_id, fl.tenant_id, ff.fingerprint_id, ff.resource_id, or sro.outcome_id/severity/description/remediation.
Every tool falls into its except and returns db_error or an empty result. The agent then tells the user there are no findings, a false “all clear” from a security tool.
The tests use fake connections, so they don’t catch it. Please add a Postgres-backed test.
-
scan_subscription would fail and skips scan admission. scans has no tenant_id or created_at, requires started_at, and uses lowercase 'pending'. Please go through the existing scan-creation path so the idempotency and admission checks apply.
-
The MCP server bypasses API auth and roles. It connects straight to the database with one tenant from an environment variable. Anyone with the config can queue scans and read findings, and the subscription allowlist only covers scans. Please route it through the API with a token, or state this limitation clearly and remove the tenant-isolation claim from the README.
-
The local mcp/ package shadows the mcp SDK. The sys.path/sys.modules workaround is fragile. Please rename it, e.g. openshield_mcp/.
-
Malformed model output can cause a 500:
A bare JSON string makes "answer" in parsed a substring match, and then parsed["answer"] raises.
tuple(sorted(tool_args.items())) raises on list, dict or non-dict arguments.
The unparsed and no-key return paths skip clean_text.
confidence isn’t validated against HIGH/LOW.
- Smaller items:
framework is accepted but never used.
--tenant-id is in the description but doesn’t exist.
openshield ask isn’t installed as a command. Please add it as a subcommand in OWASP/openshield#394’s openshield/cli.py.
The conftest change injects a tenant into the shared app fixture for the whole suite. Please limit it to the agent tests.
Drop the requirements* edits (OWASP/openshield#401 covers them) and fix Ruff lint, which is still red.
Summary
POST /api/agent/query- a natural-language CSPM Q&A endpoint powered by a ReAct loop over 6 tool functions (get_findings, get_compliance_posture, get_attack_paths, explain_finding, suggest_remediation, scan_subscription)openshield askCLI command for terminal-based queryingChanges by area
api/agent/agent.py- ReAct loop with guardrails (max iterations, prompt injection filter, confidence scoring)tools.py- 6 CSPM tool functions with tenant isolation; added db_conn.rollback() in all except blocksapi/routes/agent.pyapi/app.pycli/- openshield ask command with --subscription-id, --framework, --tenant-id flagsmcp_server.py- MCP server wiring all 6 tools for Claude Desktop / Copilot integrationtests/Test plan
python -m pytest tests/test_agent_tools.py tests/test_agent_loop.py tests/test_agent_route.py tests/test_cli_ask.py tests/test_mcp_server.py -q- 38 passed