
TREK 插件面板实操手册安全模型、安装审查与更新治理的完整闭环【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK围绕 TREK 插件管理面板你能在一台生产实例上独立跑完插件全生命周期安装一个注册表插件、走完它的审查关卡、批准一次更新、在签名密钥变更时正确重信任直到卸载并清干净数据。这篇手册按边界 → 开关 → 安装 → 审查 → 运行 → 更新 → 卸载 → 标签 → 审计的顺序推进每一步都对应服务端 插件模块 的具体实现让你在动手前先知道每个操作背后真正的安全边界在哪。先看清楚边界插件到底能碰到什么 ️插件能被信任的前提是它被关在一个 TREK 控制得住的笼子里。这个隔离模型决定了后面所有操作为什么敢做先把它立起来。每个活动插件跑在独立 OS 子进程Node--permission把读取锁在自身代码目录RPC 原始 IPC 在代码加载前被吊销未授予的调用被拒绝而不是被忽略页面组件跑在密封的浏览器 frame 里崩溃、挂起、OOM 只杀掉它自己的进程自有数据存独立 SQLite仅 TREK 可读子进程的生死与主进程彻底解耦崩溃恢复与自动停用逻辑见 plugin-supervisor.ts——这是一个插件不能拖垮 TREK这句承诺的落点。子进程与宿主之间只剩一条能力校验过的 RPC 通道原始process.send/process.on(message)在其代码执行前就被移除实现见 plugin-host-entry.ts——看这里是因为它封死了伪造宿主消息 / 窃听在途请求这两条最隐蔽的路径。插件拿不到JWT_SECRET、数据库连接或任何宿主机密这些对其进程在物理上不可达它的每一次db:read仍要按操作者的 membership 重新校验授权范围不随进程边界放大。你批准的权限清单是真实边界不是装饰。入场券管理员权限与运行时开关 整个 Admin → Plugins 面板只对管理员开放且插件运行时必须处于开启状态二者缺一不可。运行时由环境变量TREK_PLUGINS_ENABLED控制判定逻辑集中在 kill-switch.ts——取值只要不是false、0、off、no大小写不敏感就算开启且每次调用实时读取改完环境变量重启即生效。环境变量作用默认值TREK_PLUGINS_ENABLED插件系统总开关kill-switch开启TREK_PLUGINS_DEV_LINK允许从本地构建目录注册插件并热重载仅当值恰为1关闭TREK_PLUGIN_ALLOW_PRIVATE_EGRESS设为on时允许出口访问私网/内网地址关闭TREK_PLUGIN_REGISTRY_URL覆盖 Discover 页浏览的注册表索引地址TREK 官方注册表要关闭整个系统只需一行environment: - TREK_PLUGINS_ENABLEDfalse运行时关闭时面板显示Plugins are disabled提示原文为The plugin runtime is turned off (TREK_PLUGINS_ENABLED). No plugin can run until an admin enables it in the server configuration.开启时面板头部出现绿色Runtime on标识。这里必须分清开启运行时和运行某个插件前者只是让面板可用所有已安装插件都必须逐个手动激活在激活之前没有任何第三方代码执行。运行时关闭时插件仍保留在磁盘上停用、无害重新打开总开关后即可恢复。dev-link 入口还额外要求TREK_PLUGINS_DEV_LINK1否则即便运行时开启也不会出现。三条安装路径统一原则注册表、手动上传、开发链接三条路径最终都收敛到同一件事代码落地、校验、注册为 inactive激活与否是后续独立的一步。注册表安装Discover 视图切换到Discover视图每张卡片展示图标、名称、作者、描述、类型、Reviewed徽章如适用、Signed / Unsigned徽章、最新版本号与下载量。点击卡片打开预安装审查对话框下一节再点Install。版本兼容由服务端算好安装前通过assertHostCompatible/hostSatisfies校验插件声明的trek范围与当前宿主是否匹配逻辑在 host-compat.ts——所有安装入口共用这一处避免各入口各自实现 semver 逻辑而得出不同结论。当最新版要求比当前更新的 TREK 时若仍有兼容旧版按钮变为Install {version}若无任何版本兼容按钮变为Incompatible并禁用。两种情况都会在琥珀色提示条里讲清原因不会把理由藏进 tooltip。注册表浏览走的是聚合的dist/index.json而非逐个 GitHub API 调用缓存CACHE_TTL为 30 分钟且请求失败时软降级为空列表、不拖垮面板细节见 registry.service.ts——看这里能理解为什么 Rescan 按钮值得存在它既重扫磁盘本地插件又强制拉取远程注册表绕过 30 分钟缓存与 CDN 边缘缓存让刚发布的插件立即出现。刚安装的插件默认是off状态不会运行任何代码——安装流程只做下载、校验、安全解压、重校验 manifest、注册inactive。手动上传.zip入口是工具栏的Upload plugin按钮或直接拖一个.zip到面板上。服务端sideload()先解压到 staging做与注册表安装同等的硬性防护防 zip-slip/炸弹的安全解压、严格 manifest 校验、拒绝原生二进制唯一不适用的是注册表侧的 SHA-256/签名校验——因为旁路加载没有注册表条目可对照。上传上限 50 MB。该行会被标记为SideloadedUploaded manually — not from the registry, unsigned and unreviewed.用相同 id 覆盖上传时旧代码会先被强制停止并停用替换后的代码绝不可能是未经重新激活仍在运行的状态激活时仍需单独同意权限。开发链接本地构建目录Link a local plugin是一个路径输入框从本地构建目录注册插件并针对真实数据热重载。它仅限开发且仅当TREK_PLUGINS_DEV_LINK1时该入口才出现。实现上对插件代码目录创建符号链接不复制校验 manifest、拒绝原生二进制注册为 inactive再用fs.watch监听构建输出重建后防抖 400ms 自动重新 fork。该行标记为Dev-Link。它绕过了安装时的签名/完整性模型代码可在重启之间变动而无需重新同意因此被1这个显式开关单独门控。三条路径的插件都先以 inactive 落地激活时必须单独同意权限。审查关卡安装前必须读完的对话框预安装审查对话框是你安装前唯一能低成本看清单据的机会它要替你回答四个问题。它能访问什么——插件请求的权限以平实语言逐条渲染如 Read the trips…、Create and edit places…未知权限代码原样显示不请求任何权限时显示Needs no special access.它连哪些主机——manifest 声明的所有可访问主机以等宽字体 chip 展示。它要你填什么——插件将要求你或每个用户填写的设置项标注Instance-wide或Per user必要时标注Required。版本、体积、所需宿主范围、审查时间——Details一节里给出版本、体积、所需 TREK 版本范围、审查时间与总下载量。对话框底部提供Source repository、Report an issue与Homepage三个链接。这里的关键是预览数据不是插件作者自己写的介绍文字而是服务端在审查提交点拉取的实时 manifest 生成的ManifestPreview——含权限列表、出口主机列表、operatorEgress标记、设置字段key/label/inputType/scope/required、许可证、图标、所需 addon 与插件依赖来源同样是 registry.service.ts。这意味着作者改 manifest 才能改到你看到的内容而不是改一段自述文案。operatorEgress 与 Allowed hosts有一类插件会访问只有你才知道地址的服务——自托管的 Gotify、ntfy 等。它们的 manifest 预知不了主机名于是声明operatorEgress审查对话框会额外出现一个 hosts you addchip 和提示This plugin talks to a service only you can name (a self-hosted server). After installing, add the hosts it may reach under ⋯ → Allowed hosts. It can reach no others.安装完成后打开该插件行的⋯ → Allowed hosts对话框逐个添加主机。添加至少一个主机之前该行显示琥珀色的Add allowed hostchip——因为它此时一个主机都到不了不提示会像静默故障一旦有了主机chip 变蓝并显示数量。保存后会重启插件使其加载新出口白名单。运行中插件的白名单不能在原进程内热扩容源码注释在 plugin-runtime.service.ts出口守卫在子进程初始化时安装一次并拒绝二次init唯一让新列表生效的方式就是重新拉起子进程。删除某主机后插件立即失去该出口并再次重启卸载插件时这些主机一并删除防止后续复用同一 id 的插件继承前人的出口权限。主机校验与 manifest 声明出口的规则一致正则EGRESS_HOST_RE见 plugin-runtime.service.ts不允许裸*、不允许整 TLD 通配、不允许带协议前缀。未声明operatorEgress的插件永远无法被授予主机——安装时同意的范围仍是硬边界。只有管理员能添加主机普通用户即使凭据自供也不能扩大插件出口。若服务与 TREK 同机或同局域网localhost、192.168.x.x还需TREK_PLUGIN_ALLOW_PRIVATE_EGRESSon该变量放宽所有已安装插件的私网出口策略仅在信任全部插件时开启。运行态启用、级联与停用每行一个开关与Active/Off状态图标块上的彩色圆点反映运行时健康active绿、starting蓝闪、error红、inactive淡、disabled/incompatible琥珀。启用一个插件前会先按依赖图计算enableOrder先拉起所有依赖再拉起目标已停用但被依赖的插件会被自动级联启用并有 toast 告知哪些被顺带打开。启用可能被拒三种原因各有补救路径必需的 addon 未启用——toast 提示 addon 名称到 Admin → Addons 开启后重试。插件依赖缺失或版本过旧——对话框逐条列出依赖提供一键Download / Update装好最新兼容版后自动重试启用。更新拓宽了权限——弹出同意对话框见更新一节。激活被拒以结构化错误码返回便于 UI 给出对应修复ADDON_DISABLED、DEPENDENCY_MISSING、TREK_VERSION_INCOMPATIBLE/TREK_VERSION_UNKNOWN。检查顺序从最严重到最轻微——版本兼容 → 权限再同意 → 必需 addon → 插件依赖——且整个预检只读任何一项不满足都不会留下半激活状态实现见 plugin-runtime.service.ts 的assertActivatable链。两条级联语义要记牢某插件依赖的 addon 被关闭时该插件被自动停用并顺带停用所有传递依赖它的插件deactivateForDisabledAddon反过来停用一个被其他插件依赖的插件会停用所有依赖方——依赖缺失时插件无法继续运行deactivateWithDependents。每行⋯菜单提供Restart仅活动插件、View error log、Allowed hosts、Source repository与Report an issue仅注册表插件、Delete。更新与签名校验更新永不会静默扩大权限update()会把新版本声明的权限与已授予权限做差集newGrants无新增就透明重启到新代码有新增则保持 inactive 并返回差集。常规更新与权限拓宽存在新版本时行内出现Update → v{version}按钮列表上方出现{count} updates available for your plugins.提示条与Update all批量按钮。若新版本请求了尚未授予的权限TREK 会先安装新代码但保持插件关闭并显示{name} v{version} is asking for rights you havent granted yet. The new version is installed but stays off until you approve it.对话框列出Newly requested permissions与New outbound connections由你选择Approve turn on或Keep off for now批量更新多个插件时这些同意提示排队依次出现不跳过任何一个。若被同意的新版本未签名对话框会额外说明没有任何机制把该版本与其作者绑定。resolveUpdateTarget挑的是当前宿主能跑的最新版而非简单最新版——盲目取最新正是更新把好插件更新坏的常见方式新版本放弃当前宿主支持后交换成功激活门再拒绝重启结果比不更新更糟。逻辑同样在 plugin-runtime.service.ts看这里能确认拒绝更新是诚实的诚实结果而非故障。签名密钥变更唯一可覆盖场景作者签名密钥与安装时钉住的密钥不再匹配时更新被拒行内显示Update blocked — {reason}与Review链接。对话框并排展示钉住密钥指纹与当前提供密钥指纹TREK cannot tell a legitimate key rotation apart from a takeover — both look identical from here. Confirm the new key with the author through a channel you already trust before you accept it.覆盖范围被严格限定只有SIGNATURE_KEY_CHANGED才有Trust the new key update按钮。签名无效、缺失或半声明half-declared只给解释没有任何覆盖按钮服务端同样拒绝。/retrust端点强制了这一范围见 registry.service.ts 的assertRetrustable仅当钉住的密钥与注册表当前密钥不同、且调用方回显的publicKey与注册表此刻提供的一模一样时才放行——回显是为了堵住对话框渲染后注册表又换了一次钥的 TOCTOU 窗口。重信任与更新在同一次调用内原子完成要么新钥通过校验、插件落到新版本并钉住新钥要么什么都不变杜绝钉住未验证密钥的窗口。卸载与数据清理 ️⋯ → Delete弹出确认对话框Uninstall plugin?—This stops the plugin, removes its code, and deletes all of its data. This cannot be undone.uninstall()会删除进程、代码目录、plugins注册表行与设置字段deleteDatatrue时再清掉插件自身的数据目录、错误日志、实体元数据、每用户配置含加密密钥、OAuth 令牌与状态、迁移台账、能力审计日志以及待处理的 GDPR 擦除队列实现见 plugin-runtime.service.ts 的uninstall——逐项对照源码能确认没有任何一行被遗漏。停止插件进程移除代码目录删除plugins注册表行与设置字段数据目录、错误日志、实体元数据每用户配置含加密密钥、OAuth 令牌与状态迁移台账、能力审计日志、GDPR 擦除队列出口主机与定时任务无条件删除——否则复用同一 id 的插件会悄悄继承这些权限一个已不存在插件的定时回调也绝不该再触发。若选择保留数据则数据目录与待处理的用户数据擦除义务一起保留等待同 id 插件重装后继续兑现避免留了数据却丢了义务的悬空状态。信任标签保证什么、不保证什么三个标签各自只担保一件事别把它们当成对代码行为的背书。Reviewed已审查保证 TREK 维护者对每一个版本做了恶意软件扫描不保证质量、可用性也不等于无害。Reviewed means a TREK maintainer scanned this plugin for malware on each version — not for quality or whether it works. It is not a guarantee that a plugin is harmless.Signed已签名保证安装时的文件已对照作者签名密钥校验过且该密钥被钉住TOFU。校验和checksum证明文件是注册表担保的字节签名进一步证明这些字节来自作者。签名校验与 TOFU 钉钥逻辑见 verify-signature.ts看这里能分清半声明为何是硬停而非降级。Unsigned未签名The files match what the registry vouches for, but nothing ties them to the author. One guarantee fewer — not unsafe.当前注册表里多数插件未签名因此这是琥珀色提示而非警报。两个徽章都不说明代码做了什么。标签页底部有可折叠的How plugins are contained — and the limits面板完整阐述隔离模型、权限真正约束什么、TREK 不能承诺什么、最坏情况是什么。你批准的权限清单界定的是插件能触及什么不约束它在授权范围内的意图——一个被允许读行程且可连某主机的插件完全可能把数据发往那里。因此务必先读权限与出口主机再决定安装。权限语义与审计日志每条权限的授予范围都有明确边界举三个典型db:read:trips——只读且每个调用都按操作者的 membership 重新校验不能借此读到非所属行程。db:write:places——写入类叠加place_edit权限与写入审计。notify:send——收件人被强制限定为操作者本人或其所属行程插件不能把它变成群发通道。完整逐条定义见 Plugin-Permissions。审计是双向的。每个用户都能在Settings → Plugins的活动日志里查看插件以其名义执行的全部操作——读过的行程/费用、写入的地点、TREK 代发的每次出站调用——该视图不设管理员门槛管理员在Admin → Plugins看到的是按插件维度的视图。该日志基于哈希链做防篡改任何一处改写都会破坏后续链使篡改可被检测。面板上的每个端点都要求管理员账户并叠加TREK_PLUGINS_ENABLED总开关服务端所有路由挂在Controller(api/admin/plugins)并同时使用JwtAuthGuard与AdminGuardplugins.controller.ts运行时关闭时install、upload、activate、update、rescan等操作统一返回 503。延伸阅读Plugins插件系统全貌类型、隔离模型、依赖、活动日志Plugin-Permissions每条权限的确切授予范围与http:outbound细节Plugin-DevelopmentSDK 与 manifest 编写Plugin-Publishing注册表提交流程与trek-pluginCLIAdmin-Addons插件可能依赖的 addon 管理Admin-Panel-Overview管理面板总览Environment-Variables插件相关环境变量完整参考Security-Hardening安全加固建议【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考