- .claude/hooks/block-secrets.mjs: PreToolUse 훅으로 비밀값 파일 접근 하드 차단 (Read/Edit/Write + Bash cat/less 우회까지). example 파일은 허용. - .claude/settings.json: permissions.deny + 자주 쓰는 dev 명령 allow + 훅 연결 - CLAUDE.md: init 표준 헤더, 하네스 가드/아키텍처 섹션 추가 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
1.8 KiB
JavaScript
Executable File
61 lines
1.8 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
// PreToolUse 가드 — 비밀값 파일 접근을 하드 차단한다.
|
|
//
|
|
// 차단 대상: .project-env, .env, .env.*, ~/.env (LITELLM_KEY 등).
|
|
// - 허용: .project-env.example (참조용 예시는 OK)
|
|
// 적용 도구: Read/Edit/Write/NotebookEdit 의 경로, 그리고 Bash 명령 문자열(cat/less/grep 등 우회 포함).
|
|
//
|
|
// settings.json 의 permissions.deny 는 Read 도구만 막지만, 이 훅은 Bash 우회까지 막는다.
|
|
// 반환: permissionDecision=deny 면 도구 호출이 실행 전에 거부된다.
|
|
|
|
import { readFileSync } from "node:fs";
|
|
|
|
let input = {};
|
|
try {
|
|
input = JSON.parse(readFileSync(0, "utf8") || "{}");
|
|
} catch {
|
|
process.exit(0); // 입력 파싱 실패 시 통과(다른 가드에 위임).
|
|
}
|
|
|
|
const tool = input.tool_name || "";
|
|
const ti = input.tool_input || {};
|
|
|
|
// .project-env(단, .example 제외) 또는 .env / .env.* / ~/.env 를 가리키는 토큰.
|
|
const SECRET_RE =
|
|
/(?:^|[\s'"=(/])\.project-env(?!\.example)|(?:^|[\s'"=(/])\.env(?:\.[\w.-]+)?(?![\w])/;
|
|
|
|
let target = "";
|
|
switch (tool) {
|
|
case "Read":
|
|
case "Edit":
|
|
case "Write":
|
|
target = ti.file_path || "";
|
|
break;
|
|
case "NotebookEdit":
|
|
target = ti.notebook_path || "";
|
|
break;
|
|
case "Bash":
|
|
target = ti.command || "";
|
|
break;
|
|
default:
|
|
process.exit(0);
|
|
}
|
|
|
|
if (SECRET_RE.test(target)) {
|
|
process.stdout.write(
|
|
JSON.stringify({
|
|
hookSpecificOutput: {
|
|
hookEventName: "PreToolUse",
|
|
permissionDecision: "deny",
|
|
permissionDecisionReason:
|
|
"비밀값 파일(.project-env / .env / ~/.env)은 읽거나 수정할 수 없습니다. " +
|
|
"DB·MinIO·LiteLLM 자격증명은 런타임에 환경변수로만 주입됩니다($DATABASE_URL 등). " +
|
|
"키 구조가 궁금하면 .project-env.example 을 보세요.",
|
|
},
|
|
})
|
|
);
|
|
process.exit(0);
|
|
}
|
|
|
|
process.exit(0);
|