语法糖 #61
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/sugar"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User description
糖糖
PR Type
Enhancement
Description
新增语法糖插件,支持命令别名存储与展开
支持模板变量渲染(位置参数与命名参数)
通过事件克隆实现命令回注执行
更新 VSCode 配置使用 Poetry 环境管理
Diagram Walkthrough
File Walkthrough
__init__.py
语法糖插件核心逻辑:CRUD 与命令回注konabot/plugins/syntactic_sugar/init.py
语法糖/糖/sugar命令,支持存入、删除、查看操作{1}位置参数和{key}命名参数_reinject_command克隆事件并回注展开后的命令,限制递归深度为 3channel_id列和唯一索引create_table.sql
语法糖表结构与唯一索引定义konabot/plugins/syntactic_sugar/sql/create_table.sql
syntactic_sugar表,包含name、content、belong_to、channel_id等字段name、channel_id、belong_to的唯一索引insert_sugar.sql
语法糖 upsert 插入语句konabot/plugins/syntactic_sugar/sql/insert_sugar.sql
INSERT ... ON CONFLICT DO UPDATE实现 upsert 语义settings.json
VSCode 默认使用 Poetry 环境管理.vscode/settings.json
python-envs.defaultEnvManager和python-envs.defaultPackageManager配置为 Poetry
PR Reviewer Guide 🔍
(Review updated until commit
9064b31fe9)Here are some key observations to aid the review process:
命令注入风险:用户可以通过
存入操作将任意命令文本存储为语法糖,之后通过_reinject_command回注执行。这意味着任何用户都可以创建一个语法糖,使其展开后触发 bot 的任意已注册命令(包括可能的管理命令)。虽然递归深度限制为3层,但这不能阻止横向的命令权限绕过。建议对可回注的命令进行白名单过滤,或校验调用者是否有权限执行展开后的目标命令。注入安全
_reinject_command将用户可控的模板渲染结果直接作为新命令回注执行。虽然有递归深度限制(3层),但恶意用户仍可通过精心构造的语法糖内容触发任意已注册命令,可能导致权限绕过或意外操作。建议增加命令白名单或对展开内容做进一步校验。逻辑缺陷
"查看"分支中,当
_find_sugar返回None时调用cmd.finish后,代码继续执行到第200行的 fallback 逻辑。虽然cmd.finish会抛异常中断流程,但"存入"、"删除"、"查看"三个分支使用的是独立的if而非elif,如果cmd.finish的行为发生变化或被捕获,会导致意外的 fall-through 执行。建议改为elif链。数据库迁移
init_db中先无条件 DROP 旧索引再 CREATE 新索引,且通过PRAGMA table_info做列迁移。这种手动迁移方式在多次启动或并发场景下较脆弱,且没有版本追踪。如果未来 schema 继续演进,建议引入简单的迁移版本管理机制。PR Code Suggestions ✨
Latest suggestions up to
8f40572Explore these optional code suggestions:
finish后缺少显式return保护
在"查看"分支中,当
content不为None时,代码会继续执行到await cmd.finish(...)并正常结束。但当content is None时,
cmd.finish虽然会抛出异常来终止流程,但从代码可读性和安全性角度看,缺少return或else会让后续的"糖展开"逻辑在finish未能正确终止时被意外执行。同样的问题也出现在最后的糖展开部分的
None检查中。建议添加显式的return以确保流程安全。konabot/plugins/syntactic_sugar/init.py [194-197]
Suggestion importance[1-10]: 4
__
Why: In nonebot,
cmd.finishraises aFinishedExceptionto terminate the handler, so thereturnis not strictly necessary. However, adding a defensivereturnimproves readability and guards against potential framework behavior changes. This is a minor defensive coding improvement, not a real bug.糖展开时缺少None防护
在糖展开逻辑中,如果
_find_sugar返回None,cmd.finish通过抛出异常来终止处理流程。但如果异常未被正确传播(例如框架行为变更),
content为None时代码会继续执行_render_template,导致对None进行正则替换而产生错误。应在cmd.finish后添加return作为防御性编程。konabot/plugins/syntactic_sugar/init.py [201-205]
Suggestion importance[1-10]: 4
__
Why: Same reasoning as suggestion 1 —
cmd.finishraises an exception in nonebot socontentbeingNonewon't actually reach_render_template. Addingreturnis a reasonable defensive measure but not fixing an actual bug. Minor improvement.模板展开存在命令注入风险
_render_template中用户可以通过模板变量{name}注入任意内容,而展开后的结果会被_reinject_command作为新命令重新注入事件处理。虽然递归深度限制为
3,但恶意用户仍可通过构造糖内容来执行非预期的命令(如删除其他糖或触发其他插件命令)。建议对渲染后的结果进行命令白名单校验,或至少在文档中明确说明此安全风险。
konabot/plugins/syntactic_sugar/init.py [82-89]
Suggestion importance[1-10]: 3
__
Why: The security concern about command injection via template rendering into
_reinject_commandis valid conceptually, but theexisting_codeandimproved_codeare identical — no actual fix is proposed. The recursion depth is already capped at 3, and the feature is inherently designed to re-inject commands. Without a concrete code change, this is more of a discussion point than an actionable suggestion.Previous suggestions
Suggestions up to commit
9064b31分支条件应互斥避免穿透
"存入"、"删除"、"查看"三个分支都使用
if而非elif,依赖cmd.finish抛异常来终止流程。如果cmd.finish在某些边界情况下未能抛出异常(例如被上层捕获),代码会穿透到下方的默认分支,导致"存入"或"删除"操作后还会尝试查找并执行语法糖。应改为
elif链以确保互斥。konabot/plugins/syntactic_sugar/init.py [190-200]
Suggestion importance[1-10]: 6
__
Why: Using
elifinstead of separateifstatements is a valid structural improvement. In nonebot,cmd.finishraisesFinishedExceptionso fall-through won't happen in normal operation, but usingelif/elsemakes the mutual exclusivity explicit and is more robust and readable. It's a good defensive coding practice but not a real bug given the framework's behavior.finish 后缺少 return 防护
在"查看"分支和默认分支中,
_find_sugar返回None后调用cmd.finish虽然会抛出异常终止流程,但类型检查器无法感知这一点,content在后续
_render_template中仍可能被推断为None。建议在cmd.finish后显式return,以确保代码健壮性,避免在cmd.finish行为变更时
content为None传入_render_template导致运行时错误。"查看"分支同理。konabot/plugins/syntactic_sugar/init.py [201-205]
Suggestion importance[1-10]: 5
__
Why: The suggestion is valid —
cmd.finishin nonebot raisesFinishedExceptionto terminate flow, so in practice the code won't fall through. However, addingreturnaftercmd.finishis a reasonable defensive practice for type safety and resilience against future framework changes. It's a minor robustness improvement, not a real bug.模板替换可能被递归注入
_render_template的模板变量由用户输入控制,恶意用户可以构造包含特殊正则字符的content,虽然当前正则本身是安全的,但更关键的问题是:用户提供的positional值如果包含{...}模式,替换结果会在同一次re.sub中被再次匹配处理,可能导致非预期的递归替换。建议对替换后的结果不再进行二次匹配,或使用迭代方式逐段构建输出。
konabot/plugins/syntactic_sugar/init.py [81-91]
Suggestion importance[1-10]: 6
__
Why: The concern about recursive substitution is technically valid —
re.subprocesses the entire string in one pass, so replacement values containing{...}patterns won't actually be re-matched within the samere.subcall. However,re.subreplaces left-to-right and doesn't re-scan replaced text, so the "recursive replacement" claim is actually incorrect for a singlere.subcall. The iterative approach is still slightly safer and more explicit, but the stated vulnerability doesn't exist in practice.Persistent review updated to latest commit
9064b31fe9