@inventec/dsh-onetree-log 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,8 +27,9 @@ AMI MegaRAC OneTree 一键日志(OpenBMC dreport dump)上传与分析框架
27
27
 
28
28
  ## 安全
29
29
 
30
- - 解包三防:zip-slip(绝对路径/`..`/NUL)、符号链接与硬链接条目直接拒绝、
31
- 单文件 1GiB / 总量 2GiB / 条目 20k 上限
30
+ - 解包三防:zip-slip(绝对路径/`..`/NUL)、符号链接与硬链接条目直接拒绝
31
+ (tar 路径解析期拒绝;zip 路径经系统工具解包后置扫描,发现符号链接
32
+ 清除并整体拒绝)、单文件 1GiB / 总量 2GiB / 条目 20k 上限
32
33
  - 文件预览路径二次校验(resolveFile 拒绝逃逸)
33
34
  - 信任围栏与 dsh-obmc-web 同款:Host 须 loopback 或部署信任域、
34
35
  Sec-Fetch-Site 不得 cross-site、Origin 须同 Host 主机名
@@ -80,6 +81,18 @@ node scripts/e2e.mjs # 宿主半身端到端
80
81
  无构建步骤:`lib/` 即发布产物(与 dsh-surf / dsh-obmc-web 一致的薄插件风格)。
81
82
  宿主半身需要 Node ≥22.15(zlib 原生 zstd;旧版本自动回退系统 `zstd -dc`)。
82
83
 
84
+ ## 发版
85
+
86
+ npm 包走 GitHub Actions OIDC Trusted Publishing(无静态 token,自带 provenance):
87
+
88
+ ```bash
89
+ npm version patch # 或 minor / major:改 package.json 并打 v* tag
90
+ git push --follow-tags # Actions 自动发布到 @inventec/dsh-onetree-log
91
+ ```
92
+
93
+ 信任关系:package `@inventec/dsh-onetree-log` ↔ workflow `publish.yml` @ `iasiv5/dsh-onetree-log`,
94
+ registry 元数据里发布者显示为 GitHub Actions 即 OIDC 生效。
95
+
83
96
  ## 第二阶段扩展点(逐域解析)
84
97
 
85
98
  内核已按 section 预留挂钩,第二阶段只需:
package/lib/extract.js CHANGED
@@ -7,7 +7,8 @@
7
7
  * - `.tar.zst` / `.tzst`:Node ≥22.15 的 zlib zstd 流;无原生支持时回退系统 `zstd -dc`
8
8
  * - `.zip`:系统 `unzip`(回退 `tar`),先列目校验再解压(execFile,无 shell)
9
9
  *
10
- * 防护:zip-slip(绝对路径 / `..` / NUL)、符号链接与硬链接直接拒绝、
10
+ * 防护:zip-slip(绝对路径 / `..` / NUL)、符号链接与硬链接直接拒绝
11
+ * (tar 路径解析期拒绝;zip 路径经系统工具解包后置扫描拒绝)、
11
12
  * 单文件 1GiB / 总量 2GiB / 条目数 20k 上限,超限立即中止并抛错。
12
13
  */
13
14
  import fs from 'node:fs'
@@ -249,6 +250,43 @@ function assertSafeEntryNames(listing) {
249
250
  }
250
251
  }
251
252
 
253
+ // zip 交给系统工具解包,解包前只能拿到条目名(unzip -Z1 / tar -tf),
254
+ // 链接属性不可见。落盘后置扫描兜底(2026-09-28 审计修复):zip 内符号
255
+ // 链接条目会被系统工具落成真实符号链接,若不拒绝,previewFile 的
256
+ // statSync/readSync 会跟链读出 destDir 之外的文件——与 tar 路径
257
+ // 「链接条目直接拒绝」同语义。返回相对路径列表,非空即整体拒绝。
258
+ function scanSymlinkEntries(root) {
259
+ const found = []
260
+ const stack = [root]
261
+ while (stack.length > 0 && found.length < 16) {
262
+ const dir = stack.pop()
263
+ let entries
264
+ try {
265
+ entries = fs.readdirSync(dir, { withFileTypes: true })
266
+ } catch {
267
+ continue // 竞态/权限:读取失败的分支不再深挖
268
+ }
269
+ for (const entry of entries) {
270
+ const full = path.join(dir, entry.name)
271
+ if (entry.isSymbolicLink()) {
272
+ found.push(path.relative(root, full) || entry.name)
273
+ continue
274
+ }
275
+ if (entry.isDirectory()) stack.push(full)
276
+ }
277
+ }
278
+ return found
279
+ }
280
+
281
+ function rejectZipLinkEntries(destDir) {
282
+ const links = scanSymlinkEntries(destDir)
283
+ if (links.length === 0) return
284
+ for (const rel of links) {
285
+ try { fs.unlinkSync(path.join(destDir, rel)) } catch { /* 尽力清理,不影响拒绝语义 */ }
286
+ }
287
+ throw new Error(`检测到链接条目(符号链接),已拒绝: ${links.join(', ')}`)
288
+ }
289
+
252
290
  async function extractZip(archivePath, destDir) {
253
291
  fs.mkdirSync(destDir, { recursive: true })
254
292
  let listing
@@ -262,10 +300,12 @@ async function extractZip(archivePath, destDir) {
262
300
  }
263
301
  assertSafeEntryNames(listing)
264
302
  await execFilePromise('tar', ['-xf', archivePath, '-C', destDir])
303
+ rejectZipLinkEntries(destDir)
265
304
  return
266
305
  }
267
306
  assertSafeEntryNames(listing)
268
307
  await execFilePromise('unzip', ['-o', '-q', archivePath, '-d', destDir])
308
+ rejectZipLinkEntries(destDir)
269
309
  }
270
310
 
271
311
  // ── 入口 ─────────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inventec/dsh-onetree-log",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "AMI MegaRAC OneTree 一键日志(OpenBMC dreport dump)上传与分析框架:设置面板「OneTree 日志」上传压缩包或登记服务器本地路径,安全解包、自动探测 dump 根、文件清单分类,为第二阶段逐域解析提供内核。",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",