Backstage v1.5.0-next.3 版本解读:ADR 插件 entityRef 破坏性变更与 readTree ZIP 解压安全加固
2026/9/13 17:31:52 网站建设 项目流程

Backstage v1.5.0-next.3 版本解读:ADR 插件 entityRef 破坏性变更与 readTree ZIP 解压安全加固

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

本文基于仓库中的 docs/releases/v1.5.0-next.3-changelog.md 展开,对 Backstage v1.5.0 发布前的第三个预发布版本(next.3)所包含的变更进行技术解读。文章聚焦两大核心内容:ADR(Architecture Decision Records)插件系列引入entityRef字段的破坏性变更,以及backend-commonreadTree()返回的 ZIP 归档解压路径安全加固。读完本文,你将清楚了解AdrDocument数据结构的变化与自定义AdrParser的迁移方法,理解 UrlReader 树读取接口的目录穿越防护原理,并掌握next.x预发布版本在 Backstage 发布流程中的定位。

版本概览:next.x 预发布版本在做什么

Backstage 采用「预发布版本滚动确认,最后统一发布正式版」的节奏。v1.5.0-next.3表示 v1.5.0 的第三个预发布迭代,它汇总了多个包的最新变更,供使用者提前验证;当所有变更稳定后,会以 docs/releases/v1.5.0-changelog.md 的形式发布正式版 v1.5.0。仓库的 docs/releases 目录中同时保留了每个版本的*-next.*-changelog.md与正式版 changelog,可以对照阅读,追溯某项变更从预发布到正式发布的过程。

本次v1.5.0-next.3涉及 5 个包:

版本变更级别
@backstage/plugin-adr0.2.0-next.2Minor(含 BREAKING)
@backstage/plugin-adr-backend0.2.0-next.1Minor(含 BREAKING)
@backstage/plugin-adr-common0.2.0-next.1Minor(含 BREAKING)
@backstage/backend-common0.15.0-next.2Patch(安全加固)
@backstage/create-app0.4.30-next.3Patch(版本提升)

其中,ADR 插件三个包(前端plugin-adr、后端plugin-adr-backend、共享类型plugin-adr-common)的变更属于同一项特性,而backend-common的变更是独立的目录穿越安全修复。

ADR 插件:搜索结果显示关联实体标签(chip)

变更内容

本次 ADR 插件系列(plugin-adrplugin-adr-backendplugin-adr-common)的共同变更由提交bfc7c50a09引入:

Display associated entity as a chip inAdrSearchResultListItem

即:在 ADR 搜索结果列表项组件AdrSearchResultListItem中,将与该 ADR 文档关联的 Catalog 实体以 chip(标签/胶囊)的形式展示出来。搜索用户可以在结果列表中直接看到每条 ADR 属于哪个实体(例如某个SystemComponentAPI实体),不必进入详情页即可判断相关性。

破坏性变更:AdrDocument 新增 entityRef

要实现「结果列表展示关联实体」,前提是搜索索引里的 ADR 文档数据本身携带实体引用信息。因此该变更对文档数据结构做了调整:

BREAKING:AdrDocumentnow includes aentityRefproperty, if you have a customAdrParseryou will have to supply this property in your returned documents

AdrDocument(定义在plugin-adr-common中)新增了必填属性entityRefAdrParser是 ADR 后端用来把仓库中的 ADR 原始文件解析为搜索文档的解析器;如果你使用了自定义AdrParser,则解析返回的文档对象必须补上entityRef属性,否则 TypeScript 类型检查会直接报错。

自定义 AdrParser 的迁移方式

假设此前自定义解析器的返回对象大致如下:

const doc: AdrDocument = { title: 'Use Luxon for date handling', text: '...', location: 'https://example.com/adr/0001-luxon.md', };

升级到plugin-adr-common@0.2.0之后,需要为每个返回文档补充entityRef字段,指向该 ADR 所属的 Catalog 实体:

const doc: AdrDocument = { title: 'Use Luxon for date handling', text: '...', location: 'https://example.com/adr/0001-luxon.md', entityRef: 'component:my-service', // 新增:关联的 Catalog 实体引用 };

entityRef使用 Backstage 标准的实体引用语法(如component:default/my-service或省略默认命名空间的简写形式),其格式规范可参见 docs/architecture-decisions/adr009-entity-references.md。该文档同时描述了实体引用的解析规则,与本次 ADR 文档结构变更直接相关。

对于没有自定义AdrParser的使用者,无需任何改动;官方内置解析器已经在新版本中自动填充entityRef。需要说明的是,当前仓库的plugins目录已不再包含 adr 插件源码(该插件在后续版本中被移除/归档),本文的迁移示例基于 changelog 声明的接口契约整理。

与仓库内 ADR 内容的关联

ADR(Architecture Decision Records)本身是记录架构决策的轻量级文档。本仓库就在 docs/architecture-decisions 目录下维护着一套完整的 ADR 日志(adr000起,例如adr001-add-adr-log.mdadr010-luxon-date-library.mdadr014-use-fetch.md等,索引见 docs/architecture-decisions/index.md)。ADR 插件的作用正是索引这类文档并通过 Backstage 搜索提供检索。结合 docs/releases/v1.5.0-changelog.md 可以看到,同一变更在正式版中随plugin-adr@0.2.0一起发布,前端还同步升级了core-componentsplugin-search-reactplugin-catalog-react等依赖以支持 chip 渲染。

backend-common:readTree ZIP 解压目录穿越加固

变更内容

@backstage/backend-common@0.15.0-next.2的补丁变更(提交5e4dc173f7)如下:

Added a second validation to thedir()method of ZIP archive responses returned fromreadTree()that ensures that extracted files do not fall outside the target directory.

readTree()是 Backstage UrlReader 服务(UrlReaderService)的核心方法之一,用于把远程仓库(GitHub、GitLab、Bitbucket、Gerrit 等)的目录树拉取下来,返回UrlReaderServiceReadTreeResponse。调用方可以对该响应执行三种消费方式:files()(枚举所有文件)、archive()(获取归档流)、dir()(解压到本地目录并返回目录路径)。模板脚手架(Software Templates)在fetch:templatecatalog:fetch等场景中会频繁使用readTree()

本次加固针对 ZIP 归档响应的dir()方法,在原有校验之外增加第二重校验,确保解压出的文件不会落到目标目录之外——这是典型的 ZIP 路径穿越(Zip Slip)防护。恶意构造的 ZIP 归档可以在条目文件名中包含../之类的相对路径(例如../../etc/cron.d/evil),如果解压逻辑不校验目标路径,写入文件时就会逃逸出目标目录,造成任意文件写入。

源码级原理

虽然当前仓库中backend-common已拆分重构为backend-defaults,但 ZipArchiveResponse 的实现与修复思路一脉相承。核心实现在 packages/backend-defaults/src/entrypoints/urlReader/lib/tree/ZipArchiveResponse.ts:

  • forEveryZipEntry(L117-L152)使用yauzllazyEntries模式逐个读取 ZIP 条目;
  • dir()方法(L197-L226)对每个条目计算目标路径,并统一通过resolveSafeChildPath(dir, entryPath)解析目录名与写入路径(L212、L215);
  • resolveSafeChildPath@backstage/backend-plugin-api导出(见 L28 的 import),它会在拼接路径时校验结果必须位于基目录之内,一旦发现越界立即拒绝,从根上阻断../逃逸。

也就是说,解压写入文件(fs.createWriteStream)和创建中间目录(fs.mkdirp)两条路径都经过resolveSafeChildPath约束,这正是 changelog 中所说的「第二重 validation」。对应的测试见 ZipArchiveResponse.test.ts。

另外,同一个ZipArchiveResponse在 v1.5.0 发布周期内还伴随了另一项健壮性修复(见 docs/releases/v1.5.0-changelog.md 中cfa078e255):通过先将 ZIP 流写入临时文件、再从磁盘解析的方式,规避损坏 ZIP 导致 inflater 抛错或解析器无限挂起的问题。这两项变更共同提升了readTree()在不可信输入下的安全性与稳定性。

升级影响与验证

本项变更为纯加固性质,不改变readTree()的公开接口签名,普通使用方无需修改代码。受影响的主要是两类人:

  1. 自实现 UrlReader 插件/扩展:如果你的自定义 reader 返回 ZIP 归档响应,建议同步采用「先落临时文件 + 安全路径解析」的实现模式;
  2. 安全审查人员:升级后可用包含../条目的测试 ZIP 验证dir()是否会抛错并拒绝写入(仓库测试用例即按此思路覆盖)。

其他变更:create-app 版本提升

@backstage/create-app@0.4.30-next.3仅包含Bumped create-app version,属于常规的脚手架版本对齐,无功能性变更。create-appnpx @backstage/create-app创建新 Backstage 应用的引导工具,它的版本号跟着仓库整体节奏提升,确保新应用生成时默认依赖解析到最新的稳定预发布组合。

升级建议与验证路径

如果你正在使用 ADR 插件且维护了自定义AdrParser,请在升级到plugin-adr系列0.2.0版本时优先处理entityRef必填字段;backend-common的安全加固建议尽早合入。升级后可以通过以下方式验证:

  • 运行 TypeScript 类型检查,确认所有AdrDocument构造点都已补全entityRef
  • 在 Backstage 前端执行 ADR 搜索,确认AdrSearchResultListItem正确渲染关联实体的 chip;
  • 对使用fetch:template等依赖readTree()的模板做一次冒烟测试,确认 ZIP 读取与解压行为正常。

完整的正式版变更清单可对照 docs/releases/v1.5.0-changelog.md,该文件还包含本次预发布未涉及的其他变更(如plugin-catalog的创建按钮自定义、BitbucketServerEntityProvider新插件、publish:gerrit:reviewscaffolder action 等),可作为 v1.5.0 升级评估的完整依据。

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询