llm-security/tests/hooks/pre-write-pathguard.test.mjs
Kjell Tore Guttormsen f153f969a0 feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command
Add /ultraresearch-local for structured research combining local codebase
analysis with external knowledge via parallel agent swarms. Produces research
briefs with triangulation, confidence ratings, and source quality assessment.

New command: /ultraresearch-local with modes --quick, --local, --external, --fg.
New agents: research-orchestrator (opus), docs-researcher, community-researcher,
security-researcher, contrarian-researcher, gemini-bridge (all sonnet).
New template: research-brief-template.md.

Integration: --research flag in /ultraplan-local accepts pre-built research
briefs (up to 3), enriches the interview and exploration phases. Planning
orchestrator cross-references brief findings during synthesis.

Design principle: Context Engineering — right information to right agent at
right time. Research briefs are structured artifacts in the pipeline:
ultraresearch → brief → ultraplan --research → plan → ultraexecute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 08:58:35 +02:00

129 lines
5.2 KiB
JavaScript

// pre-write-pathguard.test.mjs — Tests for hooks/scripts/pre-write-pathguard.mjs
// Zero external dependencies: node:test + node:assert only.
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { resolve } from 'node:path';
import { runHook } from './hook-helper.mjs';
const SCRIPT = resolve(import.meta.dirname, '../../hooks/scripts/pre-write-pathguard.mjs');
function writePayload(filePath) {
return { tool_name: 'Write', tool_input: { file_path: filePath, content: 'data' } };
}
// ---------------------------------------------------------------------------
// BLOCK cases — exit code 2
// ---------------------------------------------------------------------------
describe('pre-write-pathguard — BLOCK cases', () => {
it('blocks a write to .env (environment file)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/.env'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /env/);
});
it('blocks a write to .env.local (environment file variant)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/.env.local'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
});
it('blocks a write to .env.production (environment file variant)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/.env.production'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
});
it('blocks a write to .ssh/id_rsa (SSH directory)', async () => {
const result = await runHook(SCRIPT, writePayload('/home/user/.ssh/id_rsa'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /ssh/i);
});
it('blocks a write to .aws/credentials (AWS credentials directory)', async () => {
const result = await runHook(SCRIPT, writePayload('/home/user/.aws/credentials'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /aws/i);
});
it('blocks a write to .gnupg/private-keys-v1.d/key (GPG directory)', async () => {
const result = await runHook(SCRIPT, writePayload('/home/user/.gnupg/private-keys-v1.d/key'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /gnupg/i);
});
it('blocks a write to .npmrc (credential file)', async () => {
const result = await runHook(SCRIPT, writePayload('/home/user/.npmrc'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
});
it('blocks a write to credentials.json (credential file)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/credentials.json'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
});
it('blocks a write to .claude/settings.json (Claude settings file)', async () => {
const result = await runHook(SCRIPT, writePayload('/home/user/.claude/settings.json'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /settings/i);
});
it('blocks a write to .vscode/settings.json (VS Code settings file)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/.vscode/settings.json'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
});
it('blocks a write to /etc/passwd (system directory)', async () => {
const result = await runHook(SCRIPT, writePayload('/etc/passwd'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /system/i);
});
it('blocks a write to a hooks/scripts/*.mjs path (hook script protection)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/hooks/scripts/my-hook.mjs'));
assert.equal(result.code, 2);
assert.match(result.stderr, /PATH GUARD/);
assert.match(result.stderr, /hooks/i);
});
});
// ---------------------------------------------------------------------------
// ALLOW cases — exit code 0
// ---------------------------------------------------------------------------
describe('pre-write-pathguard — ALLOW cases', () => {
it('allows a write to a normal source file (src/app.js)', async () => {
const result = await runHook(SCRIPT, writePayload('src/app.js'));
assert.equal(result.code, 0);
});
it('allows a write to README.md', async () => {
const result = await runHook(SCRIPT, writePayload('README.md'));
assert.equal(result.code, 0);
});
it('allows a write to settings.json at the project root (not inside .claude/ or .vscode/)', async () => {
const result = await runHook(SCRIPT, writePayload('/project/settings.json'));
assert.equal(result.code, 0);
});
it('allows a write when file_path is empty', async () => {
const result = await runHook(SCRIPT, { tool_name: 'Write', tool_input: { file_path: '', content: 'x' } });
assert.equal(result.code, 0);
});
it('exits 0 gracefully when stdin is not valid JSON', async () => {
const result = await runHook(SCRIPT, 'not json {{{');
assert.equal(result.code, 0);
});
});