Skip to content

feat(adapters): shared allow_* sensitive driver feature gates#514

Closed
cofin wants to merge 1 commit into
mainfrom
feat/sensitive-driver-gates
Closed

feat(adapters): shared allow_* sensitive driver feature gates#514
cofin wants to merge 1 commit into
mainfrom
feat/sensitive-driver-gates

Conversation

@cofin

@cofin cofin commented Jun 10, 2026

Copy link
Copy Markdown
Member

Summary

First PR of the Adapter Feature Roadmap (sqlspec-gdtl). Establishes a single, shared opt-in convention for security-sensitive driver features. Sensitive capabilities — local file reads, code/extension loading, persisted credentials, relaxed TLS trust — are now disabled by default and require an explicit allow_* flag in connection_config; requesting one without the flag raises ImproperConfigurationError naming the exact flag.

Implements the binding worksheet adapter-feature-sensitive-driver-gates/spec.md, Tasks 1–8 (epic sqlspec-gdtl.1).

Changes

  • Shared helper (sqlspec/utils/config_tools.py): assert_sensitive_feature_enabled(feature, requested, allowed, *, flag_name, risk) + SENSITIVE_FLAG_PREFIX = "allow_". mypyc-safe (builtins only); message format "{feature} requires {flag_name}=True because {risk}." reproduces the prior asyncmy message verbatim.
  • asyncmy: existing local_infile gate refactored onto the helper (no behavior change; existing test passes unedited).
  • aiomysql: clean-break rename enable_local_infileallow_local_infile with asyncmy-style two-gate raise at config construction. No alias/shim.
  • pymysql: new allow_local_infile gate — local_infile=True without the flag now raises.
  • duckdb: CREATE PERSISTENT SECRET gated behind allow_persistent_secrets (native key, forwarded not popped); proof tests that all four sensitive flags are absent by default.
  • arrow_odbc / mssql_python: default-off proof tests for trusted_connection / trust_server_certificate (no production change — they were already emitted only when configured).
  • docs: new "Sensitive Driver Features" section in docs/usage/configuration.rst.

Validation

  • make lint — pre-commit, mypy, pyright, slotscheck all green.
  • 207 targeted unit tests pass (utils + asyncmy/aiomysql/pymysql/mysqlconnector/duckdb/arrow_odbc/mssql_python).
  • Rename completeness: grep enable_local_infile sqlspec/ docs/ returns nothing (only descriptive test-fn names remain).
  • TDD throughout: each gate test was watched failing before implementation.

Follow-ups (unblocked by this PR)

This lands the shared helper that sibling flows consume: allow_extension_loading (sqlite/aiosqlite), and allow_* cloud-billing gates (BigQuery/Spanner) — reserved here, implemented in their own flows.

Add `assert_sensitive_feature_enabled` + `SENSITIVE_FLAG_PREFIX` to
`sqlspec/utils/config_tools.py` and route every security-sensitive driver
feature through the shared `allow_*` opt-in convention.

- asyncmy: refactor existing local_infile gate onto the shared helper
- aiomysql: rename enable_local_infile -> allow_local_infile with a
  config-time raise (clean break, no alias)
- pymysql: add allow_local_infile gate (local_infile=True now requires opt-in)
- duckdb: gate CREATE PERSISTENT SECRET behind allow_persistent_secrets;
  prove the four sensitive flags are absent by default
- arrow_odbc / mssql_python: default-off proof tests for trusted_connection /
  trust_server_certificate (no production change)
- docs: Sensitive Driver Features section in docs/usage/configuration.rst

Closes sqlspec-gdtl.1 (Tasks 1-8).
@codecov-commenter

codecov-commenter commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.42%. Comparing base (5642615) to head (9542f90).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #514      +/-   ##
==========================================
- Coverage   74.44%   74.42%   -0.02%     
==========================================
  Files         439      439              
  Lines       53490    53506      +16     
  Branches     8464     8465       +1     
==========================================
+ Hits        39819    39821       +2     
- Misses      11048    11055       +7     
- Partials     2623     2630       +7     
Flag Coverage Δ
integration 58.26% <75.00%> (-0.05%) ⬇️
py3.10 61.59% <100.00%> (-9.65%) ⬇️
py3.11 71.26% <100.00%> (+0.01%) ⬆️
py3.12 61.60% <100.00%> (-9.65%) ⬇️
py3.13 71.26% <100.00%> (+<0.01%) ⬆️
py3.14 73.56% <100.00%> (+<0.01%) ⬆️
unit 61.80% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
sqlspec/adapters/aiomysql/config.py 91.32% <100.00%> (+0.15%) ⬆️
sqlspec/adapters/asyncmy/config.py 88.77% <100.00%> (-0.12%) ⬇️
sqlspec/adapters/duckdb/config.py 95.51% <100.00%> (+0.14%) ⬆️
sqlspec/adapters/pymysql/config.py 95.00% <100.00%> (+0.21%) ⬆️
sqlspec/utils/config_tools.py 93.12% <100.00%> (+0.27%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cofin

cofin commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

Reverting: default-deny gating disabled core driver features (file reads, etc.) by default, which is the wrong default. Redesign needed — gating must be operator opt-in, default permissive. Reopening Beads epic sqlspec-gdtl.1.

@cofin cofin closed this Jun 10, 2026
@cofin cofin deleted the feat/sensitive-driver-gates branch June 10, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants