Default SESSION_DIGEST_METHOD from hashlib.sha1 to hashlib.sha256.
HMAC-SHA1 is still cryptographically acceptable for the cookie's
(sid, randval) signature, but SHA-256 is the modern default and aligns
with the file-HMAC header introduced earlier in this branch. The session
file format already invalidates all existing sessions on upgrade (the
new HMAC header is required), so flipping this default at the same time
is a free hardening rather than an additional break.
Test polish from the post-merge hostile review:
* Tighten the "no unsafe deserializer imported" assertion in the four
cloud-module test files (RDS, Google, BigAnimal, Azure) to a regex
anchored at line start with a word boundary, so it catches
`from pickle import dumps, loads`, `import pickle as p`, and indented
imports — not just bare `import pickle`.
* test_login.py: drop a sid-rotation assertion that would have given
false confidence. Flask-Paranoid does NOT rotate the session id on
login (it binds a `_paranoid_token` to UA+IP and validates per
request), so an `assertNotEqual(pre_sid, post_sid)` would always fail
for the wrong reason. Comment the limitation in the test for the next
reviewer; stronger fixation testing is owed as a follow-up.
* docs/proposals: spec line numbers in §4.2 had drifted ~10 lines from
the implemented branch (helper extraction, etc.); refresh them and
the audit-summary table to point at HEAD-of-branch lines. Append a
§1.6 entry enumerating the residual `pickle.loads` callsites in
sqleditor / schema_diff / bgprocess that PR 7 / Phase 2 will close,
so future reviewers see the surface.
CWE-502 in FileBackedSessionManager.get(): pickle.load was called on
the session file before the HMAC integrity check. Any file dropped
in the sessions directory was deserialized unconditionally, allowing
an authenticated user with sessions-dir write access to achieve
OS-level RCE.
Fix: prepend a 64-byte hex SHA-256 HMAC header over the pickle body,
computed with the SECRET_KEY, and verify it via hmac.compare_digest
before any deserialization. Also raises (not asserts) on empty
SECRET_KEY so -O does not strip the check, and narrows the
post-deserialize except clause to surface programming errors instead
of masking them.
Tests: 13 new session-format tests covering round-trip, malicious-
pickle rejection, header tampering, empty/truncated files,
cookie-HMAC mismatch, unsafe sids, empty SECRET_KEY, MFA-shaped data,
and SERVER_MODE=False direct upload.
Includes docs/proposals/2026-04-30-eliminate-rce-and-symlink-escape.md,
the shared design doc covering this fix and the symlink-traversal fix
in the following commit.
Reported-by: Fernando Bortotti <fernando.bortotti@bsd.com.br>
* Address CodeRabbit review feedback for streaming and SQL extraction.
- Anthropic: preserve separators between text blocks in streaming to
match _parse_response() behavior.
- Docker: validate that the API URL points to a loopback address to
constrain the request surface.
- Docker/OpenAI: raise LLMClientError on empty streams instead of
yielding blank LLMResponse objects, matching non-streaming behavior.
- SQL extraction: strip trailing semicolons before joining blocks to
avoid double semicolons in output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Address remaining CodeRabbit review feedback for streaming and rendering.
- Use distinct 3-tuple ('complete', text, messages) for completion events
to avoid ambiguity with ('tool_use', [...]) 2-tuples in chat streaming.
- Pass conversation history from request into chat_with_database_stream()
so follow-up NLQ turns retain context.
- Add re.IGNORECASE to SQL fence regex for case-insensitive matching.
- Render MarkdownContent as block element instead of span to avoid
invalid DOM when response contains paragraphs, lists, or tables.
- Keep stop notice as a separate message instead of appending to partial
markdown, preventing it from being swallowed by open code fences.
- Snapshot streamingIdRef before setMessages in error handler to avoid
race condition where ref is cleared before React executes the updater.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Address CodeRabbit review feedback for streaming providers and history.
- Fix critical NameError: use self._api_url instead of undefined API_URL
in anthropic and openai streaming _process_stream() methods.
- Match sync path auth handling: conditionally set API key headers in
streaming paths for both anthropic and openai providers.
- Remove unconditional temperature from openai streaming payload to
match sync path compatibility approach.
- Add URL scheme validation to OllamaClient.__init__ to prevent unsafe
local/resource access via non-http schemes.
- Guard ollama streaming finalizer: raise error when stream drops
without a done frame and no content was received.
- Update chat.py type hint and docstring for 3-tuple completion event.
- Serialize and return filtered conversation history in the complete
SSE event so the client can round-trip it on follow-up turns.
- Store and send conversation history from NLQChatPanel, clear on
conversation reset.
- Fix JSON-fallback SQL render path: clear content when SQL was
extracted without fenced blocks so ChatMessage uses sql-only renderer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix missing closing brace in NLQChatPanel switch statement.
Adding block scoping to the error case introduced an unmatched brace
that prevented the switch statement from closing properly, causing
an eslint parse error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix missing compaction module and SQL extraction test.
- Replace compaction module imports with inline history deserialization
and filtering since compaction.py is on a different branch.
- Add rstrip(';') to SQL extraction test to match production code,
fixing double-semicolon assertion failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix SQL extraction test expected values after rstrip(';') change.
The rstrip(';') applied to each block before joining means single
blocks and the last block in multi-block joins no longer have
trailing semicolons. Update expected values to match.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Strictly guard Ollama stream: raise if no terminal done frame received.
Truncated content from a dropped connection should not be treated as
a complete response, even if partial text was streamed. Always raise
when final_data is None, matching CodeRabbit's recommendation.
* Address CodeRabbit review feedback for chat context and compaction.
- Track tool-use turns as groups instead of one-to-one pairs, so
multi-tool assistant messages don't leave orphaned results.
- Add fallback to shrink the recent window when protected messages
alone exceed the token budget, preventing compaction no-ops.
- Fix low-value test fixtures to keep transient messages short so
they actually classify as low-importance.
- Guard Clear button against in-flight stream race conditions by
adding a clearedRef flag and cancelling active streams.
- Assert that conversation history is actually passed through to
chat_with_database in the "With History" test.
* Address remaining CodeRabbit review feedback for compaction module.
- Expand protected set to cover full tool groups, preventing orphaned
tool call/result messages when a turn straddles the recent window.
- Add input validation in deserialize_history() for non-list/non-dict data.
- Strengthen test assertion for preserved recent window tail.
* Fix CI test failures in compaction and NLQ chat tests.
- Lower max_tokens budget in test_drops_low_value to reliably force
compaction (500 was borderline, use 200).
- Consume SSE response data before asserting mock calls in NLQ chat
test, since Flask's streaming generator only executes on iteration.
* Clarify mock patch target in NLQ chat test.
Add comment explaining why we patch the source module rather than the
use site: the endpoint uses a local import inside the function body,
so there is no module-level binding to patch.
* Don't let auto-selection override an explicit default_provider choice.
If the same save payload includes a default_provider update (including
setting it to empty/disabled), skip the auto-selection logic so the
user's explicit choice is respected.
The previous messages like "Vacuuming the catalog..." and "Analyzing
table statistics..." could be mistaken for actual database operations.
Replace them with clearly whimsical elephant-themed messages, expand
the pool to 32 messages, and consolidate them into a single shared
module with gettext() support.
Removed the temperature parameter from all LLM provider clients and
pipeline calls, allowing each model to use its default. This fixes
compatibility with GPT-5-mini/nano and future models that don't
support user-configurable temperature.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Fix NLQ system prompt to work with models that prioritize text instructions over tool calls.
The previous prompt told the model to "Return ONLY the JSON object, nothing else"
while also providing tool definitions. Models like Qwen 3.5 would follow the text
instruction and never use tools. The updated prompt clearly separates the tool-use
phase from the final JSON response phase, and explicitly instructs the model to
call tools directly rather than describing them in text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Update release notes for NLQ prompt fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix issue number in release notes for NLQ prompt fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add configurable API URL fields for OpenAI and Anthropic providers
- Make API keys optional when using custom URLs (for local providers)
- Auto-clear model dropdown when provider settings change
- Refresh button uses current unsaved form values
- Update documentation and release notes
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Core infrastructure for LLM integration.
* Add support for a number of different AI generated reports on security, performance, and schema design on servers, databases, and schemas, as appropriate.
* Add a Natural Language AI assistant to the Query Tool.
* Add an AI Insights panel to the EXPLAIN tool in the Query Tool, to analyse and report on issues in query plans.
Change logging level from exception to error for OIDC profile data issues.
Refactor debug logging in OAuth2 authentication to improve clarity and consistency
Add error handling for missing OAuth2 provider and enhance claims processing logic
Enhance OIDC ID token handling by implementing JWT parsing and updating tests to mock claims extraction
Refactor ID token claims extraction for OIDC providers and update tests to mock userinfo handling
Refactor OAuth2 configuration to use get method for optional URLs
Enhance OAuth2 documentation and implement PKCE support for public clients in authentication logic
Fix typo in OAUTH2 authentication documentation
Implement Azure Entra ID Workload Identity authentication support and add corresponding tests
Co-authored-by: Paul Bourhis <paul.bourhis@bhs-consulting.com>