mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Two issues in the last round of commits: 1. explorer/auth.py added a new, opt-in APIKeyAuthMiddleware (EXPLORER_API_KEY) and wired it into create_app(), but in doing so removed the Depends(require_auth) dependency from every router and deleted the /ws/graph-updates handshake check entirely. The new middleware also fails OPEN (allows all requests) when its key is unset, the opposite of require_auth's fail-closed design. Since GHSA-j4mq-hprp-987v (the unauthenticated-Explorer-API advisory) is already merged into main via require_auth, this would have reverted a merged Critical fix the moment this branch merges. Removed explorer/auth.py, restored the per-router dependencies and the WebSocket auth check. Kept auth.py's one genuine improvement (adding X-API-Key to the CORS allow_headers list) by folding it into the existing CORS middleware config. 2. sparql.py's new _is_read_only_query() hardening (comment/PREFIX stripping + forbidden-keyword scan) used `#[^\n]*` to strip SPARQL comments, but a bare '#' also appears inside standard RDF namespace IRIs (e.g. ".../1999/02/22-rdf-syntax-ns#") — the regex struck everything after that '#' as a "comment", corrupting the query and rejecting any legitimate SELECT using rdf:/rdfs:-style PREFIX declarations. Confirmed by the fact the new hardening's own inlined test copy failed against two of its own cases. Fixed by only treating '#' as a comment-start at line-start or after whitespace, which distinguishes ".../ns#" (preceded by a word character) from an actual comment (preceded by whitespace/newline in every realistic case, including the attacker's own comment-hiding PoC). Also fixed the companion PREFIX/BASE regex, which required a prefix-name token between the keyword and the IRI even for bare `BASE <...>` declarations (which have none). tests/test_security_regression.py's SPARQL section now imports the real _is_read_only_query instead of maintaining a parallel inlined copy that had silently drifted from — and shared the same bug as — the real implementation; removed its TestAPIKeyAuth class (tested the now-deleted auth.py) since equivalent, more thorough coverage already exists in tests/explorer/test_explorer_auth.py. Updated tests/explorer/test_sparql_route.py's multi-statement-injection test to reflect that the keyword scan now catches "SELECT ... ; DROP ALL" itself rather than relying on rdflib's parser, and added a new test confirming the parser still catches multi-statement syntax that doesn't contain any forbidden keyword. Full explorer/vector_store/security-regression/age_store suite: 543 passed (the only failures are 6 pre-existing, unrelated Pinecone-client mocking issues).