Skip to content

fix: security hardening, config defaults, and test coverage across connectors and Rust core - #2551

Draft
tusharsharma20021114-rgb wants to merge 3 commits into
Canner:mainfrom
tusharsharma20021114-rgb:complete-fix-and-new-feature-added
Draft

fix: security hardening, config defaults, and test coverage across connectors and Rust core#2551
tusharsharma20021114-rgb wants to merge 3 commits into
Canner:mainfrom
tusharsharma20021114-rgb:complete-fix-and-new-feature-added

Conversation

@tusharsharma20021114-rgb

@tusharsharma20021114-rgb tusharsharma20021114-rgb commented Jul 20, 2026

Copy link
Copy Markdown

Summary

Comprehensive security and stability hardening across the Python connector layer, Rust core (wren-core), config system, and MCP server. All changes add no new dependencies and maintain backward compatibility (deprecation warnings used where defaults changed).


1. SQL injection prevention — all 15 connectors

Every connector previously interpolated the LIMIT value directly into SQL via f-strings. This is a SQL injection vector when limit originates from user input.

Changes:

  • Added ConnectorABC._normalize_limit() — centralized limit sanitization with clamp to MAX_ROW_LIMIT, NoneMAX_ROW_LIMIT, negative → MAX_ROW_LIMIT
  • Added ConnectorABC._apply_limit_param() — wraps SQL with parameterized LIMIT (supports %s, ?, :num styles)
  • Added ConnectorABC._apply_limit_inline() — wraps SQL with inline LIMIT (for connectors that don't support parameters in subqueries)
  • All 15 connectors use parameterized LIMITs
  • DuckDB S3/Minio/GCS secrets: replaced f-string interpolation with parameterized queries, removed _escape_sql()

2. Config system hardening

strict_mode default flipped to True

  • load_config() default changed from False to True — unregistered table references are rejected by default
  • Added deprecation warning when strict_mode key is absent from config JSON
  • Dataclass default (WrenConfig()) was already strict_mode=True — only load_config() was wrong

__post_init__ normalization

  • denied_functions and allowed_source_functions lowercased in __post_init__
  • Removed redundant .lower() calls from load_config()
  • Prevents case-sensitivity bugs

Denied-function error messages

  • Error message now includes the matched denied function name

3. MCP server auth — bearer token support

  • --api-key CLI flag for bearer token auth on Streamable HTTP transport
  • _ApiKeyVerifier class in mcp_server.py
  • Connection help text shows --bearer-token usage for Claude Code and Codex

4. Engine-level SQL safety check

  • basic_safety_check(sql) added to dry_plan(), query(), and dry_run()

5. Rust clippy hardening — 33 fixes across 12 files

Configuration

  • unwrapped_used = "deny" and expect_used = "deny" in workspace and standalone crate Cargo.tomls

Fixes by file

  • mdl/mod.rs// SAFETY: comment
  • mdl/function/remote_function.rs — 4x unwrap → ? or match
  • mdl/type_planner.rs — 3x unwrap → ? or unwrap_or_default
  • mdl/context.rs — 5x unwrap → ? or unwrap_or_default
  • mdl/dataset.rs — 2x unwrap → ?
  • mdl/lineage.rs — 2x unwrap → ?
  • mdl/utils.rs — 7x unwrap → ?
  • mdl/dialect/inner_dialect.rs — 1x unwrap → ?
  • mdl/dialect/wren_dialect.rs — 1x unwrap → unwrap_or_default
  • logical_plan/unparser.rs — 2x unwrap → ?
  • logical_plan/analyze/plan.rs — 2x expect → ?
  • logical_plan/analyze/relation_chain.rs — 1x unwrap → ?
  • logical_plan/analyze/model_generation.rs — 2x unwrap → ?

6. CI safety

  • Labeler workflow SAFETY comment explaining pull_request_target usage

7. WASM ACL

  • ACL hardening in core/wren-core-wasm/src/lib.rs

8. Test coverage

New: test_connector_base.py (13 tests)

Covers _normalize_limitNone, 0, negative, overflow, float, bool, custom max.

Updated: test_mysql_helpers.py

Replaced dead tests for removed functions with _apply_limit_mysql parameterized tests.

Updated: test_config.py (3 new tests + assertion fixes)

  • __post_init__ normalization tests
  • Fixed assertions for new strict_mode=True default

Updated: conftest.py

wren_core MagicMock for environments without compiled Rust binary.


Migration notes

  • strict_mode default change: Set strict_mode: false explicitly in config JSON to keep old behavior
  • LIMIT clamp: Values > 10000 are clamped — no code change needed
  • MCP auth: --api-key is opt-in, existing setups are unaffected

Summary by CodeRabbit

  • New Features

    • Added optional API-key bearer-token authentication for MCP over HTTP, plus CLI and documentation guidance.
    • Added a basic SQL policy check to block invalid, multi-statement, and non-read-only queries.
    • Standardized row-limit handling across connectors with safer normalization and parameterized LIMIT.
    • strict_mode now defaults to enabled, with allow/deny function lists normalized to lowercase.
  • Bug Fixes

    • Clearer errors when querying before an MDL is loaded.
    • Replaced multiple panic-prone paths with returned, actionable planning/execution errors.
  • Tests / Chores

    • Updated connector/config tests and strengthened linting to disallow unwrap()/expect().

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file python Pull requests that update Python code rust Pull requests that update rust code core ci wasm labels Jul 20, 2026
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR strengthens Rust linting and error propagation, centralizes connector row-limit handling, adds SQL safety checks and configuration normalization, introduces optional MCP bearer authentication, updates the WASM MDL precondition, and documents the pull-request labeler trigger.

Changes

Rust safety and lint enforcement

Layer / File(s) Summary
Workspace lint enforcement
core/wren-core/**/Cargo.toml
Clippy now denies unwrap() and expect() usage across configured workspace crates.
Planning and runtime error paths
core/wren-core-wasm/src/lib.rs, core/wren-core/core/src/**
Unchecked assumptions in query execution, planning, MDL handling, dialect conversion, and schema construction now return explicit errors or safe fallbacks.

Connector limit handling

Layer / File(s) Summary
Shared limit utilities
core/wren/src/wren/connector/base.py, core/wren/tests/unit/test_connector_base.py
Connectors share limit normalization, maximum-row clamping, and parameterized SQL wrapping.
Connector integration
core/wren/src/wren/connector/*.py, core/wren/tests/unit/*
Connector query and dry-run paths use normalized or bound limits; DuckDB secret creation is parameterized.

SQL policy and configuration

Layer / File(s) Summary
SQL safety and configuration behavior
core/wren/src/wren/engine.py, core/wren/src/wren/policy.py, core/wren/src/wren/config.py, core/wren/tests/*
Engine entry points reject unsupported SQL statements, configuration defaults to strict mode, and function names are normalized to lowercase.

MCP bearer authentication

Layer / File(s) Summary
API key configuration and verification
core/wren/src/wren/mcp_server.py, core/wren/src/wren/serve_cli.py
HTTP MCP serving accepts an optional API key, verifies bearer tokens, and displays token-aware client registration commands.

Pull request labeler workflow

Layer / File(s) Summary
Labeler trigger safety
.github/workflows/labeler.yaml
The labeler uses a direct pull_request_target trigger and documents its permission and forked-PR constraints.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant WrenEngine
  participant basic_safety_check
  participant Connector
  participant Database
  Client->>WrenEngine: submit SQL and limit
  WrenEngine->>basic_safety_check: validate SQL policy
  basic_safety_check-->>WrenEngine: allow or raise WrenError
  WrenEngine->>Connector: execute SQL with normalized limit
  Connector->>Database: send SQL and bound parameters
  Database-->>Connector: return rows
  Connector-->>Client: return query result
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: goldmedal

Poem

I’m a rabbit guarding rows tonight,
Limits bound and SQL parsed right.
Rust won’t panic, tokens hop,
Safe little queries never stop.
MCP wears a key with pride—
Happy code on every side!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the PR’s main themes: security hardening, config defaults, and expanded testing across connectors and Rust core.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/wren/src/wren/connector/trino.py (1)

484-511: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use qmark for LIMIT parameters here and in Athena

_apply_limit_param(..., param_style="format") emits %s, but Trino only accepts ?, and PyAthena needs paramstyle="qmark" for positional parameters. Any query()/dry_run() with a limit will fail otherwise.

  • core/wren/src/wren/connector/trino.py: switch both calls to param_style="qmark".
  • core/wren/src/wren/connector/athena.py: switch to param_style="qmark" and pass paramstyle="qmark" to cursor.execute().
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren/src/wren/connector/trino.py` around lines 484 - 511, Update
core/wren/src/wren/connector/trino.py lines 484-511 in both query and dry_run to
call _apply_limit_param with param_style="qmark" instead of "format". Also
update core/wren/src/wren/connector/athena.py lines 305-318 to use
param_style="qmark" and pass paramstyle="qmark" to cursor.execute().
🧹 Nitpick comments (5)
core/wren/src/wren/serve_cli.py (1)

89-104: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Update the documentation to reflect bearer-token auth support.

As per the downstream behavior evidence, the documentation files docs/core/guides/mcp.md and docs/core/reference/cli.md explicitly state that HTTP transport "ships no bearer-token auth in this version — keep it local". Consider updating these documentation files to reflect the newly introduced --api-key support.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren/src/wren/serve_cli.py` around lines 89 - 104, Update the HTTP
transport authentication statements in the MCP guide and CLI reference to
document the newly supported --api-key bearer-token authentication, removing the
outdated claim that bearer-token auth is unavailable while preserving the
existing local/no-auth guidance where applicable.
core/wren/src/wren/engine.py (1)

115-115: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Remove redundant basic_safety_check(sql) calls. Both query and dry_run redundantly call basic_safety_check(sql) immediately before calling self.dry_plan(sql, properties). Since dry_plan already executes this safety check unconditionally, the SQL gets parsed twice per request. Remove these calls to avoid unnecessary overhead.

  • core/wren/src/wren/engine.py#L115-L115: remove basic_safety_check(sql) from query.
  • core/wren/src/wren/engine.py#L132-L132: remove basic_safety_check(sql) from dry_run.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren/src/wren/engine.py` at line 115, Remove the redundant
basic_safety_check(sql) calls from both query and dry_run in
core/wren/src/wren/engine.py (lines 115 and 132). Leave each method delegating
safety validation to self.dry_plan(sql, properties), which already performs the
check.
core/wren/src/wren/policy.py (1)

204-205: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a defensive bounds check for empty statements.

If sqlglot.parse() evaluates to an empty list, stmts[0] will raise an IndexError. Adding a quick guard prevents a potential unexpected crash.

🛡️ Proposed fix to add the bounds check
-    stmt = stmts[0]
-    if stmt is None:
+    if not stmts or stmts[0] is None:
         raise WrenError(
             ErrorCode.INVALID_SQL,
             "Could not parse SQL statement",
             phase=ErrorPhase.SQL_POLICY_CHECK,
         )
+    stmt = stmts[0]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren/src/wren/policy.py` around lines 204 - 205, Add an empty-list guard
before indexing stmts in the policy parsing flow: return the existing
no-statement result when stmts is empty, then keep the current stmt = stmts[0]
and None handling unchanged for non-empty results.
core/wren-core/core/src/mdl/utils.rs (1)

179-187: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove redundant to_string() mapping.

The BTreeSet is populated with Strings due to the mapping logic on line 182. Calling .map(|m| m.to_string()) again after into_iter() is unnecessary and triggers redundant memory allocations.

♻️ Proposed refactor
     let models = required_fields
         .iter()
         .filter_map(|c| c.relation.as_ref().map(|r| r.table().to_string()))
         .collect::<BTreeSet<_>>() // Collect into a BTreeSet to remove duplicates
         .into_iter() // Convert BTreeSet back into an iterator
-        .map(|m| m.to_string())
         .collect::<Vec<String>>();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren-core/core/src/mdl/utils.rs` around lines 179 - 187, Remove the
redundant `.map(|m| m.to_string())` from the model collection pipeline after
`BTreeSet::into_iter()`. Since `relation.table().to_string()` already produces
`String` values, collect the iterator directly into `Vec<String>` while
preserving deduplication and ordering.
core/wren-core/core/src/mdl/mod.rs (1)

477-478: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid creating a new Tokio runtime per query transformation.

Instantiating a new Tokio runtime via Runtime::new() is an expensive operation involving thread spawning and setup. If transform_sql is executed per-query, this will add measurable latency and reduce overall throughput. Consider passing a shared handle to an existing runtime or using a lazily initialized static global runtime.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren-core/core/src/mdl/mod.rs` around lines 477 - 478, Update the
query-transformation flow around transform_sql to reuse an existing Tokio
runtime or shared runtime handle instead of constructing a new Runtime per
invocation. Pass the shared runtime dependency through the relevant callers, or
lazily initialize one shared runtime if that matches the existing architecture,
while preserving the current async transformation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/wren-core/core/src/logical_plan/analyze/model_generation.rs`:
- Around line 72-75: Replace internal_err! and plan_err! with their
*_datafusion_err! variants in every listed map_err and ok_or_else closure across
model_generation.rs, plan.rs, and relation_chain.rs, preserving each existing
error message and surrounding logic so the closures return underlying DataFusion
errors rather than Result values.

In `@core/wren-core/core/src/mdl/dialect/inner_dialect.rs`:
- Around line 388-389: Cache the compiled identifier regex instead of rebuilding
it on each call to identifier_quote_style. In
core/wren-core/core/src/mdl/dialect/inner_dialect.rs:388-389 and
core/wren-core/core/src/mdl/dialect/wren_dialect.rs:46-47, define a static
OnceLock (or equivalent lazy static) and retrieve the initialized Regex through
it, preserving the existing pattern and matching behavior at both sites.

In `@core/wren-core/core/src/mdl/function/remote_function.rs`:
- Around line 42-44: Update the coercion extraction in get_signature to avoid
propagating errors with ?. Since the preceding check guarantees no Err values
remain, collect only successful entries with filter_map into the existing vector
type while preserving the current signature-building behavior.

In `@core/wren-core/core/src/mdl/mod.rs`:
- Around line 248-250: Replace plan_err! with plan_datafusion_err! in the
TableReference conversion at core/wren-core/core/src/mdl/mod.rs lines 248-250
and in the corresponding error closures at
core/wren-core/core/src/mdl/lineage.rs lines 147-152 and 181-186, plus
core/wren-core/core/src/mdl/utils.rs lines 188-193, so each ok_or_else closure
returns a DataFusionError value rather than a nested Result.

In `@core/wren/src/wren/connector/base.py`:
- Around line 43-96: Resolve the contradictory None-limit behavior by choosing
and applying one consistent contract across _normalize_limit,
_apply_limit_param, _apply_limit_inline, and connector query methods such as
MSSqlConnector and MySqlConnector. If queries must be bounded, remove None
bypasses and safely apply the configured maximum, handling existing MySQL LIMIT
clauses; otherwise make _normalize_limit return None for limit=None, update its
documentation, and have callers uniformly preserve unbounded SQL.

In `@core/wren/src/wren/connector/postgres.py`:
- Around line 272-276: Update PostgresConnector.dry_run to call
_apply_limit_param with param_style="format" so the generated placeholder
matches psycopg’s %s parameter syntax; leave the existing cursor execution flow
unchanged.

In `@core/wren/src/wren/mcp_server.py`:
- Around line 700-703: The authentication settings in the server setup use
hardcoded URLs instead of the configured bind address. Update the
ServeContext/build_server flow to carry the CLI host and port into the
AuthSettings construction, then build both issuer_url and resource_server_url
from the actual host and port while preserving existing defaults.
- Around line 683-690: Update verify_token to compare token and self._api_key
with secrets.compare_digest instead of ==, preserving the existing AccessToken
return for matches and None for non-matches; ensure the secrets module is
imported.

In `@core/wren/src/wren/serve_cli.py`:
- Around line 154-160: Update serve_mcp to reject api_key when transport is not
"http", immediately after the existing transport validation. Emit a clear error
to stderr and exit with a failure status, while preserving the existing HTTP
behavior and stdio flow when no API key is provided.

---

Outside diff comments:
In `@core/wren/src/wren/connector/trino.py`:
- Around line 484-511: Update core/wren/src/wren/connector/trino.py lines
484-511 in both query and dry_run to call _apply_limit_param with
param_style="qmark" instead of "format". Also update
core/wren/src/wren/connector/athena.py lines 305-318 to use param_style="qmark"
and pass paramstyle="qmark" to cursor.execute().

---

Nitpick comments:
In `@core/wren-core/core/src/mdl/mod.rs`:
- Around line 477-478: Update the query-transformation flow around transform_sql
to reuse an existing Tokio runtime or shared runtime handle instead of
constructing a new Runtime per invocation. Pass the shared runtime dependency
through the relevant callers, or lazily initialize one shared runtime if that
matches the existing architecture, while preserving the current async
transformation behavior.

In `@core/wren-core/core/src/mdl/utils.rs`:
- Around line 179-187: Remove the redundant `.map(|m| m.to_string())` from the
model collection pipeline after `BTreeSet::into_iter()`. Since
`relation.table().to_string()` already produces `String` values, collect the
iterator directly into `Vec<String>` while preserving deduplication and
ordering.

In `@core/wren/src/wren/engine.py`:
- Line 115: Remove the redundant basic_safety_check(sql) calls from both query
and dry_run in core/wren/src/wren/engine.py (lines 115 and 132). Leave each
method delegating safety validation to self.dry_plan(sql, properties), which
already performs the check.

In `@core/wren/src/wren/policy.py`:
- Around line 204-205: Add an empty-list guard before indexing stmts in the
policy parsing flow: return the existing no-statement result when stmts is
empty, then keep the current stmt = stmts[0] and None handling unchanged for
non-empty results.

In `@core/wren/src/wren/serve_cli.py`:
- Around line 89-104: Update the HTTP transport authentication statements in the
MCP guide and CLI reference to document the newly supported --api-key
bearer-token authentication, removing the outdated claim that bearer-token auth
is unavailable while preserving the existing local/no-auth guidance where
applicable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d548bc69-6799-4517-8cf6-529a160124bb

📥 Commits

Reviewing files that changed from the base of the PR and between 4e0c4f3 and 7902a55.

📒 Files selected for processing (44)
  • .github/workflows/labeler.yaml
  • core/wren-core-base/Cargo.toml
  • core/wren-core-wasm/src/lib.rs
  • core/wren-core/Cargo.toml
  • core/wren-core/benchmarks/Cargo.toml
  • core/wren-core/core/Cargo.toml
  • core/wren-core/core/src/logical_plan/analyze/model_generation.rs
  • core/wren-core/core/src/logical_plan/analyze/plan.rs
  • core/wren-core/core/src/logical_plan/analyze/relation_chain.rs
  • core/wren-core/core/src/logical_plan/unparser.rs
  • core/wren-core/core/src/mdl/context.rs
  • core/wren-core/core/src/mdl/dataset.rs
  • core/wren-core/core/src/mdl/dialect/inner_dialect.rs
  • core/wren-core/core/src/mdl/dialect/wren_dialect.rs
  • core/wren-core/core/src/mdl/function/remote_function.rs
  • core/wren-core/core/src/mdl/lineage.rs
  • core/wren-core/core/src/mdl/mod.rs
  • core/wren-core/core/src/mdl/type_planner.rs
  • core/wren-core/core/src/mdl/utils.rs
  • core/wren-core/sqllogictest/Cargo.toml
  • core/wren-core/wren-example/Cargo.toml
  • core/wren/src/wren/config.py
  • core/wren/src/wren/connector/athena.py
  • core/wren/src/wren/connector/base.py
  • core/wren/src/wren/connector/canner.py
  • core/wren/src/wren/connector/clickhouse.py
  • core/wren/src/wren/connector/databricks.py
  • core/wren/src/wren/connector/datafusion.py
  • core/wren/src/wren/connector/duckdb.py
  • core/wren/src/wren/connector/mssql.py
  • core/wren/src/wren/connector/mysql.py
  • core/wren/src/wren/connector/oracle.py
  • core/wren/src/wren/connector/postgres.py
  • core/wren/src/wren/connector/redshift.py
  • core/wren/src/wren/connector/snowflake.py
  • core/wren/src/wren/connector/trino.py
  • core/wren/src/wren/engine.py
  • core/wren/src/wren/mcp_server.py
  • core/wren/src/wren/policy.py
  • core/wren/src/wren/serve_cli.py
  • core/wren/tests/conftest.py
  • core/wren/tests/unit/test_config.py
  • core/wren/tests/unit/test_connector_base.py
  • core/wren/tests/unit/test_mysql_helpers.py

Comment thread core/wren-core/core/src/logical_plan/analyze/model_generation.rs
Comment thread core/wren-core/core/src/mdl/dialect/inner_dialect.rs Outdated
Comment thread core/wren-core/core/src/mdl/function/remote_function.rs Outdated
Comment thread core/wren-core/core/src/mdl/mod.rs
Comment thread core/wren/src/wren/connector/base.py Outdated
Comment thread core/wren/src/wren/connector/postgres.py
Comment thread core/wren/src/wren/mcp_server.py
Comment thread core/wren/src/wren/mcp_server.py
Comment thread core/wren/src/wren/serve_cli.py
…ck caching, Cargo.toml lints, Python parameterized limits, mcp auth hardening

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/wren/src/wren/policy.py`:
- Around line 204-210: Update the safety gate around the parsed stmt assignment
in the policy-check flow to explicitly allow only read-only statement kinds and
reject every other parsed statement before _plan runs. Preserve the existing
INVALID_SQL handling for missing or unparsable statements, and use the parser’s
statement-kind symbols rather than relying only on DDL/DML/COPY exclusions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 29a489bb-76b0-4008-bd1d-76bd7938971d

📥 Commits

Reviewing files that changed from the base of the PR and between 7902a55 and b2dee1c.

📒 Files selected for processing (29)
  • core/wren-core-base/Cargo.toml
  • core/wren-core/benchmarks/Cargo.toml
  • core/wren-core/core/Cargo.toml
  • core/wren-core/core/src/logical_plan/analyze/model_generation.rs
  • core/wren-core/core/src/logical_plan/analyze/plan.rs
  • core/wren-core/core/src/logical_plan/analyze/relation_chain.rs
  • core/wren-core/core/src/mdl/dialect/inner_dialect.rs
  • core/wren-core/core/src/mdl/dialect/wren_dialect.rs
  • core/wren-core/core/src/mdl/function/remote_function.rs
  • core/wren-core/core/src/mdl/lineage.rs
  • core/wren-core/core/src/mdl/mod.rs
  • core/wren-core/core/src/mdl/utils.rs
  • core/wren-core/sqllogictest/Cargo.toml
  • core/wren-core/wren-example/Cargo.toml
  • core/wren/src/wren/connector/athena.py
  • core/wren/src/wren/connector/base.py
  • core/wren/src/wren/connector/postgres.py
  • core/wren/src/wren/connector/trino.py
  • core/wren/src/wren/engine.py
  • core/wren/src/wren/mcp_server.py
  • core/wren/src/wren/policy.py
  • core/wren/src/wren/serve_cli.py
  • core/wren/tests/unit/test_athena_connector.py
  • core/wren/tests/unit/test_athena_limit_pushdown.py
  • core/wren/tests/unit/test_canner_semicolon.py
  • core/wren/tests/unit/test_connector_base.py
  • core/wren/tests/unit/test_duckdb_file_listing.py
  • core/wren/tests/unit/test_postgres_semicolon_unlimited.py
  • core/wren/tests/unit/test_redshift_semicolon.py
💤 Files with no reviewable changes (1)
  • core/wren/src/wren/engine.py
🚧 Files skipped from review as they are similar to previous changes (16)
  • core/wren-core/benchmarks/Cargo.toml
  • core/wren-core/core/Cargo.toml
  • core/wren-core/wren-example/Cargo.toml
  • core/wren-core-base/Cargo.toml
  • core/wren/src/wren/connector/athena.py
  • core/wren-core/sqllogictest/Cargo.toml
  • core/wren-core/core/src/logical_plan/analyze/model_generation.rs
  • core/wren-core/core/src/logical_plan/analyze/relation_chain.rs
  • core/wren/src/wren/serve_cli.py
  • core/wren-core/core/src/mdl/function/remote_function.rs
  • core/wren-core/core/src/mdl/utils.rs
  • core/wren-core/core/src/mdl/lineage.rs
  • core/wren/src/wren/mcp_server.py
  • core/wren/src/wren/connector/base.py
  • core/wren/src/wren/connector/postgres.py
  • core/wren-core/core/src/logical_plan/analyze/plan.rs

Comment thread core/wren/src/wren/policy.py
@tusharsharma20021114-rgb

Copy link
Copy Markdown
Author

what are the unresolved issues in this PR can you list them in one place what are the things that need to be fixed and how important they are.

…_safety_check, update docs for --api-key auth
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/wren/src/wren/policy.py`:
- Around line 212-215: Update the safety gate in the policy validation logic to
accept read-only query expressions by checking against exp.Query and
exp.Subquery instead of only exp.Select and exp.Explain. Preserve the existing
POLICY_VIOLATION error for non-query statements while allowing UNION, INTERSECT,
EXCEPT, and top-level parenthesized SELECT queries.

In `@docs/core/reference/cli.md`:
- Line 430: Add a --api-key row to the wren serve mcp options table, describing
that it accepts a secret and requires bearer-token authentication for HTTP
requests. Keep the existing prose and table formatting consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cd009aa3-61d0-4a67-9df6-f0ddec008dd0

📥 Commits

Reviewing files that changed from the base of the PR and between b2dee1c and c77bda3.

📒 Files selected for processing (3)
  • core/wren/src/wren/policy.py
  • docs/core/guides/mcp.md
  • docs/core/reference/cli.md

Comment on lines +212 to +215
if not isinstance(stmt, (exp.Select, exp.Explain)):
raise WrenError(
ErrorCode.POLICY_VIOLATION,
f"Only read-only queries are allowed, got: {type(stmt).__name__}",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Allow UNION, INTERSECT, and EXCEPT queries in the safety gate.

The isinstance(stmt, (exp.Select, exp.Explain)) check inadvertently blocks UNION, INTERSECT, and EXCEPT queries. In sqlglot, set operations parse as subclasses of exp.SetOperation (e.g., exp.Union), which inherits from exp.Query but not exp.Select. This will cause BI tools and dashboards that issue UNION queries to fail.

To safely allow all read-only queries, use exp.Query (which is the base class for both Select and SetOperation). Including exp.Subquery is also recommended to support top-level parenthesized queries (e.g. (SELECT 1)).

🛠️ Proposed fix to allow all read-only queries
-    if not isinstance(stmt, (exp.Select, exp.Explain)):
+    if not isinstance(stmt, (exp.Query, exp.Explain, exp.Subquery)):
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if not isinstance(stmt, (exp.Select, exp.Explain)):
raise WrenError(
ErrorCode.POLICY_VIOLATION,
f"Only read-only queries are allowed, got: {type(stmt).__name__}",
if not isinstance(stmt, (exp.Query, exp.Explain, exp.Subquery)):
raise WrenError(
ErrorCode.POLICY_VIOLATION,
f"Only read-only queries are allowed, got: {type(stmt).__name__}",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/wren/src/wren/policy.py` around lines 212 - 215, Update the safety gate
in the policy validation logic to accept read-only query expressions by checking
against exp.Query and exp.Subquery instead of only exp.Select and exp.Explain.
Preserve the existing POLICY_VIOLATION error for non-query statements while
allowing UNION, INTERSECT, EXCEPT, and top-level parenthesized SELECT queries.

For `--transport http`, connect the client to the Streamable HTTP endpoint at
`http://<host>:<port>` instead of spawning a process. Binds to `127.0.0.1` by
default; there is no bearer-token auth in this version — treat it as local-only.
default. Pass `--api-key <secret>` to enable bearer-token authentication.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add --api-key to the options table.

The prose documents the flag, but the wren serve mcp flag table still omits it. Add a row describing that it requires a bearer token for HTTP requests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/core/reference/cli.md` at line 430, Add a --api-key row to the wren
serve mcp options table, describing that it accepts a secret and requires
bearer-token authentication for HTTP requests. Keep the existing prose and table
formatting consistent.

@goldmedal

Copy link
Copy Markdown
Collaborator

@tusharsharma20021114-rgb, thanks for working on this. The PR makes sense to me. There are some conflicts and CI failure. Could you fix them?

@goldmedal
goldmedal marked this pull request as draft July 31, 2026 03:04
@goldmedal

Copy link
Copy Markdown
Collaborator

To clean my review queue, I change the PR status to draft. After addressing the CI failure, you can request me again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci core dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation python Pull requests that update Python code rust Pull requests that update rust code wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants