promptkaizen-agent 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -4
- package/dist/backfill/run.d.ts +15 -0
- package/dist/backfill/run.d.ts.map +1 -0
- package/dist/backfill/run.js +33 -0
- package/dist/backfill/run.js.map +1 -0
- package/dist/backfill/scanner.d.ts +82 -0
- package/dist/backfill/scanner.d.ts.map +1 -0
- package/dist/backfill/scanner.js +271 -0
- package/dist/backfill/scanner.js.map +1 -0
- package/dist/cli/detect.d.ts +2 -0
- package/dist/cli/detect.d.ts.map +1 -0
- package/dist/cli/detect.js +40 -0
- package/dist/cli/detect.js.map +1 -0
- package/dist/cli/disable.d.ts +2 -0
- package/dist/cli/disable.d.ts.map +1 -0
- package/dist/cli/disable.js +44 -0
- package/dist/cli/disable.js.map +1 -0
- package/dist/cli/enable.d.ts +2 -0
- package/dist/cli/enable.d.ts.map +1 -0
- package/dist/cli/enable.js +105 -0
- package/dist/cli/enable.js.map +1 -0
- package/dist/cli/hook.d.ts +2 -0
- package/dist/cli/hook.d.ts.map +1 -0
- package/dist/cli/hook.js +406 -0
- package/dist/cli/hook.js.map +1 -0
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +70 -5
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/install-hooks.d.ts +5 -0
- package/dist/cli/install-hooks.d.ts.map +1 -0
- package/dist/cli/install-hooks.js +132 -0
- package/dist/cli/install-hooks.js.map +1 -0
- package/dist/cli/install-systemd.d.ts +17 -0
- package/dist/cli/install-systemd.d.ts.map +1 -0
- package/dist/cli/install-systemd.js +96 -0
- package/dist/cli/install-systemd.js.map +1 -0
- package/dist/cli/install-task.d.ts +28 -0
- package/dist/cli/install-task.d.ts.map +1 -0
- package/dist/cli/install-task.js +119 -0
- package/dist/cli/install-task.js.map +1 -0
- package/dist/cli/mcp.d.ts +2 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +148 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/metrics.d.ts +2 -0
- package/dist/cli/metrics.d.ts.map +1 -0
- package/dist/cli/metrics.js +103 -0
- package/dist/cli/metrics.js.map +1 -0
- package/dist/cli/report.d.ts +2 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +211 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/scan.d.ts +2 -0
- package/dist/cli/scan.d.ts.map +1 -0
- package/dist/cli/scan.js +171 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/start.d.ts.map +1 -1
- package/dist/cli/start.js +112 -18
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +105 -19
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/uninstall-systemd.d.ts +8 -0
- package/dist/cli/uninstall-systemd.d.ts.map +1 -0
- package/dist/cli/uninstall-systemd.js +58 -0
- package/dist/cli/uninstall-systemd.js.map +1 -0
- package/dist/cli/uninstall-task.d.ts +8 -0
- package/dist/cli/uninstall-task.d.ts.map +1 -0
- package/dist/cli/uninstall-task.js +44 -0
- package/dist/cli/uninstall-task.js.map +1 -0
- package/dist/config.d.ts +233 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +145 -3
- package/dist/config.js.map +1 -1
- package/dist/console-safe.d.ts +21 -0
- package/dist/console-safe.d.ts.map +1 -0
- package/dist/console-safe.js +71 -0
- package/dist/console-safe.js.map +1 -0
- package/dist/detection-secret.d.ts +8 -0
- package/dist/detection-secret.d.ts.map +1 -0
- package/dist/detection-secret.js +49 -0
- package/dist/detection-secret.js.map +1 -0
- package/dist/env-detect.d.ts +44 -0
- package/dist/env-detect.d.ts.map +1 -0
- package/dist/env-detect.js +151 -0
- package/dist/env-detect.js.map +1 -0
- package/dist/exec/executor.d.ts +42 -0
- package/dist/exec/executor.d.ts.map +1 -0
- package/dist/exec/executor.js +135 -0
- package/dist/exec/executor.js.map +1 -0
- package/dist/exec/pk-execute.d.ts +30 -0
- package/dist/exec/pk-execute.d.ts.map +1 -0
- package/dist/exec/pk-execute.js +174 -0
- package/dist/exec/pk-execute.js.map +1 -0
- package/dist/exec/policy-fetcher.d.ts +9 -0
- package/dist/exec/policy-fetcher.d.ts.map +1 -0
- package/dist/exec/policy-fetcher.js +46 -0
- package/dist/exec/policy-fetcher.js.map +1 -0
- package/dist/exec/policy.d.ts +32 -0
- package/dist/exec/policy.d.ts.map +1 -0
- package/dist/exec/policy.js +88 -0
- package/dist/exec/policy.js.map +1 -0
- package/dist/hooks/block-store.d.ts +14 -0
- package/dist/hooks/block-store.d.ts.map +1 -0
- package/dist/hooks/block-store.js +26 -0
- package/dist/hooks/block-store.js.map +1 -0
- package/dist/hooks/claude-hook.d.ts +55 -0
- package/dist/hooks/claude-hook.d.ts.map +1 -0
- package/dist/hooks/claude-hook.js +122 -0
- package/dist/hooks/claude-hook.js.map +1 -0
- package/dist/hooks/continuity.d.ts +48 -0
- package/dist/hooks/continuity.d.ts.map +1 -0
- package/dist/hooks/continuity.js +92 -0
- package/dist/hooks/continuity.js.map +1 -0
- package/dist/hooks/observation.d.ts +27 -0
- package/dist/hooks/observation.d.ts.map +1 -0
- package/dist/hooks/observation.js +0 -0
- package/dist/hooks/observation.js.map +1 -0
- package/dist/hooks/platforms.d.ts +24 -0
- package/dist/hooks/platforms.d.ts.map +1 -0
- package/dist/hooks/platforms.js +57 -0
- package/dist/hooks/platforms.js.map +1 -0
- package/dist/hooks/read-cache.d.ts +71 -0
- package/dist/hooks/read-cache.d.ts.map +1 -0
- package/dist/hooks/read-cache.js +166 -0
- package/dist/hooks/read-cache.js.map +1 -0
- package/dist/hooks/reduction.d.ts +78 -0
- package/dist/hooks/reduction.d.ts.map +1 -0
- package/dist/hooks/reduction.js +111 -0
- package/dist/hooks/reduction.js.map +1 -0
- package/dist/hooks/settings-merge.d.ts +32 -0
- package/dist/hooks/settings-merge.d.ts.map +1 -0
- package/dist/hooks/settings-merge.js +74 -0
- package/dist/hooks/settings-merge.js.map +1 -0
- package/dist/hooks/snapshot.d.ts +37 -0
- package/dist/hooks/snapshot.d.ts.map +1 -0
- package/dist/hooks/snapshot.js +180 -0
- package/dist/hooks/snapshot.js.map +1 -0
- package/dist/index.js +64 -5
- package/dist/index.js.map +1 -1
- package/dist/mask-rules-fetcher.d.ts +15 -0
- package/dist/mask-rules-fetcher.d.ts.map +1 -0
- package/dist/mask-rules-fetcher.js +67 -0
- package/dist/mask-rules-fetcher.js.map +1 -0
- package/dist/mcp/server.d.ts +118 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +240 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/onboarding-report.d.ts +66 -0
- package/dist/onboarding-report.d.ts.map +1 -0
- package/dist/onboarding-report.js +152 -0
- package/dist/onboarding-report.js.map +1 -0
- package/dist/onboarding.d.ts +55 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +98 -0
- package/dist/onboarding.js.map +1 -0
- package/dist/pii-masker.d.ts +55 -1
- package/dist/pii-masker.d.ts.map +1 -1
- package/dist/pii-masker.js +137 -58
- package/dist/pii-masker.js.map +1 -1
- package/dist/privacy.d.ts +13 -0
- package/dist/privacy.d.ts.map +1 -0
- package/dist/privacy.js +67 -0
- package/dist/privacy.js.map +1 -0
- package/dist/residency.d.ts +21 -0
- package/dist/residency.d.ts.map +1 -0
- package/dist/residency.js +68 -0
- package/dist/residency.js.map +1 -0
- package/dist/secret-detector.d.ts +101 -0
- package/dist/secret-detector.d.ts.map +1 -0
- package/dist/secret-detector.js +516 -0
- package/dist/secret-detector.js.map +1 -0
- package/dist/store/local-store.d.ts +167 -0
- package/dist/store/local-store.d.ts.map +1 -0
- package/dist/store/local-store.js +538 -0
- package/dist/store/local-store.js.map +1 -0
- package/dist/store/schema.d.ts +38 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +189 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/types.d.ts +25 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/watcher.d.ts +6 -0
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +13 -2
- package/dist/watcher.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPkExecute = runPkExecute;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const reduction_1 = require("../hooks/reduction");
|
|
6
|
+
const policy_1 = require("./policy");
|
|
7
|
+
const executor_1 = require("./executor");
|
|
8
|
+
function hashPreview(code) {
|
|
9
|
+
return (0, crypto_1.createHash)('sha256').update(code).digest('hex').slice(0, 16);
|
|
10
|
+
}
|
|
11
|
+
/** 実行ログ/拒否ログの観測 entry を組み立てる (本文はマスク済み・先頭のみ)。 */
|
|
12
|
+
function buildExecEntry(p) {
|
|
13
|
+
const maskedCode = p.maskText(p.code).slice(0, 2000);
|
|
14
|
+
const entry = {
|
|
15
|
+
filepath: 'mcp://pk_execute',
|
|
16
|
+
lineNumber: 0,
|
|
17
|
+
parsedAt: p.now,
|
|
18
|
+
source: 'hook',
|
|
19
|
+
raw: {
|
|
20
|
+
type: 'pk_execute',
|
|
21
|
+
sessionId: null, // MCP 経由はセッション文脈を持たない
|
|
22
|
+
timestamp: p.now,
|
|
23
|
+
language: p.language,
|
|
24
|
+
outcome: p.outcome,
|
|
25
|
+
exitCode: p.exitCode ?? null,
|
|
26
|
+
durationMs: p.durationMs ?? null,
|
|
27
|
+
codeMasked: maskedCode,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
if (p.outcome === 'blocked' && p.ruleId) {
|
|
31
|
+
const detection = {
|
|
32
|
+
category: 'custom',
|
|
33
|
+
ruleId: 'pk_execute_blocked',
|
|
34
|
+
severity: 'high',
|
|
35
|
+
count: 1,
|
|
36
|
+
// 拒否理由の識別補助。コードはマスク済み先頭のみ (cloud 上限 200 文字)。
|
|
37
|
+
maskedPreview: `[${p.ruleId}] ${maskedCode}`.slice(0, 200),
|
|
38
|
+
matchHash: hashPreview(p.code),
|
|
39
|
+
};
|
|
40
|
+
entry.detections = [detection];
|
|
41
|
+
}
|
|
42
|
+
if (p.reduction)
|
|
43
|
+
entry.reduction = p.reduction;
|
|
44
|
+
return entry;
|
|
45
|
+
}
|
|
46
|
+
/** pk_execute 本体。例外を投げず PkExecuteResult に正規化する。 */
|
|
47
|
+
async function runPkExecute(deps, args) {
|
|
48
|
+
const now = deps.now ?? (() => new Date().toISOString());
|
|
49
|
+
const language = args.language;
|
|
50
|
+
const code = typeof args.code === 'string' ? args.code : '';
|
|
51
|
+
if (!(0, executor_1.isExecLanguage)(language)) {
|
|
52
|
+
return {
|
|
53
|
+
content: [{ type: 'text', text: 'language は bash / node / python のいずれかを指定してください' }],
|
|
54
|
+
isError: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (!code.trim()) {
|
|
58
|
+
return { content: [{ type: 'text', text: 'code は必須です' }], isError: true };
|
|
59
|
+
}
|
|
60
|
+
const timeoutArg = typeof args.timeout === 'number' && Number.isFinite(args.timeout) ? args.timeout : null;
|
|
61
|
+
const timeoutMs = timeoutArg ? Math.min(Math.max(timeoutArg * 1000, 1000), 300_000) : deps.timeoutMs;
|
|
62
|
+
// 1. 実行前ポリシー判定 (#44 接続)。拒否は違反イベントとして記録される。
|
|
63
|
+
const verdict = (0, policy_1.checkExecutionPolicy)(code, deps.getPolicy(), deps.projectRoot);
|
|
64
|
+
if (!verdict.allowed) {
|
|
65
|
+
await deps
|
|
66
|
+
.recordEntry(buildExecEntry({
|
|
67
|
+
maskText: deps.maskText,
|
|
68
|
+
now: now(),
|
|
69
|
+
language,
|
|
70
|
+
code,
|
|
71
|
+
outcome: 'blocked',
|
|
72
|
+
ruleId: verdict.ruleId,
|
|
73
|
+
}))
|
|
74
|
+
.catch(() => { });
|
|
75
|
+
return {
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: `PromptKaizen のポリシーにより実行をブロックしました: ${verdict.reason}\n` +
|
|
80
|
+
'コードを修正するか、組織の管理者にポリシー設定を確認してください。',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// 2. 実行 (サンドボックス制約は executor 側)。
|
|
87
|
+
const exec = deps.execImpl ?? executor_1.executeCode;
|
|
88
|
+
const result = await exec({
|
|
89
|
+
language,
|
|
90
|
+
code,
|
|
91
|
+
projectRoot: deps.projectRoot,
|
|
92
|
+
timeoutMs,
|
|
93
|
+
});
|
|
94
|
+
// 3. 返却 stdout のマスク → 上限トリム (超過分は R1 退避 + 削減イベント)。
|
|
95
|
+
const masked = deps.maskText(result.stdout);
|
|
96
|
+
let returned = masked;
|
|
97
|
+
let reduction;
|
|
98
|
+
let overflowNote = '';
|
|
99
|
+
if (Buffer.byteLength(masked, 'utf8') > deps.maxReturnBytes) {
|
|
100
|
+
returned = masked.slice(0, deps.maxReturnBytes);
|
|
101
|
+
const refId = (0, executor_1.generateExecId)();
|
|
102
|
+
try {
|
|
103
|
+
deps.storeRef({
|
|
104
|
+
refId,
|
|
105
|
+
sessionId: null,
|
|
106
|
+
toolName: 'pk_execute',
|
|
107
|
+
cwd: deps.projectRoot,
|
|
108
|
+
createdAt: now(),
|
|
109
|
+
originalBytes: Buffer.byteLength(masked, 'utf8'),
|
|
110
|
+
originalTokens: (0, reduction_1.estimateTokensFromText)(masked),
|
|
111
|
+
replacedTokens: (0, reduction_1.estimateTokensFromText)(returned),
|
|
112
|
+
savedTokens: (0, reduction_1.estimateTokensFromText)(masked) - (0, reduction_1.estimateTokensFromText)(returned),
|
|
113
|
+
body: masked,
|
|
114
|
+
});
|
|
115
|
+
reduction = {
|
|
116
|
+
kind: 'r2_execute',
|
|
117
|
+
refId,
|
|
118
|
+
originalTokens: (0, reduction_1.estimateTokensFromText)(masked),
|
|
119
|
+
replacedTokens: (0, reduction_1.estimateTokensFromText)(returned),
|
|
120
|
+
savedTokens: (0, reduction_1.estimateTokensFromText)(masked) - (0, reduction_1.estimateTokensFromText)(returned),
|
|
121
|
+
};
|
|
122
|
+
overflowNote =
|
|
123
|
+
`\n--- stdout が上限 (${deps.maxReturnBytes.toLocaleString()} bytes) を超えたため切り詰めました。` +
|
|
124
|
+
`全文: pk_fetch(ref_id: "${refId}") / 絞り込み: pk_fetch(ref_id: "${refId}", query: "検索語") ---`;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// 退避失敗時は参照を案内しない (切り詰めのみ)。
|
|
128
|
+
overflowNote = `\n--- stdout が上限 (${deps.maxReturnBytes.toLocaleString()} bytes) を超えたため切り詰めました ---`;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// 4. 実行ログ (#68) + 削減イベント (#92) を記録 (best-effort)。
|
|
132
|
+
await deps
|
|
133
|
+
.recordEntry(buildExecEntry({
|
|
134
|
+
maskText: deps.maskText,
|
|
135
|
+
now: now(),
|
|
136
|
+
language,
|
|
137
|
+
code,
|
|
138
|
+
outcome: 'executed',
|
|
139
|
+
exitCode: result.exitCode,
|
|
140
|
+
durationMs: result.durationMs,
|
|
141
|
+
reduction,
|
|
142
|
+
}))
|
|
143
|
+
.catch(() => { });
|
|
144
|
+
// 5. 応答の組み立て。
|
|
145
|
+
if (result.timedOut) {
|
|
146
|
+
return {
|
|
147
|
+
content: [
|
|
148
|
+
{
|
|
149
|
+
type: 'text',
|
|
150
|
+
text: `タイムアウト (${Math.round(timeoutMs / 1000)}s) のため実行を中断しました。` + (returned ? `\n--- 中断までの stdout ---\n${returned}${overflowNote}` : ''),
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
isError: true,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (result.exitCode !== 0) {
|
|
157
|
+
const stderrMasked = deps.maskText(result.stderrHead);
|
|
158
|
+
return {
|
|
159
|
+
content: [
|
|
160
|
+
{
|
|
161
|
+
type: 'text',
|
|
162
|
+
text: `exit code ${result.exitCode ?? 'null'} (${result.durationMs}ms)\n` +
|
|
163
|
+
(stderrMasked ? `--- stderr (先頭) ---\n${stderrMasked}\n` : '') +
|
|
164
|
+
(returned ? `--- stdout ---\n${returned}${overflowNote}` : ''),
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
isError: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
content: [{ type: 'text', text: (returned || '(stdout なし)') + overflowNote }],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=pk-execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pk-execute.js","sourceRoot":"","sources":["../../src/exec/pk-execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ExecutionPolicy } from './policy';
|
|
2
|
+
export interface FetchExecutionPolicyOptions {
|
|
3
|
+
apiEndpoint: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
}
|
|
7
|
+
/** 組織/ユーザーの実行ポリシーを取得する。未設定・通信エラーは null。 */
|
|
8
|
+
export declare function fetchExecutionPolicy(opts: FetchExecutionPolicyOptions): Promise<ExecutionPolicy | null>;
|
|
9
|
+
//# sourceMappingURL=policy-fetcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-fetcher.d.ts","sourceRoot":"","sources":["../../src/exec/policy-fetcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAgB/C,MAAM,WAAW,2BAA2B;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AAED,2CAA2C;AAC3C,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAuBjC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchExecutionPolicy = fetchExecutionPolicy;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const logger_1 = require("../logger");
|
|
6
|
+
const mask_rules_fetcher_1 = require("../mask-rules-fetcher");
|
|
7
|
+
// =============================================
|
|
8
|
+
// 組織実行ポリシーの取得 (Issue #94 / #44 接続)
|
|
9
|
+
// =============================================
|
|
10
|
+
//
|
|
11
|
+
// 配信は既存の getAgentMaskRules 応答に同梱される execution フィールドを使う
|
|
12
|
+
// (新エンドポイントを増やさない — functions のデプロイ明示列挙を変えないため)。
|
|
13
|
+
// 取得できない場合は null を返し、ビルトイン禁止リストのみで動作する
|
|
14
|
+
// (緩める方向には倒れない = 安全側)。
|
|
15
|
+
const ExecutionPolicySchema = zod_1.z.object({
|
|
16
|
+
forbiddenCommands: zod_1.z.array(zod_1.z.string().min(1).max(200)).max(50).default([]),
|
|
17
|
+
forbiddenPaths: zod_1.z.array(zod_1.z.string().min(1).max(200)).max(50).default([]),
|
|
18
|
+
});
|
|
19
|
+
/** 組織/ユーザーの実行ポリシーを取得する。未設定・通信エラーは null。 */
|
|
20
|
+
async function fetchExecutionPolicy(opts) {
|
|
21
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
22
|
+
try {
|
|
23
|
+
const res = await doFetch((0, mask_rules_fetcher_1.maskRulesUrl)(opts.apiEndpoint), {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` },
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
logger_1.logger.warn('fetchExecutionPolicy: non-OK response', { status: res.status });
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const body = (await res.json());
|
|
32
|
+
if (!body.success || body.execution == null)
|
|
33
|
+
return null;
|
|
34
|
+
const parsed = ExecutionPolicySchema.safeParse(body.execution);
|
|
35
|
+
if (!parsed.success) {
|
|
36
|
+
logger_1.logger.warn('fetchExecutionPolicy: invalid payload', { error: parsed.error.message });
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return parsed.data;
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
logger_1.logger.warn('fetchExecutionPolicy failed', { error: e.message });
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=policy-fetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-fetcher.js","sourceRoot":"","sources":["../../src/exec/policy-fetcher.ts"],"names":[],"mappings":";;AA0BA,oDAyBC;AAnDD,6BAAuB;AACvB,sCAAkC;AAClC,8DAAoD;AAGpD,gDAAgD;AAChD,mCAAmC;AACnC,gDAAgD;AAChD,EAAE;AACF,uDAAuD;AACvD,iDAAiD;AACjD,uCAAuC;AACvC,uBAAuB;AAEvB,MAAM,qBAAqB,GAAG,OAAC,CAAC,MAAM,CAAC;IACrC,iBAAiB,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1E,cAAc,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxE,CAAC,CAAA;AAQF,2CAA2C;AACpC,KAAK,UAAU,oBAAoB,CACxC,IAAiC;IAEjC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAA;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAA,iCAAY,EAAC,IAAI,CAAC,WAAW,CAAC,EAAE;YACxD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE;SACpD,CAAC,CAAA;QACF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,eAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YAC5E,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA+C,CAAA;QAC7E,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI;YAAE,OAAO,IAAI,CAAA;QACxD,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC9D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,eAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACrF,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAA;IACpB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,eAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC,CAAA;QAC3E,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** 組織ポリシー (#44 PolicyConfig.execution) の agent 側表現。 */
|
|
2
|
+
export interface ExecutionPolicy {
|
|
3
|
+
/** 禁止コマンド (正規表現文字列)。 */
|
|
4
|
+
forbiddenCommands: string[];
|
|
5
|
+
/** 禁止パス (前方一致 / ~ 展開対応)。 */
|
|
6
|
+
forbiddenPaths: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* ビルトイン禁止コマンド (高シグナルのみ。誤検知しやすい汎用語は入れない)。
|
|
10
|
+
* 組織ポリシーは追加方向にのみ働く (緩める方向の上書きは不可 = 安全側)。
|
|
11
|
+
*/
|
|
12
|
+
export declare const BUILTIN_FORBIDDEN_COMMANDS: Array<{
|
|
13
|
+
ruleId: string;
|
|
14
|
+
pattern: string;
|
|
15
|
+
label: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** ビルトイン禁止パス (秘匿情報ディレクトリ)。組織ポリシーで追加可能。 */
|
|
18
|
+
export declare const BUILTIN_FORBIDDEN_PATHS: string[];
|
|
19
|
+
export interface PolicyVerdict {
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
/** 拒否時のみ。detection メタ・拒否メッセージに使う。 */
|
|
22
|
+
ruleId?: string;
|
|
23
|
+
reason?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* code を実行ポリシーに照らす。拒否は最初の該当 1 件を返す。
|
|
27
|
+
* - 禁止コマンド: ビルトイン + 組織ポリシーの正規表現
|
|
28
|
+
* - 禁止パス: ビルトイン + 組織ポリシー (~ 表記と展開後の両方で部分一致)
|
|
29
|
+
* - プロジェクトルート外の絶対パス参照 (ホーム直下・システム領域) を拒否
|
|
30
|
+
*/
|
|
31
|
+
export declare function checkExecutionPolicy(code: string, policy: ExecutionPolicy | null, projectRoot: string): PolicyVerdict;
|
|
32
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/exec/policy.ts"],"names":[],"mappings":"AAiBA,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,4BAA4B;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,0BAA0B,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAQhG,CAAA;AAED,0CAA0C;AAC1C,eAAO,MAAM,uBAAuB,UAA0E,CAAA;AAE9G,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAMD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,eAAe,GAAG,IAAI,EAC9B,WAAW,EAAE,MAAM,GAClB,aAAa,CAkDf"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BUILTIN_FORBIDDEN_PATHS = exports.BUILTIN_FORBIDDEN_COMMANDS = void 0;
|
|
7
|
+
exports.checkExecutionPolicy = checkExecutionPolicy;
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
/**
|
|
11
|
+
* ビルトイン禁止コマンド (高シグナルのみ。誤検知しやすい汎用語は入れない)。
|
|
12
|
+
* 組織ポリシーは追加方向にのみ働く (緩める方向の上書きは不可 = 安全側)。
|
|
13
|
+
*/
|
|
14
|
+
exports.BUILTIN_FORBIDDEN_COMMANDS = [
|
|
15
|
+
{ ruleId: 'exec_rm_rf', pattern: 'rm\\s+(-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r)\\b', label: 'rm -rf' },
|
|
16
|
+
{ ruleId: 'exec_sudo', pattern: '(^|[\\s;|&])sudo\\s', label: 'sudo' },
|
|
17
|
+
{ ruleId: 'exec_mkfs', pattern: '\\bmkfs(\\.|\\s)', label: 'mkfs' },
|
|
18
|
+
{ ruleId: 'exec_dd_device', pattern: '\\bdd\\s+[^\\n]*of=/dev/', label: 'dd of=/dev/*' },
|
|
19
|
+
{ ruleId: 'exec_fork_bomb', pattern: ':\\(\\)\\s*\\{\\s*:\\s*\\|\\s*:', label: 'fork bomb' },
|
|
20
|
+
{ ruleId: 'exec_shutdown', pattern: '(^|[\\s;|&])(shutdown|reboot|halt)\\s*($|[\\s;|&-])', label: 'shutdown/reboot' },
|
|
21
|
+
{ ruleId: 'exec_curl_pipe_sh', pattern: '(curl|wget)\\s[^\\n|]*\\|\\s*(ba|z)?sh\\b', label: 'curl | sh' },
|
|
22
|
+
];
|
|
23
|
+
/** ビルトイン禁止パス (秘匿情報ディレクトリ)。組織ポリシーで追加可能。 */
|
|
24
|
+
exports.BUILTIN_FORBIDDEN_PATHS = ['~/.ssh', '~/.aws', '~/.gnupg', '~/.config/gcloud', '~/.promptkaizen'];
|
|
25
|
+
function expandHome(p) {
|
|
26
|
+
return p.startsWith('~') ? path_1.default.join(os_1.default.homedir(), p.slice(1)) : p;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* code を実行ポリシーに照らす。拒否は最初の該当 1 件を返す。
|
|
30
|
+
* - 禁止コマンド: ビルトイン + 組織ポリシーの正規表現
|
|
31
|
+
* - 禁止パス: ビルトイン + 組織ポリシー (~ 表記と展開後の両方で部分一致)
|
|
32
|
+
* - プロジェクトルート外の絶対パス参照 (ホーム直下・システム領域) を拒否
|
|
33
|
+
*/
|
|
34
|
+
function checkExecutionPolicy(code, policy, projectRoot) {
|
|
35
|
+
// 1. 禁止コマンド (ビルトイン)
|
|
36
|
+
for (const b of exports.BUILTIN_FORBIDDEN_COMMANDS) {
|
|
37
|
+
if (new RegExp(b.pattern).test(code)) {
|
|
38
|
+
return { allowed: false, ruleId: b.ruleId, reason: `禁止コマンド (${b.label}) を含むため実行できません` };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// 2. 禁止コマンド (組織ポリシー)。不正な正規表現は 1 件で全体を落とさずスキップ。
|
|
42
|
+
for (const pattern of policy?.forbiddenCommands ?? []) {
|
|
43
|
+
try {
|
|
44
|
+
if (new RegExp(pattern).test(code)) {
|
|
45
|
+
return {
|
|
46
|
+
allowed: false,
|
|
47
|
+
ruleId: 'exec_org_forbidden_command',
|
|
48
|
+
reason: '組織ポリシーの禁止コマンドに該当するため実行できません',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
/* invalid regex → skip */
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 3. 禁止パス (ビルトイン + 組織)。~ 表記と展開後の両方を見る。
|
|
57
|
+
const forbiddenPaths = [...exports.BUILTIN_FORBIDDEN_PATHS, ...(policy?.forbiddenPaths ?? [])];
|
|
58
|
+
for (const p of forbiddenPaths) {
|
|
59
|
+
const expanded = expandHome(p);
|
|
60
|
+
if (code.includes(p) || (expanded !== p && code.includes(expanded))) {
|
|
61
|
+
return {
|
|
62
|
+
allowed: false,
|
|
63
|
+
ruleId: 'exec_forbidden_path',
|
|
64
|
+
reason: `禁止パス (${p}) への参照を含むため実行できません`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// 4. プロジェクトルート外の絶対パス参照 (作業ディレクトリ制限)。
|
|
69
|
+
// システム領域・他ユーザー領域を指す絶対パスを高シグナルに検査する。
|
|
70
|
+
// /tmp と projectRoot 配下、および /usr 等の読み取り系ツールパスは許容。
|
|
71
|
+
const rootResolved = path_1.default.resolve(projectRoot);
|
|
72
|
+
const absPattern = /(?:^|[\s"'`=(])(\/(?:Users|home|etc|var|root)\/[^\s"'`);|&]*)/g;
|
|
73
|
+
for (const m of code.matchAll(absPattern)) {
|
|
74
|
+
const ref = m[1];
|
|
75
|
+
const resolved = path_1.default.resolve(ref);
|
|
76
|
+
if (resolved === rootResolved || resolved.startsWith(rootResolved + path_1.default.sep))
|
|
77
|
+
continue;
|
|
78
|
+
if (resolved.startsWith(path_1.default.resolve(os_1.default.tmpdir()) + path_1.default.sep))
|
|
79
|
+
continue;
|
|
80
|
+
return {
|
|
81
|
+
allowed: false,
|
|
82
|
+
ruleId: 'exec_outside_project_root',
|
|
83
|
+
reason: `プロジェクトルート外のパス (${ref}) への参照を含むため実行できません`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return { allowed: true };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/exec/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DetectionMeta } from '../secret-detector';
|
|
2
|
+
declare const BLOCK_LOG_PATH: string;
|
|
3
|
+
export interface BlockEvent {
|
|
4
|
+
recordedAt: string;
|
|
5
|
+
sessionId: string | null;
|
|
6
|
+
cwd: string | null;
|
|
7
|
+
toolName: string | null;
|
|
8
|
+
/** 生機密を含まない検知メタ。 */
|
|
9
|
+
detections: DetectionMeta[];
|
|
10
|
+
}
|
|
11
|
+
/** ブロックイベントを 1 行 append する (best-effort、失敗してもブロック自体は成立)。 */
|
|
12
|
+
export declare function recordBlockEvent(event: BlockEvent, logPath?: string): Promise<void>;
|
|
13
|
+
export { BLOCK_LOG_PATH };
|
|
14
|
+
//# sourceMappingURL=block-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-store.d.ts","sourceRoot":"","sources":["../../src/hooks/block-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAWvD,QAAA,MAAM,cAAc,QAAiE,CAAA;AAErF,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,oBAAoB;IACpB,UAAU,EAAE,aAAa,EAAE,CAAA;CAC5B;AAED,4DAA4D;AAC5D,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,MAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BLOCK_LOG_PATH = void 0;
|
|
7
|
+
exports.recordBlockEvent = recordBlockEvent;
|
|
8
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
// =============================================
|
|
12
|
+
// ブロックイベントの記録 (Issue #67)
|
|
13
|
+
// =============================================
|
|
14
|
+
//
|
|
15
|
+
// PreToolUse で deny したイベントをローカルに追記記録する。受け入れ条件は
|
|
16
|
+
// 「ローカル SQLite へ記録」だが、SQLite 導入は Epic #66 P2 (#68) の専用スコープ。
|
|
17
|
+
// 本タスクでは依存を増やさず JSONL に追記し、#68 で SQLite (FTS5) へ移行する。
|
|
18
|
+
// 記録するのは検知メタ (生機密本文を含まない) のみ。
|
|
19
|
+
const BLOCK_LOG_PATH = path_1.default.join(os_1.default.homedir(), '.promptkaizen', 'block-events.jsonl');
|
|
20
|
+
exports.BLOCK_LOG_PATH = BLOCK_LOG_PATH;
|
|
21
|
+
/** ブロックイベントを 1 行 append する (best-effort、失敗してもブロック自体は成立)。 */
|
|
22
|
+
async function recordBlockEvent(event, logPath = BLOCK_LOG_PATH) {
|
|
23
|
+
await promises_1.default.mkdir(path_1.default.dirname(logPath), { recursive: true });
|
|
24
|
+
await promises_1.default.appendFile(logPath, JSON.stringify(event) + '\n', { mode: 0o600 });
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=block-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-store.js","sourceRoot":"","sources":["../../src/hooks/block-store.ts"],"names":[],"mappings":";;;;;;AA0BA,4CAMC;AAhCD,2DAA4B;AAC5B,4CAAmB;AACnB,gDAAuB;AAGvB,gDAAgD;AAChD,0BAA0B;AAC1B,gDAAgD;AAChD,EAAE;AACF,+CAA+C;AAC/C,4DAA4D;AAC5D,sDAAsD;AACtD,8BAA8B;AAE9B,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAA;AAoB5E,wCAAc;AATvB,4DAA4D;AACrD,KAAK,UAAU,gBAAgB,CACpC,KAAiB,EACjB,UAAkB,cAAc;IAEhC,MAAM,kBAAE,CAAC,KAAK,CAAC,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,MAAM,kBAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AAC7E,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SecretDetector, type DetectionMeta } from '../secret-detector';
|
|
2
|
+
/**
|
|
3
|
+
* 対応する hook イベント (全プラットフォームの和集合)。
|
|
4
|
+
* プラットフォーム別にどれを登録/受理するかは hooks/platforms.ts が定義する。
|
|
5
|
+
* - PreCompact: Claude Code 固有。
|
|
6
|
+
* - Stop: Codex CLI のターン終了イベント (#70)。観測のみ。
|
|
7
|
+
*/
|
|
8
|
+
export declare const SUPPORTED_EVENTS: readonly ["PreToolUse", "PostToolUse", "UserPromptSubmit", "SessionStart", "PreCompact", "Stop"];
|
|
9
|
+
export type HookEvent = (typeof SUPPORTED_EVENTS)[number];
|
|
10
|
+
export declare function isHookEvent(v: unknown): v is HookEvent;
|
|
11
|
+
/** Claude Code が stdin で渡す共通フィールド (必要な分のみ)。 */
|
|
12
|
+
export interface HookInput {
|
|
13
|
+
hook_event_name?: string;
|
|
14
|
+
session_id?: string;
|
|
15
|
+
cwd?: string;
|
|
16
|
+
transcript_path?: string;
|
|
17
|
+
tool_name?: string;
|
|
18
|
+
tool_input?: unknown;
|
|
19
|
+
prompt?: string;
|
|
20
|
+
[k: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* PreToolUse の deny は無条件ブロックなので、誤検知の影響が大きい。
|
|
24
|
+
* file_path 等の「パスにキーらしき文字列が紛れる」誤検出を避けるため、
|
|
25
|
+
* 値部分 (コマンド本文・プロンプト) のみを検知対象に集める。
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractRiskText(event: HookEvent, input: HookInput): string;
|
|
28
|
+
/** PreToolUse の出力 (Claude Code hooks の hookSpecificOutput 形式)。 */
|
|
29
|
+
export interface PreToolUseDecision {
|
|
30
|
+
hookSpecificOutput: {
|
|
31
|
+
hookEventName: 'PreToolUse';
|
|
32
|
+
permissionDecision: 'deny' | 'allow' | 'ask';
|
|
33
|
+
permissionDecisionReason: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** 検知メタから日本語の deny 理由を組み立てる (具体的に・生機密は出さない)。 */
|
|
37
|
+
export declare function buildDenyReason(detections: DetectionMeta[]): string;
|
|
38
|
+
/** PreToolUse の判定結果。 */
|
|
39
|
+
export interface HookEvaluation {
|
|
40
|
+
/** PreToolUse で deny したか。 */
|
|
41
|
+
blocked: boolean;
|
|
42
|
+
/** 検知メタ (生機密は含まない)。記録・送信に使う。 */
|
|
43
|
+
detections: DetectionMeta[];
|
|
44
|
+
/** Claude Code に返す stdout JSON。null なら出力なし (= allow)。 */
|
|
45
|
+
output: PreToolUseDecision | null;
|
|
46
|
+
/** 終了コード。PreToolUse の deny は exit 0 + JSON で制御 (exit 2 は非構造化 block)。 */
|
|
47
|
+
exitCode: 0 | 2;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* hook イベントを評価する純粋関数。
|
|
51
|
+
* - PreToolUse: 検知に該当したら deny を返す。
|
|
52
|
+
* - その他: 検知のみ付与 (ブロックはしない)。
|
|
53
|
+
*/
|
|
54
|
+
export declare function evaluateHook(event: HookEvent, input: HookInput, detector: SecretDetector): HookEvaluation;
|
|
55
|
+
//# sourceMappingURL=claude-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hook.d.ts","sourceRoot":"","sources":["../../src/hooks/claude-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAkB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAcvF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,kGAOnB,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzD,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,SAAS,CAEtD;AAED,+CAA+C;AAC/C,MAAM,WAAW,SAAS;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAO1E;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,EAAE;QAClB,aAAa,EAAE,YAAY,CAAA;QAC3B,kBAAkB,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;QAC5C,wBAAwB,EAAE,MAAM,CAAA;KACjC,CAAA;CACF;AAUD,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,MAAM,CAenE;AA6BD,wBAAwB;AACxB,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,gCAAgC;IAChC,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,yDAAyD;IACzD,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjC,wEAAwE;IACxE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;CAChB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,cAAc,GACvB,cAAc,CAwBhB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SUPPORTED_EVENTS = void 0;
|
|
4
|
+
exports.isHookEvent = isHookEvent;
|
|
5
|
+
exports.extractRiskText = extractRiskText;
|
|
6
|
+
exports.buildDenyReason = buildDenyReason;
|
|
7
|
+
exports.evaluateHook = evaluateHook;
|
|
8
|
+
const secret_detector_1 = require("../secret-detector");
|
|
9
|
+
// =============================================
|
|
10
|
+
// Claude Code hooks アダプタ (Issue #67 / Epic #66 P1) — 純粋ロジック
|
|
11
|
+
// =============================================
|
|
12
|
+
//
|
|
13
|
+
// Claude Code 公式 hooks は JSON を stdin で渡し、stdout の JSON で制御する。
|
|
14
|
+
// 本モジュールは「stdin の event payload を受け取り、返すべき hook 出力 +
|
|
15
|
+
// 送信すべき観測 entry を計算する」純粋部分。I/O (stdin 読み取り・送信・記録) は
|
|
16
|
+
// cli/hook.ts が担う。install-launchd / install-systemd と同じテスト容易性方針。
|
|
17
|
+
//
|
|
18
|
+
// 検知 (#42) を PreToolUse に接続して「事後検知」を「事前ブロック」に格上げする。
|
|
19
|
+
// 既存 chokidar 経路は補完として併存 (hooks 未登録環境・取りこぼし回収)。
|
|
20
|
+
/**
|
|
21
|
+
* 対応する hook イベント (全プラットフォームの和集合)。
|
|
22
|
+
* プラットフォーム別にどれを登録/受理するかは hooks/platforms.ts が定義する。
|
|
23
|
+
* - PreCompact: Claude Code 固有。
|
|
24
|
+
* - Stop: Codex CLI のターン終了イベント (#70)。観測のみ。
|
|
25
|
+
*/
|
|
26
|
+
exports.SUPPORTED_EVENTS = [
|
|
27
|
+
'PreToolUse',
|
|
28
|
+
'PostToolUse',
|
|
29
|
+
'UserPromptSubmit',
|
|
30
|
+
'SessionStart',
|
|
31
|
+
'PreCompact',
|
|
32
|
+
'Stop',
|
|
33
|
+
];
|
|
34
|
+
function isHookEvent(v) {
|
|
35
|
+
return typeof v === 'string' && exports.SUPPORTED_EVENTS.includes(v);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* PreToolUse の deny は無条件ブロックなので、誤検知の影響が大きい。
|
|
39
|
+
* file_path 等の「パスにキーらしき文字列が紛れる」誤検出を避けるため、
|
|
40
|
+
* 値部分 (コマンド本文・プロンプト) のみを検知対象に集める。
|
|
41
|
+
*/
|
|
42
|
+
function extractRiskText(event, input) {
|
|
43
|
+
if (event === 'UserPromptSubmit') {
|
|
44
|
+
return typeof input.prompt === 'string' ? input.prompt : '';
|
|
45
|
+
}
|
|
46
|
+
// PreToolUse / PostToolUse: tool_input 全体の string を集める。
|
|
47
|
+
// Bash の command、Write/Edit の content 等が含まれる。
|
|
48
|
+
return (0, secret_detector_1.collectStrings)(input.tool_input ?? {});
|
|
49
|
+
}
|
|
50
|
+
const SEVERITY_LABEL = { high: '重大', medium: '中', low: '低' };
|
|
51
|
+
const CATEGORY_LABEL = {
|
|
52
|
+
secret: 'シークレット',
|
|
53
|
+
pii: '個人情報',
|
|
54
|
+
pii_jp: '個人情報(日本)',
|
|
55
|
+
custom: '社内機密',
|
|
56
|
+
};
|
|
57
|
+
/** 検知メタから日本語の deny 理由を組み立てる (具体的に・生機密は出さない)。 */
|
|
58
|
+
function buildDenyReason(detections) {
|
|
59
|
+
const top = [...detections].sort((a, b) => severityRank(b.severity) - severityRank(a.severity));
|
|
60
|
+
const lines = top
|
|
61
|
+
.slice(0, 5)
|
|
62
|
+
.map((d) => `・${CATEGORY_LABEL[d.category] ?? d.category} / ${ruleLabel(d.ruleId)} ` +
|
|
63
|
+
`(重大度: ${SEVERITY_LABEL[d.severity] ?? d.severity}, ${d.count} 件, 例: ${d.maskedPreview})`);
|
|
64
|
+
return ('PromptKaizen のポリシーにより、このツール実行をブロックしました。\n' +
|
|
65
|
+
'以下の機密情報が含まれています:\n' +
|
|
66
|
+
lines.join('\n') +
|
|
67
|
+
'\n機密値を削除するか、環境変数・シークレットマネージャ経由に変更してから再実行してください。');
|
|
68
|
+
}
|
|
69
|
+
function severityRank(s) {
|
|
70
|
+
return s === 'high' ? 2 : s === 'medium' ? 1 : 0;
|
|
71
|
+
}
|
|
72
|
+
const RULE_LABEL = {
|
|
73
|
+
anthropic_key: 'Anthropic APIキー',
|
|
74
|
+
openai_key: 'OpenAI APIキー',
|
|
75
|
+
github_token: 'GitHub トークン',
|
|
76
|
+
slack_token: 'Slack トークン',
|
|
77
|
+
aws_access_key: 'AWS アクセスキー',
|
|
78
|
+
gcp_api_key: 'GCP APIキー',
|
|
79
|
+
private_key_block: '秘密鍵ブロック',
|
|
80
|
+
jwt: 'JWT',
|
|
81
|
+
bearer_token: 'Bearer トークン',
|
|
82
|
+
high_entropy: '高エントロピー文字列',
|
|
83
|
+
jp_mynumber: 'マイナンバー',
|
|
84
|
+
jp_corporate_number: '法人番号',
|
|
85
|
+
jp_phone: '電話番号',
|
|
86
|
+
jp_postal: '郵便番号',
|
|
87
|
+
jp_address: '住所',
|
|
88
|
+
credit_card: 'クレジットカード番号',
|
|
89
|
+
email: 'メールアドレス',
|
|
90
|
+
};
|
|
91
|
+
function ruleLabel(id) {
|
|
92
|
+
return RULE_LABEL[id] ?? id;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* hook イベントを評価する純粋関数。
|
|
96
|
+
* - PreToolUse: 検知に該当したら deny を返す。
|
|
97
|
+
* - その他: 検知のみ付与 (ブロックはしない)。
|
|
98
|
+
*/
|
|
99
|
+
function evaluateHook(event, input, detector) {
|
|
100
|
+
const text = extractRiskText(event, input);
|
|
101
|
+
const detections = text ? detector.detect(text) : [];
|
|
102
|
+
// PreToolUse の deny は無条件ブロックなので誤検知の影響が大きい。
|
|
103
|
+
// 重大度 high (重大) のみをブロック対象とし、medium/low は観測のみ
|
|
104
|
+
// (記録・送信は全件残す) に留めて通常の開発作業を妨げない。
|
|
105
|
+
const blocking = detections.filter((d) => d.severity === 'high');
|
|
106
|
+
if (event === 'PreToolUse' && blocking.length > 0) {
|
|
107
|
+
return {
|
|
108
|
+
blocked: true,
|
|
109
|
+
detections,
|
|
110
|
+
output: {
|
|
111
|
+
hookSpecificOutput: {
|
|
112
|
+
hookEventName: 'PreToolUse',
|
|
113
|
+
permissionDecision: 'deny',
|
|
114
|
+
permissionDecisionReason: buildDenyReason(blocking),
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
exitCode: 0,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return { blocked: false, detections, output: null, exitCode: 0 };
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=claude-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-hook.js","sourceRoot":"","sources":["../../src/hooks/claude-hook.ts"],"names":[],"mappings":"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"}
|