From d046f5b9b45074a85ea0b021088a3558793ed6da Mon Sep 17 00:00:00 2001 From: MarkXian Date: Tue, 28 Jul 2026 11:24:10 +0800 Subject: [PATCH] fix(kap-server): sanitize download filenames --- .changeset/safe-download-filenames.md | 5 +++++ packages/kap-server/src/routes/fs.ts | 5 +++-- packages/kap-server/test/fs.test.ts | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .changeset/safe-download-filenames.md diff --git a/.changeset/safe-download-filenames.md b/.changeset/safe-download-filenames.md new file mode 100644 index 0000000000..6b8812bf46 --- /dev/null +++ b/.changeset/safe-download-filenames.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Sanitize filenames in session file download response headers. diff --git a/packages/kap-server/src/routes/fs.ts b/packages/kap-server/src/routes/fs.ts index 4a55cd33d4..6e99a816c7 100644 --- a/packages/kap-server/src/routes/fs.ts +++ b/packages/kap-server/src/routes/fs.ts @@ -590,8 +590,9 @@ function buildValidationEnvelope( }; } -function sanitizeFilename(rel: string): string { +export function sanitizeFilename(rel: string): string { const segs = rel.split('/'); const base = segs[segs.length - 1] ?? rel; - return base.replace(/"/g, '\\"'); + const sanitized = base.replace(/[\u0000-\u001f\u007f"\\]/g, '_'); + return sanitized.length > 0 ? sanitized : 'download'; } diff --git a/packages/kap-server/test/fs.test.ts b/packages/kap-server/test/fs.test.ts index bf1a057cb3..5c61e41bc9 100644 --- a/packages/kap-server/test/fs.test.ts +++ b/packages/kap-server/test/fs.test.ts @@ -6,6 +6,7 @@ import { IModelCatalog } from '@moonshot-ai/agent-core-v2'; import { ErrorCode } from '../src/protocol/error-codes'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { sanitizeFilename } from '../src/routes/fs'; import { type RunningServer, startServer } from '../src/start'; import { authHeaders } from './helpers/auth'; @@ -303,4 +304,8 @@ describe('server-v2 /api/v1/sessions/{sid}/fs:*', () => { } as never); expect(cached.status).toBe(304); }); + + it('sanitizeFilename strips control characters and path separators', async () => { + expect(sanitizeFilename('bad"name\\.txt')).toBe('bad_name_.txt'); + }); });