Repository navigation
Conversation
- sidecar 的危险 SQL 判定从字符串前缀/" WHERE " 匹配改为词法分析:去掉注释、 字符串、引号标识符和 $$ 块;按语句逐条检查;WHERE 必须直接限定该 UPDATE/DELETE(子查询里的 WHERE 不算);识别 WITH ... DELETE 与数据修改型 CTE;DROP/TRUNCATE(含 ALTER ... DROP)需要确认;排除 FOR UPDATE、 ON DELETE CASCADE、GRANT、MySQL TRUNCATE() 等非写入用法;MySQL/MariaDB 与 PostgreSQL E'' 字符串按反斜杠转义处理,SQL Server 识别 [标识符]。 - 修复根因:执行前格式化会把 WHERE 换到新行,旧判定只认 " WHERE ",导致 生产保护连接上所有带 WHERE 的 UPDATE/DELETE 都被拒绝。 - sidecar 新增不连库的 checkWriteProtection 方法;macOS 在生产保护连接执行写入 前先问后端,需要确认时弹出原有确认框,避免批量执行到一半被拒。 - 补充 Rust 金样例测试与 Swift 预检测试。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lithe Review结论: ❓ 审查未完成 任务: 332 审查状态:已由服务器取消 可以重新评论 |
5 tasks done
Owner
Author
|
已合并到 #1470(数据库模块插件化的整体 PR),后续在那里继续推进。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
在开启了"生产保护"的数据库连接上,所有带
WHERE的 UPDATE/DELETE 都执行失败。报错是Database request failed (confirmation_required): Production protection requires explicit confirmation,界面上也不会弹出确认框。根因:
WHERE挪到新的一行(UPDATE items\nSET value = 2\nWHERE id = 1)。upper.contains(" WHERE "),只认前后带空格的WHERE,换行后的\nWHERE匹配不上,于是被当成"没有 WHERE 的 UPDATE"拒绝。同一套判定还有漏判,开头加注释(
-- x\nDELETE FROM users)、WITH … DELETE、多语句脚本都能绕过。按数据库插件化提案(#1466),危险 SQL 规则以后只保留在 Rust 后端一份,Swift 那份会删掉。所以这次的修法是让后端判断准确并成为权威,而不是去对齐 Swift 的字符串规则。
改动
1. sidecar:危险 SQL 判定改为词法分析(
rust/lithe-db-sidecar/src/main.rs)is_dangerous_sql(kind, sql)先做词法切分,跳过:--和/* */注释(支持 PostgreSQL 的嵌套块注释);$$/$tag$块($1占位符不算);[标识符]。E''字符串支持反斜杠转义,其它方言只认双写引号。为此判定需要拿到连接的kind。;拆分语句,逐条检查。RESTORE开头;DROP/TRUNCATE,包括ALTER TABLE … DROP COLUMN。但TRUNCATE(是 MySQL 的数值函数,不算;UPDATE/DELETE处于动词位置(语句开头、(之后,或WITH … )之后),而且同一层括号内没有WHERE。子查询、注释、字符串里的WHERE都不算数;数据修改型 CTE(WITH d AS (DELETE …))也会被识别。SELECT … FOR UPDATE、ON DELETE CASCADE、ON DUPLICATE KEY UPDATE、GRANT UPDATE, DELETE。ensure_write_allowed/ensure_transaction_allowed改用新判定,返回的错误码不变。checkWriteProtection方法:不连接数据库,只返回{"requiresConfirmation": bool},用的规则和execute相同。2. macOS:执行前先由后端确认
DatabaseOperations/DatabaseSidecarService新增requiresWriteConfirmation(connection:sql:),对应调用checkWriteProtection。DatabaseFeatureModel.sqlConfirmation(forSQLTab:scope:):execute报出错误,后端仍会拒绝未确认的危险 SQL。DatabaseSQLWorkspaceView.run(scope:)改为先await sqlConfirmation:confirmedRisk: true执行;execute返回confirmation_required再弹框,前面的语句已经生效,确认后整批重跑会把它们再执行一遍。3. 测试与矩阵
write_protection_classifies_dangerous_sql:危险/安全金样例,覆盖换行和 tab 前的 WHERE、注释、字符串、子查询、CTE、多语句、FOR UPDATE、ON DELETE CASCADE、$$块、嵌套注释等;write_protection_lexes_quotes_per_dialect:MySQL 反斜杠转义、PostgreSQL 标准字符串与E''、SQL Server[where];write_protection_check_matches_execute_guard_without_connecting:checkWriteProtection的行为。databaseSQLConfirmationAsksTheHelperBeforeProtectedWrites覆盖三种情况:shared/platform-feature-matrix/features/database-query-history.json:macOS 证据增加 FeatureModel、sidecar 和测试文件,验收说明补上生产保护确认行为。验证
cargo test -p lithe-db-sidecar:15 passed。clippy 对改动行无新增警告(其余警告是原有代码)。./scripts/test-macos.sh --filter 'databaseSQLConfirmation…|databaseSQLBatch…|databaseTreeRejectsLateResults…':通过。databaseTreeRenders{Dark,Light}Theme、sqlExecutionLock…、delayed…等,与本 PR 无关。delayedPageOnlyClearsItsOwnCurrentDrafts:单独运行连续 3 次全部通过,在 preview 上单独运行也通过,属于并发下的不稳定,不经过 SQL 执行路径。draftConnectionTestDoesNotSaveOrNavigate:情况相同。verify-test-stability.sh、verify-service-boundaries.sh、verify-runtime-bundle-immutability.sh(test-macos 内执行)、verify-platform-feature-matrix.sh、verify-platform-feature-matrix-change.sh origin/preview HEAD、generate-platform-feature-matrix.mjs --check:全部通过。未包含
rust/lithe-db-mcp的classify_sql仍是第三份规则。它按空白切词,换行的 WHERE 已能识别,但注释、CTE 这些情况还没覆盖。按 docs(notes): 提议把数据库拆成双端共用的独立插件 #1466 的计划,迁入数据库插件时会和 sidecar 合并成一份,本 PR 不动。🤖 Generated with Claude Code