dsh-db-tool 1.8.3 → 1.8.5

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.
@@ -5,7 +5,9 @@
5
5
  * 调用 handleDbToolRequest——前端同源相对路径 fetch 即可达。
6
6
  *
7
7
  * trust 校验(等价移植 dsh-ssh-tunnel lib/shared/http-trust.js,自包含):
8
- * - Host 必须是 loopback(或 ctx.webRuntime.trustedHosts 中的条目);
8
+ * - Host 必须是 loopback(或受信条目):0.2.1-rc.3 起来自 ctx.webStartup.trustedHosts
9
+ * 加监听 bind 地址(Connection 的 isBindAddressAuthority 语义),旧宿主来自已删除的
10
+ * ctx.webRuntime.trustedHosts;
9
11
  * - 带 Origin/Referer 时其 host 必须是 loopback(且同端口)或受信条目。
10
12
  * - 0.0.0.0 不是 loopback。违者 403 FORBIDDEN。
11
13
  *
package/dist/index.js CHANGED
@@ -10,11 +10,21 @@
10
10
  * http-trust 本地校验(Host loopback / trustedHosts + Origin 同源校验)。
11
11
  * - ctx.effect 收尾:注销 HTTP 路由、关适配器、停 challenge 清理。
12
12
  */
13
+ import { isIP } from 'node:net';
13
14
  import { DbToolStore, normalizeProjectKey } from './store/index.js';
14
15
  import { DbToolService, handleToolAction } from './manager.js';
15
16
  import { handleDbToolRequest } from './http/index.js';
16
- /** cordis 注入清单(服务名以 dsh-ssh-tunnel 为准;connection 用于宿主鉴权栅栏) */
17
- export const inject = ['webServer', 'sessions', 'tools', 'webRuntime', 'connection'];
17
+ /**
18
+ * cordis 注入清单(服务名以 dsh-ssh-tunnel 为准;connection 用于宿主鉴权栅栏)。
19
+ *
20
+ * 注意:不要把 webRuntime 写进来。宿主 @deepseek-ai/dsh-web-app 提供的是
21
+ * webApp,从不注册 webRuntime;cordis 的 inject 是硬依赖,缺失服务会让 fiber
22
+ * 永久 pending、apply() 不执行,HTTP 路由也就不会注册(前端表现为 HTTP 404)。
23
+ * trustedHosts 改用 ctx.get('webStartup' | 'webRuntime', true) 可选读取:
24
+ * 0.2.1-rc.3 删除了 webRuntime 服务、信任权威改为 webStartup.trustedHosts,
25
+ * 旧宿主仍用 webRuntime,故按新优先、旧回退读取。
26
+ */
27
+ export const inject = ['webServer', 'sessions', 'tools', 'connection'];
18
28
  const TOOL_DESCRIPTION = `数据库管理工具(dsh-db-tool):在已配置的数据库连接上执行查询/写操作/脚本。
19
29
 
20
30
  权限模型(务必遵守):
@@ -40,9 +50,37 @@ export function apply(ctx) {
40
50
  const store = new DbToolStore();
41
51
  const service = new DbToolService(store);
42
52
  // HTTP API:挂在 DSH webServer 的 /dsh-db-tool/api 前缀下(同源访问)
53
+ /**
54
+ * rc.3 的 Connection 在 trustedHosts 之外还单独接受监听 bind 地址
55
+ * (isBindAddressAuthority)。本地兜底对齐该语义,但只补具体单播字面量:
56
+ * wildcard(0.0.0.0/::/*)与 loopback 一律跳过,不放宽 DNS rebinding 攻击面。
57
+ */
58
+ const bindAuthorities = () => {
59
+ const host = ctx.webServer?.host;
60
+ if (typeof host !== 'string')
61
+ return [];
62
+ const h = host.trim();
63
+ if (h === '' || h === '*' || h === '0.0.0.0' || h === '::')
64
+ return [];
65
+ if (isIP(h) === 0)
66
+ return [];
67
+ if (h === '::1' || h === '::ffff:127.0.0.1' || /^127\./.test(h))
68
+ return [];
69
+ const port = ctx.webServer?.port;
70
+ if (typeof port !== 'number' || !(port > 0))
71
+ return [h];
72
+ return [h, `${h.includes(':') ? `[${h}]` : h}:${port}`];
73
+ };
43
74
  const trustedHosts = () => {
44
75
  try {
45
- return ctx.webRuntime?.trustedHosts ?? [];
76
+ // webRuntime 不在 inject 内:缺失服务会让插件永不激活,故可选读取。
77
+ // 0.2.1-rc.3 删除了 webRuntime,改由 webStartup.trustedHosts 提供信任权威。
78
+ const startup = ctx.get?.('webStartup', true);
79
+ const declared = startup?.trustedHosts ??
80
+ ctx.get?.('webRuntime', true)?.trustedHosts ??
81
+ [];
82
+ // 仅 rc.3(webStartup 存在)补 bind 地址;旧宿主的 webRuntime 已含 bind 派生的 LAN 地址。
83
+ return startup === undefined ? declared : [...bindAuthorities(), ...declared];
46
84
  }
47
85
  catch {
48
86
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-db-tool",
3
- "version": "1.8.3",
3
+ "version": "1.8.5",
4
4
  "description": "DSH community plugin: chat-operated multi-database admin tool with sidebar management, project-scoped grants, ro/rw modes and dangerous-operation confirmation",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,7 +14,7 @@
14
14
  "homepage": "https://github.com/mengqi1436/dsh-db-tool#readme",
15
15
  "engines": {
16
16
  "node": ">=20",
17
- "dsh": ">=0.1.0-rc.6 <0.2.0-0 || 0.1.7-rc.2 || >=0.2.0-rc.1 <0.3.0-0"
17
+ "dsh": ">=0.1.0-rc.6 <0.2.0-0 || 0.1.7-rc.2 || >=0.2.0-rc.1 <0.3.0-0 || >=0.2.1-rc.2 <0.3.0-0"
18
18
  },
19
19
  "main": "dist/index.js",
20
20
  "exports": {
@@ -0,0 +1,44 @@
1
+ # DSH dsh-app-boot resolve.paths hotfix (upstream bug: createRequire(parent).resolve.paths(name)
2
+ # returns null for core-module names like "punycode", breaking hoisted profile installs).
3
+ # Covers BOTH unguarded for..of sites in 0.2.1-rc.3 lib/index.js (extracted from the
4
+ # shipped asar; CR=0, 4566 lines):
5
+ # nativePackageDir() for-line at 1371 -> hunk @@ -1368,7 +1368,10 @@
6
+ # routeScoped() for-line at 1628 -> hunk @@ -1625,7 +1628,14 @@
7
+ # Anchor lines are byte-identical to the 0.2.0-rc.2 patch (whole-file line shift only);
8
+ # hunk bodies are shared verbatim with 0.2.0-rc.1/rc.2.
9
+ # Target-Version: 0.2.1-rc.3
10
+ # Apply manually: git apply -p1 -d <dsh-app-boot package root> <this file>
11
+ # Or one command: npm run patch:dsh (scripts/apply-dsh-hotfix.ps1)
12
+ # Generated from @deepseek-ai/dsh-app-boot@0.2.1-rc.3 (asar) vs patched local copy.
13
+ diff --git a/lib/index.js b/lib/index.js
14
+ index 39401ea..8c053c3 100644
15
+ --- a/lib/index.js
16
+ +++ b/lib/index.js
17
+ @@ -1368,7 +1368,10 @@ function profileChild(path, treePrefix) {
18
+ return treePrefix + (end < 0 ? rest : rest.slice(0, end));
19
+ }
20
+ function nativePackageDir(parent, name) {
21
+ - for (const searchPath of createRequire(parent).resolve.paths(name)) {
22
+ + /* local hotfix: nativePackageDir: resolve.paths returns null for core-module names
23
+ + (fs, node:fs, ...); an empty list means no local candidate, matching the
24
+ + guard in profile.ts:596. */
25
+ + for (const searchPath of createRequire(parent).resolve.paths(name) ?? []) {
26
+ const candidate = join(searchPath, name);
27
+ if (existsSync(join(candidate, "package.json"))) return candidate;
28
+ }
29
+ @@ -1625,7 +1628,14 @@ var ResolutionRouter = class {
30
+ const target = resolution.entries.get(name);
31
+ const candidates = [];
32
+ const localSearchPaths = [];
33
+ - for (const searchPath of createRequire(parent).resolve.paths(name)) {
34
+ + /* local hotfix: resolve.paths returns null for core-module names (e.g. "punycode"),
35
+ + which made the for..of throw TypeError and broke every hoisted profile install
36
+ + whose dependency tree requires such an npm package. Fall back to the standard
37
+ + node_modules search chain so the local candidate can still be found. */
38
+ + const _hotReq = createRequire(parent);
39
+ + const _hotPaths = _hotReq.resolve.paths(name)
40
+ + ?? _hotReq("node:module")._nodeModulePaths(_hotReq("node:path").dirname(parent));
41
+ + for (const searchPath of _hotPaths) {
42
+ if (!searchPath.startsWith(layer.localPrefix)) break;
43
+ localSearchPaths.push(searchPath);
44
+ const candidate = localPackageCandidate(searchPath, name, flavor);
@@ -23,13 +23,15 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
23
23
 
24
24
  /** 补丁文件里的目标版本声明行(patches/*.patch 注释头)。 */
25
25
  export const TARGET_VERSION = '0.1.7-rc.2';
26
- /** 锚点行逐字节一致的受支持版本列表(仅整体行号偏移;0.2.0-rc.1/0.2.0-rc.2 的 lib/index.js 逐字节相同)。 */
27
- export const TARGET_VERSIONS = ['0.1.7-rc.2', '0.2.0-rc.1', '0.2.0-rc.2'];
26
+ /** 锚点行逐字节一致的受支持版本列表(仅整体行号偏移;0.2.0-rc.1/0.2.0-rc.2 的 lib/index.js 逐字节相同;
27
+ * 0.2.1-rc.3 锚点内容同样逐字节一致,仅整体行号偏移(npd +123 / routeScoped +205)。 */
28
+ export const TARGET_VERSIONS = ['0.1.7-rc.2', '0.2.0-rc.1', '0.2.0-rc.2', '0.2.1-rc.3'];
28
29
  /** 各受支持版本对应的默认补丁文件名(patches/ 下;git-apply 路径按版本选择)。 */
29
30
  export const PATCH_BY_VERSION = {
30
31
  '0.1.7-rc.2': 'dsh-app-boot-route-scoped-hotfix.patch',
31
32
  '0.2.0-rc.1': 'dsh-app-boot-route-scoped-hotfix-0.2.0-rc.1.patch',
32
33
  '0.2.0-rc.2': 'dsh-app-boot-route-scoped-hotfix-0.2.0-rc.2.patch',
34
+ '0.2.1-rc.3': 'dsh-app-boot-route-scoped-hotfix-0.2.1-rc.3.patch',
33
35
  };
34
36
  /** 判断目标文件是否已打补丁的标识串(hotfix 注释首行片段)。 */
35
37
  export const HOTFIX_MARKER = 'local hotfix: resolve.paths returns null';