Skip to content

Wiki Transformation 全局 starter pack 可被任意 workspace 编辑/删除(方案 A 跨租户写删洞) #456

Description

@ncw1992120

背景

#152(Wiki Transformations starter pack 在新 workspace 不可见)已按方案 A修复并合入 dev(commit 07d6f01b):7 个 starter pack 模板 workspace_id 置 NULL(全局),查询层 listForKb/listByWorkspace/findByNameOR workspace_id IS NULL。可见性问题确实修好了(已本地复测 WikiTransformationStarterPackGlobalE2ETest 4/4 绿)。

但 方案 A 把 starter pack 变成全局共享行后,带进来一个跨 workspace 的写/删问题:被描述为"只读共享",实际代码并非只读。

问题:全局模板可被任意 workspace 编辑/删除,且影响所有 workspace

WikiTransformationController.verifyTemplateWorkspace

private void verifyTemplateWorkspace(WikiTransformationEntity t, Long workspaceId) {
    long wsId = workspaceId != null ? workspaceId : 1L;
    if (t.getWorkspaceId() != null && !t.getWorkspaceId().equals(wsId)) {
        throw new MateClawException("err.common.wrong_workspace", 403, "...");
    }
}

workspace_id IS NULL 的全局模板,t.getWorkspaceId() != null 为 false → 校验对所有 workspace 放行。而 PUT /{id}(update)与 DELETE /{id}(delete,门槛仅 @RequireWorkspaceRole("member"))都复用这同一个校验。

后果:

  1. 任意 workspace 的 member 都能编辑全局 starter pack,改动命中所有 workspace(单一共享行)。
  2. 任意 workspace 的 member 都能删除全局 starter pack,删除后对所有 workspace 消失。
  3. 删除不可恢复:V165 是一次性 Flyway 迁移,删掉不会重新播种。

即一个 workspace 的普通成员可以把开箱即用模板从全平台改坏或删除。

复现

  1. workspace B(≠1)的 member 登录
  2. DELETE /api/v1/wiki/transformations/{starterPackId}(如 1000004001),带 X-Workspace-Id: B
  3. 返回 200,模板被删
  4. 任意其它 workspace(含 workspace 1)的 Transformations 列表里该模板消失,且无法恢复

建议修复

把 null-workspace 模板视为"系统所有、对所有 workspace 只读",在写路径拒绝改动全局模板。例如在 update/delete 入口(或专门的校验里)加:

if (t.getWorkspaceId() == null) {
    throw new MateClawException("err.wiki.global_template_readonly", 403,
        "Built-in global templates are read-only");
}

verifyTemplateWorkspace 当前的"放行"语义只适合读/应用(查看、apply 全局模板对所有 workspace 合理),不适合改/删。建议读写分离:读/apply 放行 null-workspace,改/删拒绝 null-workspace。

顺带:findByName 同名碰撞(🟢 minor)

findByName 现在是 workspace_id = ? OR workspace_id IS NULL + LIMIT 1,无确定性排序。若某 workspace 自建了与 starter pack 同名的模板,可能返回全局那条(修复前确定返回本地那条)。建议排序让 workspace-local 优先于 global(如 workspace_id 非空优先)。

关联

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions