Skip to content

Improve error handling and security for plugin data storage methods#16717

Merged
Vanessa219 merged 1 commit intosiyuan-note:devfrom
TCOTC:fix/plugin-data
Dec 29, 2025
Merged

Improve error handling and security for plugin data storage methods#16717
Vanessa219 merged 1 commit intosiyuan-note:devfrom
TCOTC:fix/plugin-data

Conversation

@TCOTC
Copy link
Copy Markdown
Contributor

@TCOTC TCOTC commented Dec 28, 2025

改进插件数据存储方法的错误处理和安全性

  • 检查 storageName 是否包含路径分隔符,防止路径注入
  • saveData 和 removeData 返回完整的 IWebSocketData 对象,包含 code、msg、data 字段,便于插件检查操作结果
  • saveData 和 removeData 在函数开始处立即修改 this.data[storageName],即使操作失败也不影响后续使用 this.data[storageName]
  • 所有方法始终 resolve

- Check if storageName contains path separators to prevent path injection
- saveData and removeData return complete IWebSocketData objects with code, msg, and data fields for result checking
- saveData and removeData immediately modify this.data[storageName] at function start, so even if the operation fails, subsequent use of this.data[storageName] is not affected
- All methods always resolve
@88250 88250 requested a review from Vanessa219 December 29, 2025 00:52
@Vanessa219 Vanessa219 merged commit c243fea into siyuan-note:dev Dec 29, 2025
1 check passed
@Vanessa219 Vanessa219 requested a review from Copilot December 29, 2025 03:01
@Vanessa219 Vanessa219 added this to the 3.5.2 milestone Dec 29, 2025
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 enhances the security and error handling of plugin data storage methods by adding path injection prevention and improving return value consistency.

Key Changes:

  • Added validation to prevent path injection attacks by checking for path separators in storageName
  • Modified saveData and removeData to return complete IWebSocketData objects with code, msg, and data fields for better error handling
  • Updated data modification timing to occur at function start regardless of operation success

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

Comment thread app/src/plugin/index.ts
} as IWebSocketData);
}

this.data[storageName] = data;
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

Setting this.data[storageName] before validating readonly/publish mode means the in-memory data is modified even when the operation will fail. This could lead to inconsistent state where plugins believe data is saved when it actually isn't persisted. Consider moving this assignment after the readonly check or inside the fetch callback on success.

Copilot uses AI. Check for mistakes.
Comment thread app/src/plugin/index.ts
} as IWebSocketData);
}

delete this.data[storageName];
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

Deleting this.data[storageName] before validating readonly/publish mode means the in-memory data is removed even when the file deletion will fail. This creates inconsistent state where the data is removed from memory but still exists on disk. Consider moving this deletion after the readonly check or inside the fetch callback on success.

Copilot uses AI. Check for mistakes.
Comment thread app/src/plugin/index.ts
this.data[storageName] = "";
}
return new Promise((resolve) => {
fetchPost("/api/file/getFile", {path: `/data/storage/petal/${this.name}/${storageName}`}, (response) => {
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

The logic for handling error codes has changed to exclude both 404 and 403, but only 403 was mentioned in the PR description. Consider adding a comment explaining why 403 errors should not update this.data[storageName], similar to the existing 404 handling.

Suggested change
fetchPost("/api/file/getFile", {path: `/data/storage/petal/${this.name}/${storageName}`}, (response) => {
fetchPost("/api/file/getFile", {path: `/data/storage/petal/${this.name}/${storageName}`}, (response) => {
// For 404 (no storage file yet) and 403 (no permission / restricted storage),
// keep the existing cached/default value instead of overwriting it with the error response.

Copilot uses AI. Check for mistakes.
Comment thread app/src/plugin/index.ts
}
fetchPost("/api/file/removeFile", {path: `/data/storage/petal/${this.name}/${storageName}`}, (response) => {
delete this.data[storageName];
if (response.code !== 0 && response.code !== 404) {
Copy link

Copilot AI Dec 29, 2025

Choose a reason for hiding this comment

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

404 errors during file removal are silently ignored without logging. While this may be intentional (file already doesn't exist), consider adding a debug-level log or comment explaining this behavior for future maintainers.

Suggested change
if (response.code !== 0 && response.code !== 404) {
if (response.code === 404) {
// File already does not exist; treat as successful removal but log at debug level for diagnostics
console.debug(`plugin ${this.name} removeData: file not found, treating as success`, response);
} else if (response.code !== 0) {

Copilot uses AI. Check for mistakes.
Vanessa219 added a commit that referenced this pull request Dec 29, 2025
@Vanessa219
Copy link
Copy Markdown
Member

有些地方有问题,重新修改了一下。

@Vanessa219 Vanessa219 self-assigned this Dec 29, 2025
Vanessa219 added a commit to siyuan-note/petal that referenced this pull request Dec 29, 2025
Vanessa219 added a commit that referenced this pull request Dec 29, 2025
Vanessa219 added a commit to siyuan-note/plugin-sample that referenced this pull request Dec 29, 2025
@TCOTC TCOTC deleted the fix/plugin-data branch December 29, 2025 06:04
@TCOTC
Copy link
Copy Markdown
Contributor Author

TCOTC commented Dec 29, 2025

@Vanessa219

“所有方法始终 resolve”是因为所有插件使用这三个方法的时候都不会考虑到要 catch Promise.reject() ,行为要跟以前保持一致。

  • loadData():必须 resolve(this.data[storageName]),写插件的时候就默认了配置文件不存在的时候返回值一定是空字符串。
  • saveData():希望能静默失效,把错误信息返回并且同时输出到控制台就够了,方便开发者调试。目前只要保存不成功,后续的代码都无法执行,我觉得为了保持兼容性,插件保存配置失败之后还是应该能继续运行。
  • removeData():我的插件目前的用法中没有会产生问题的情况,就不举例了。

我单独测试我现有的4个带配置的插件,全军覆没了,全部都不能正常启用。

在集市里装了最新的插件进行测试,控制台一片红:

video.webm

@Vanessa219
Copy link
Copy Markdown
Member

插件发我看看。我这里是可以继续运行的。

@Vanessa219
Copy link
Copy Markdown
Member

试了 syplugin-hierarchyNavigate,sy-plugin-enhance,siyuan-plugin-task-management 都是可以正常加载运行的。

QQ_1767067188754

控制台日志红色是正常的,并不影响使用,目的就是为了插件开发者看到后 catch 。

88250 added a commit that referenced this pull request Dec 30, 2025
Signed-off-by: Daniel <845765@qq.com>
@88250
Copy link
Copy Markdown
Member

88250 commented Dec 30, 2025

改回 resolve(""); 了

Vanessa219 added a commit to siyuan-note/petal that referenced this pull request Dec 30, 2025
@TCOTC
Copy link
Copy Markdown
Contributor Author

TCOTC commented Dec 30, 2025

要 resolve(this.data[storageName]),没有拿到配置数据的时候应该返回当前的配置,不要直接清空。

config;

onload() {
	const defaultConfig = {"name":"zhangsan"}
	this.config = await loadData("config") || defaultConfig;
}

onDataChanged() {
	this.config = await loadData("config"); // 这里预期是返回 this.data[storageName]
}

Vanessa219 added a commit that referenced this pull request Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants