Skip to content

feat: add kernel plugin network timers - #18149

Closed
xyzuanli wants to merge 4 commits into
siyuan-note:devfrom
xyzuanli:codex/kernel-plugin-net-timers-dev
Closed

feat: add kernel plugin network timers#18149
xyzuanli wants to merge 4 commits into
siyuan-note:devfrom
xyzuanli:codex/kernel-plugin-net-timers-dev

Conversation

@xyzuanli

@xyzuanli xyzuanli commented Jul 8, 2026

Copy link
Copy Markdown

Description / 描述

Adds kernel plugin runtime capabilities for event-driven peer communication and safe coordination with SiYuan's built-in sync. Kernel plugins can now open guarded outbound WebSocket connections, use browser-compatible timers, and query or hold the official sync idle state before performing workspace writes.

Refs #17445
Related to #17487, #17670

Type of change / 变更类型

  • Bug fix
    缺陷修复
  • Refactoring
    代码重构
  • New feature
    新功能
  • Text updates or new language additions
    修改文案或增加新语言

Changes

  • Adds siyuan.net.ws(...) for kernel plugins, with trusted peer validation before dialing outbound WebSocket connections.
  • Adds setTimeout, clearTimeout, setInterval, and clearInterval to the kernel plugin sandbox.
  • Adds siyuan.sync.isSyncing() and siyuan.sync.tryLockIdle(ttlMs) so kernel plugins can avoid conflicting with official sync while performing workspace writes.
  • Exposes current sync activity from /api/sync/getSyncInfo as syncing for frontend/plugin coordination.
  • Refactors the existing siyuan.client.socket path into shared WebSocket helper code.
  • Adds tests for peer host normalization used by the outbound network guard.

Verification

  • cd kernel && go test -vet=off -run '^$' ./plugin ./api ./model
  • git diff --check origin/dev...origin/pr/18149
  • git merge-tree --write-tree origin/dev origin/pr/18149

Checklist / 检查清单

  • I have performed a self-review of my own code
  • I have full rights to the submitted code and agree to license it under this project's AGPL-3.0 license
  • PR is submitted to the dev branch and has no merge conflicts

@88250

88250 commented Jul 9, 2026

Copy link
Copy Markdown
Member

请举例使用场景

@xyzuanli

Copy link
Copy Markdown
Author

请举例使用场景

主要用于局域网同步,比如桌面跟docker

Copilot AI 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.

Pull request overview

This PR extends the Go kernel-side plugin runtime with (1) guarded outbound WebSocket dialing for peer-to-peer/event-driven communication, (2) browser-compatible timer APIs in the goja sandbox, and (3) sync-idle coordination primitives so plugins can avoid racing with SiYuan’s official sync while performing workspace writes.

Changes:

  • Added siyuan.net (trusted-peer outbound ws) and siyuan.sync (sync state + idle lock token) namespaces to the kernel plugin sandbox.
  • Introduced shared WebSocket client object builder and refactored siyuan.client.socket to reuse it.
  • Added setTimeout / setInterval (and clear variants) to the plugin global runtime, plus normalization tests for trusted peer hosts.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
kernel/plugin/websocket_client.go New shared builder for browser-like WebSocket JS objects used by both siyuan.client.socket and siyuan.net.ws.
kernel/plugin/timers.go Adds timer APIs to the goja plugin sandbox and ties timer lifecycle to plugin context.
kernel/plugin/sandbox.go Wires new net, sync, and timer injections into the plugin runtime bootstrap.
kernel/plugin/api_sync.go Exposes siyuan.sync.isSyncing() and siyuan.sync.tryLockIdle(ttlMs) to plugins.
kernel/plugin/api_net.go Adds siyuan.net.setTrustedPeers() and guarded outbound siyuan.net.ws().
kernel/plugin/api_net_test.go Tests peer host normalization used by the trusted-peer guard.
kernel/plugin/api_client.go Refactors siyuan.client.socket to reuse the shared WebSocket builder.
kernel/model/sync.go Adds IsSyncing() and a TTL-based TryLockSyncIdle() lock token for coordination.
kernel/api/sync.go Exposes syncing in /api/sync/getSyncInfo response for frontend/plugin coordination.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread kernel/plugin/websocket_client.go Outdated
Comment on lines +149 to +156
}, func(rt *goja.Runtime, result any, err error) {
if lo.IsNil(err) {
if opening, ok := result.(bool); !ok || !opening {
if resolveErr := openResolve(nil); resolveErr != nil {
logging.LogErrorf("[plugin:%s] ws.open resolve: %v", p.Name, resolveErr)
}
}
} else {
Comment thread kernel/plugin/websocket_client.go Outdated
Comment on lines +324 to +330
closeRunErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {
if c := gwsConn.Load(); c != nil {
setReadyState(rt, WebSocketReadyStateClosing)
err = c.WriteClose(code, reason)
}
return
}, func(rt *goja.Runtime, result any, err error) {
Comment thread kernel/plugin/timers.go Outdated
Comment on lines +156 to +159
delay := time.Duration(call.Argument(1).ToInteger()) * time.Millisecond
if delay < 0 {
delay = 0
}
Comment thread kernel/plugin/timers.go Outdated
Comment on lines +172 to +175
delay := time.Duration(call.Argument(1).ToInteger()) * time.Millisecond
if delay < 0 {
delay = 0
}
@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

审查结论 (不包含 Copilot 已报告的问题)

  • 高风险siyuan.net.setTrustedPeers() 的“白名单”完全由插件自己设置,siyuan.net.ws() 只校验这个插件自声明列表;因此任意 kernel plugin 都可以先信任任意 host:port 再发起出站 WebSocket。若目标是 SSRF/内网访问防护,这不是安全边界,且实现显式绕过 SSRFSafeDialer。建议改为 manifest/用户授权/配对流程生成的受信列表,或默认继续使用 SSRF-safe dialer。位置:kernel/plugin/api_net.go:55kernel/plugin/api_net.go:88kernel/plugin/websocket_client.go:102
  • 高风险injectTimers() 注入了 setTimeout, clearTimeout, setIntervalclearInterval,但这些定时器 API 在通过 eventloop.NewEventLoop() 创建 goja 运行时中已经注入。位置:kernel/plugin/plugin.go:190kernel/model/timers.go:65
  • 中风险tryLockIdle() 获取的同步锁没有绑定插件生命周期;插件卸载、崩溃或 runtime 停止后,锁只能等 TTL 自动释放,最长可阻塞官方同步 10 分钟。建议在 p.context.Done() 时自动 lock.Unlock(),或把插件生命周期传入 model.TryLockSyncIdle。位置:kernel/plugin/api_sync.go:48kernel/model/sync.go:180
  • 中风险:PR 描述里的验证命令 go test -vet=off -run '^$' ./plugin ./api ./model 不会运行新增的 TestNormalizePeerHost,因为 -run '^$' 匹配不到该测试。建议 PR 验证改为至少运行 go test -vet=off ./plugin -run TestNormalizePeerHost 或相关包全量测试。位置:kernel/plugin/api_net_test.go:21

已验证

  • git diff --check upstream/dev...HEAD:通过
  • cd kernel && go test -vet=off -run '^$' ./plugin ./api ./model:通过
  • cd kernel && go test -vet=off ./plugin -run TestNormalizePeerHost -count=1:通过

@Zuoqiu-Yingyi

Zuoqiu-Yingyi commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@88250
目前看需要先在本体中实现一个用户可配置的信任列表, 命中信任列表中的请求可以逃过代理的 SSRF 检查

GitHub Copilot 报告的现存问题我在 #18220 处理一下

@88250

88250 commented Jul 14, 2026

Copy link
Copy Markdown
Member

SSRF 检查已经在安全政策中放弃了 https://github.com/siyuan-note/siyuan/security/policy 所以不用考虑

@Zuoqiu-Yingyi

Zuoqiu-Yingyi commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

SSRF 检查已经在安全政策中放弃了 https://github.com/siyuan-note/siyuan/security/policy 所以不用考虑

是要移除现有的对于正向代理的 SSRF 检查吗?
还是将相关请求更改为仅日志审计而不阻止

@88250

88250 commented Jul 14, 2026

Copy link
Copy Markdown
Member

已有的不用移除,只是在安全政策中说明 ssrf 不要报告了,后续代码也不用考虑解决 ssrf。

@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

已有的不用移除,只是在安全政策中说明 ssrf 不要报告了,后续代码也不用考虑解决 ssrf。

该 PR 受现存 SSRF 策略影响引入了大量冗余代码 (新增了绕过 SSRF 策略的 API), 同时导致现有的 SSRF 策略形同虚设, 不如直接将现有策略更改为日志审计

@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

我看现在也有个安全模式, 可以在安全模式下使用 SSRF 阻止策略, 普通模式下使用日志审计策略

@TCOTC

TCOTC commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

安全模式是自动关插件,不是有个专门的模式状态

@Zuoqiu-Yingyi

Zuoqiu-Yingyi commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

安全模式是自动关插件,不是有个专门的模式状态

安全模式可以使用命令行参数 --safe-mode 启用, 虽然不会持久化, 但确实是个模式状态
安全模式启用 SSRF 阻止策略也符合预期, 毕竟正向代理 API 可能由外部调用

@TCOTC

TCOTC commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

感觉价值好像不大

@88250

88250 commented Jul 14, 2026

Copy link
Copy Markdown
Member

新增的代码不用考虑 ssrf 阻止,不然好麻烦。

@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

感觉价值好像不大

目前看没有其他比较好的方案了
维护一个全局信任列表的方案对攻击者来说也是形同虚设, 因为攻击者完全可以调用修改信任列表的 API 将攻击目标添加到名单中

@Zuoqiu-Yingyi

Zuoqiu-Yingyi commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@88250
目前有个方案

  • 默认模式下 SSRF 只审计不阻止
  • 安全模式下 SSRF 审计且阻止

如果这个方案可接受的话我在 #18220 中修改

@88250

88250 commented Jul 14, 2026

Copy link
Copy Markdown
Member

我觉得没有必要,完全放弃 SSRF 防御吧

@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

我觉得没有必要,完全放弃 SSRF 防御吧

我这个方便比直接移除 SSRF 变更与影响更小😏

@88250

88250 commented Jul 14, 2026

Copy link
Copy Markdown
Member

直接移掉吧

@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

@88250
#18220 中修复了本 PR 中 GitHub Copilot 报告的问题, 并调整了 ./kernel/util/net.goSSRFSafeDialer() 实现 (默认模式下 SSRF 只审计不阻止, 安全模式下 SSRF 审计且阻止)
若需要完成移除 SSRF, 直接删除其中的 Control 字段即可

@xyzuanli
#18220 合并后本 PR 可能需要重构

@88250

88250 commented Jul 14, 2026

Copy link
Copy Markdown
Member

#18220 已经合并

@xyzuanli

Copy link
Copy Markdown
Author

已经重构大半了,不过是在有SSRF的情况下hhh,后面我再改改

@xyzuanli
xyzuanli force-pushed the codex/kernel-plugin-net-timers-dev branch from 930277d to b732a0f Compare July 14, 2026 13:02
@TCOTC

TCOTC commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

新增两万五千行代码看起来好夸张

@xyzuanli

Copy link
Copy Markdown
Author

用ai粗暴合并了下,好多还是之前的东西

@xyzuanli
xyzuanli force-pushed the codex/kernel-plugin-net-timers-dev branch 2 times, most recently from 858d182 to 930277d Compare July 14, 2026 13:29
@Zuoqiu-Yingyi

Copy link
Copy Markdown
Contributor

用ai粗暴合并了下,好多还是之前的东西

还是重新从 dev 分支分叉再修改提交 PR 吧

@xyzuanli
xyzuanli force-pushed the codex/kernel-plugin-net-timers-dev branch from 930277d to 68b9c29 Compare July 15, 2026 07:43
@xyzuanli xyzuanli closed this Jul 16, 2026
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.

5 participants