Extracts validateAgentName() with path.resolve containment guard after regex validation; returns clean ephemeral Discord reply on violation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
31 lines
982 B
TypeScript
31 lines
982 B
TypeScript
import { describe, it, expect } from "vitest";
|
||
import { validateAgentName } from "../../src/commands/new-agent";
|
||
|
||
const ROOT = "/tmp/ws";
|
||
|
||
describe("validateAgentName – path traversal containment", () => {
|
||
it('throws for "../etc"', () => {
|
||
expect(() => validateAgentName("../etc", ROOT)).toThrow();
|
||
});
|
||
|
||
it('throws for ".."', () => {
|
||
expect(() => validateAgentName("..", ROOT)).toThrow();
|
||
});
|
||
|
||
it('does not throw for "a/../b" (resolves to /tmp/ws/b, stays inside root)', () => {
|
||
// path.resolve("/tmp/ws", "a/../b") => "/tmp/ws/b" -- still inside root
|
||
expect(() => validateAgentName("a/../b", ROOT)).not.toThrow();
|
||
});
|
||
|
||
it('throws for empty string ""', () => {
|
||
expect(() => validateAgentName("", ROOT)).toThrow();
|
||
});
|
||
|
||
it('allows "my-agent"', () => {
|
||
expect(() => validateAgentName("my-agent", ROOT)).not.toThrow();
|
||
});
|
||
|
||
it('allows "agent-123"', () => {
|
||
expect(() => validateAgentName("agent-123", ROOT)).not.toThrow();
|
||
});
|
||
});
|