|
1 | 1 | import { afterEach, beforeEach, describe, expect, it } from "bun:test"; |
2 | 2 | import { mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs"; |
3 | 3 | import { join } from "node:path"; |
4 | | -import { validatePromptFilePath, validatePromptFileStats } from "../security.js"; |
| 4 | +import { stripControlChars, validatePromptFilePath, validatePromptFileStats } from "../security.js"; |
5 | 5 |
|
6 | 6 | describe("validatePromptFilePath", () => { |
7 | 7 | it("should accept normal text file paths", () => { |
@@ -158,6 +158,45 @@ describe("validatePromptFilePath", () => { |
158 | 158 | expect(() => validatePromptFilePath(symlink)).not.toThrow(); |
159 | 159 | }); |
160 | 160 | }); |
| 161 | + |
| 162 | + it("should reject paths containing ANSI escape sequences", () => { |
| 163 | + expect(() => validatePromptFilePath("\x1b[2J\x1b[Hfake.txt")).toThrow("control characters"); |
| 164 | + expect(() => validatePromptFilePath("file\x1b[31mred.txt")).toThrow("control characters"); |
| 165 | + }); |
| 166 | + |
| 167 | + it("should reject paths containing null bytes", () => { |
| 168 | + expect(() => validatePromptFilePath("file\x00.txt")).toThrow("control characters"); |
| 169 | + }); |
| 170 | + |
| 171 | + it("should reject paths containing other control characters", () => { |
| 172 | + expect(() => validatePromptFilePath("file\x07bell.txt")).toThrow("control characters"); |
| 173 | + expect(() => validatePromptFilePath("file\x08backspace.txt")).toThrow("control characters"); |
| 174 | + expect(() => validatePromptFilePath("file\x7Fdel.txt")).toThrow("control characters"); |
| 175 | + }); |
| 176 | +}); |
| 177 | + |
| 178 | +describe("stripControlChars", () => { |
| 179 | + it("should strip ANSI escape sequences", () => { |
| 180 | + expect(stripControlChars("\x1b[2J\x1b[Hfake.txt")).toBe("[2J[Hfake.txt"); |
| 181 | + }); |
| 182 | + |
| 183 | + it("should strip null bytes", () => { |
| 184 | + expect(stripControlChars("file\x00.txt")).toBe("file.txt"); |
| 185 | + }); |
| 186 | + |
| 187 | + it("should strip bell, backspace, and DEL", () => { |
| 188 | + expect(stripControlChars("file\x07\x08\x7F.txt")).toBe("file.txt"); |
| 189 | + }); |
| 190 | + |
| 191 | + it("should preserve tabs and newlines", () => { |
| 192 | + expect(stripControlChars("line1\nline2\ttab")).toBe("line1\nline2\ttab"); |
| 193 | + }); |
| 194 | + |
| 195 | + it("should return normal strings unchanged", () => { |
| 196 | + expect(stripControlChars("/tmp/prompt.txt")).toBe("/tmp/prompt.txt"); |
| 197 | + expect(stripControlChars("")).toBe(""); |
| 198 | + expect(stripControlChars("hello world")).toBe("hello world"); |
| 199 | + }); |
161 | 200 | }); |
162 | 201 |
|
163 | 202 | describe("validatePromptFileStats", () => { |
|
0 commit comments