From c736fdc93b45d5c7391c7e7d47f889e94016abdc Mon Sep 17 00:00:00 2001 From: digua Date: Tue, 26 May 2026 00:03:15 +0800 Subject: [PATCH] fix(cli): disable web self update execution --- apps/cli/src/http/auth.test.ts | 17 ----------------- apps/cli/src/http/auth.ts | 5 ----- apps/cli/src/http/routes/web/index.ts | 17 ----------------- src/services/platform/web.test.ts | 23 +++++++++++++++++++++++ src/services/platform/web.ts | 13 +++---------- 5 files changed, 26 insertions(+), 49 deletions(-) delete mode 100644 apps/cli/src/http/auth.test.ts create mode 100644 src/services/platform/web.test.ts diff --git a/apps/cli/src/http/auth.test.ts b/apps/cli/src/http/auth.test.ts deleted file mode 100644 index b743bc7e..00000000 --- a/apps/cli/src/http/auth.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { describe, it } from 'node:test' -import assert from 'node:assert/strict' -import { createServer } from './server' -import { setAuthToken } from './auth' - -describe('CLI HTTP auth hook', () => { - it('requires bearer token for the CLI self-update endpoint under /_web', async () => { - setAuthToken('clb_test_token') - const app = createServer() - app.post('/_web/system/update', async () => ({ success: true })) - - const response = await app.inject({ method: 'POST', url: '/_web/system/update' }) - await app.close() - - assert.equal(response.statusCode, 401) - }) -}) diff --git a/apps/cli/src/http/auth.ts b/apps/cli/src/http/auth.ts index a7af8de6..dec47055 100644 --- a/apps/cli/src/http/auth.ts +++ b/apps/cli/src/http/auth.ts @@ -10,7 +10,6 @@ import { unauthorized, errorResponse } from './errors' let cachedToken: string | null = null let webModeEnabled = false -const protectedWebPaths = new Set(['/_web/system/update']) /** * 设置 auth hook 使用的 token(由 server 启动时注入) @@ -37,10 +36,6 @@ function safeTokenCompare(a: string, b: string): boolean { export async function authHook(request: FastifyRequest, reply: FastifyReply): Promise { if (!cachedToken) return - if (protectedWebPaths.has(request.url.split('?')[0])) { - return requireBearerToken(request, reply) - } - // /_web/ internal API: no auth required (same-origin Web UI only) if (request.url.startsWith('/_web/')) return diff --git a/apps/cli/src/http/routes/web/index.ts b/apps/cli/src/http/routes/web/index.ts index e51328e4..c6e7b952 100644 --- a/apps/cli/src/http/routes/web/index.ts +++ b/apps/cli/src/http/routes/web/index.ts @@ -19,7 +19,6 @@ import * as os from 'os' import * as path from 'path' -import { execFile } from 'child_process' import type { FastifyInstance } from 'fastify' import type { PathProvider } from '@openchatlab/core' import type { DatabaseManager } from '@openchatlab/node-runtime' @@ -119,20 +118,4 @@ export function registerWebRoutes( } } }) - - server.post('/_web/system/update', async () => { - const packageName = 'chatlab-cli' - try { - await new Promise((resolve, reject) => { - const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm' - execFile(npmCmd, ['install', '-g', `${packageName}@latest`], { timeout: 120_000 }, (err, _stdout, stderr) => { - if (err) return reject(new Error(stderr || err.message)) - resolve() - }) - }) - return { success: true } - } catch (err) { - return { success: false, error: err instanceof Error ? err.message : String(err) } - } - }) } diff --git a/src/services/platform/web.test.ts b/src/services/platform/web.test.ts new file mode 100644 index 00000000..351d38a6 --- /dev/null +++ b/src/services/platform/web.test.ts @@ -0,0 +1,23 @@ +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' +import { WebPlatformAdapter } from './web' + +describe('WebPlatformAdapter', () => { + it('does not bootstrap self-update auth from public web config', async () => { + const originalFetch = globalThis.fetch + const requestedUrls: string[] = [] + globalThis.fetch = ((input: RequestInfo | URL) => { + requestedUrls.push(String(input)) + return Promise.resolve(new Response('{}')) + }) as typeof fetch + + try { + const result = await new WebPlatformAdapter().performUpdate() + + assert.equal(result.success, false) + assert.equal(requestedUrls.length, 0) + } finally { + globalThis.fetch = originalFetch + } + }) +}) diff --git a/src/services/platform/web.ts b/src/services/platform/web.ts index ae2b639e..a786702f 100644 --- a/src/services/platform/web.ts +++ b/src/services/platform/web.ts @@ -73,16 +73,9 @@ export class WebPlatformAdapter implements PlatformAdapter { } async performUpdate(): Promise { - try { - const configResp = await fetch('/_web/automation/config') - const config = (await configResp.json()) as { token?: string } - const headers: Record = {} - if (config.token) headers.Authorization = `Bearer ${config.token}` - - const resp = await fetch('/_web/system/update', { method: 'POST', headers }) - return await resp.json() - } catch (err) { - return { success: false, error: err instanceof Error ? err.message : String(err) } + return { + success: false, + error: 'Web update is unavailable. Run npm install -g chatlab-cli@latest in your terminal.', } }