promptkaizen-agent 0.6.3 → 0.7.2
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 +24 -0
- package/dist/analyze/index.d.ts.map +1 -1
- package/dist/analyze/index.js +1 -1
- package/dist/analyze/index.js.map +1 -1
- package/dist/analyze/optimize-rules-fetcher.d.ts +1 -2
- package/dist/analyze/optimize-rules-fetcher.d.ts.map +1 -1
- package/dist/analyze/optimize-rules-fetcher.js +5 -2
- package/dist/analyze/optimize-rules-fetcher.js.map +1 -1
- package/dist/batcher.d.ts +18 -1
- package/dist/batcher.d.ts.map +1 -1
- package/dist/batcher.js +77 -36
- package/dist/batcher.js.map +1 -1
- package/dist/cli/disable-hooks.d.ts +2 -0
- package/dist/cli/disable-hooks.d.ts.map +1 -0
- package/dist/cli/disable-hooks.js +117 -0
- package/dist/cli/disable-hooks.js.map +1 -0
- package/dist/cli/hook.d.ts.map +1 -1
- package/dist/cli/hook.js +15 -5
- package/dist/cli/hook.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +4 -2
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp.js +1 -1
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/start.d.ts.map +1 -1
- package/dist/cli/start.js +11 -3
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +15 -1
- package/dist/cli/status.js.map +1 -1
- package/dist/config.d.ts +71 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +76 -3
- package/dist/config.js.map +1 -1
- package/dist/detection/engine.d.ts +149 -0
- package/dist/detection/engine.d.ts.map +1 -0
- package/dist/detection/engine.js +0 -0
- package/dist/detection/engine.js.map +1 -0
- package/dist/detection/index.d.ts +3 -0
- package/dist/detection/index.d.ts.map +1 -0
- package/dist/detection/index.js +24 -0
- package/dist/detection/index.js.map +1 -0
- package/dist/detection/rules.d.ts +103 -0
- package/dist/detection/rules.d.ts.map +1 -0
- package/dist/detection/rules.js +586 -0
- package/dist/detection/rules.js.map +1 -0
- package/dist/hooks/claude-hook.d.ts +31 -4
- package/dist/hooks/claude-hook.d.ts.map +1 -1
- package/dist/hooks/claude-hook.js +131 -16
- package/dist/hooks/claude-hook.js.map +1 -1
- package/dist/hooks/hook-pause.d.ts +34 -0
- package/dist/hooks/hook-pause.d.ts.map +1 -0
- package/dist/hooks/hook-pause.js +111 -0
- package/dist/hooks/hook-pause.js.map +1 -0
- package/dist/hooks/pretooluse-policy.d.ts +34 -0
- package/dist/hooks/pretooluse-policy.d.ts.map +1 -0
- package/dist/hooks/pretooluse-policy.js +97 -0
- package/dist/hooks/pretooluse-policy.js.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/mask-rules-fetcher.d.ts +5 -0
- package/dist/mask-rules-fetcher.d.ts.map +1 -1
- package/dist/mask-rules-fetcher.js +9 -2
- package/dist/mask-rules-fetcher.js.map +1 -1
- package/dist/pii-masker.d.ts.map +1 -1
- package/dist/pii-masker.js.map +1 -1
- package/dist/secret-detector.d.ts +51 -27
- package/dist/secret-detector.d.ts.map +1 -1
- package/dist/secret-detector.js +108 -439
- package/dist/secret-detector.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/suppress-sea-warning.d.ts +0 -2
- package/dist/suppress-sea-warning.d.ts.map +0 -1
- package/dist/suppress-sea-warning.js +0 -21
- package/dist/suppress-sea-warning.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { SecretDetector, type DetectionMeta } from '../secret-detector';
|
|
1
|
+
import { SecretDetector, type DetectionContext, type DetectionMeta } from '../secret-detector';
|
|
2
|
+
import { type PreToolUsePolicy } from './pretooluse-policy';
|
|
2
3
|
/**
|
|
3
4
|
* 対応する hook イベント (全プラットフォームの和集合)。
|
|
4
5
|
* プラットフォーム別にどれを登録/受理するかは hooks/platforms.ts が定義する。
|
|
@@ -25,6 +26,11 @@ export interface HookInput {
|
|
|
25
26
|
* 値部分 (コマンド本文・プロンプト) のみを検知対象に集める。
|
|
26
27
|
*/
|
|
27
28
|
export declare function extractRiskText(event: HookEvent, input: HookInput): string;
|
|
29
|
+
/**
|
|
30
|
+
* tool_input から「作業対象のパス」を拾う。allowPaths の判定に使う。
|
|
31
|
+
* Bash のようにパスを持たないツールでは cwd だけが手掛かりになる。
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractTargetPaths(input: HookInput): string[];
|
|
28
34
|
/** PreToolUse の出力 (Claude Code hooks の hookSpecificOutput 形式)。 */
|
|
29
35
|
export interface PreToolUseDecision {
|
|
30
36
|
hookSpecificOutput: {
|
|
@@ -44,8 +50,13 @@ export interface UserPromptSubmitDecision {
|
|
|
44
50
|
}
|
|
45
51
|
export type HookDecisionOutput = PreToolUseDecision | UserPromptSubmitDecision;
|
|
46
52
|
/** 検知メタから日本語の deny 理由を組み立てる (PreToolUse=ツール実行ブロック)。 */
|
|
47
|
-
export declare function buildDenyReason(detections: DetectionMeta[]): string;
|
|
48
|
-
/**
|
|
53
|
+
export declare function buildDenyReason(detections: DetectionMeta[], contexts?: DetectionContext[]): string;
|
|
54
|
+
/**
|
|
55
|
+
* UserPromptSubmit の block 理由 (#205)。送信前にモデル到達を止めた旨を伝える。
|
|
56
|
+
*
|
|
57
|
+
* contexts は渡さない。こちらの入力はまだモデルに届いていないので、抜粋を理由文に
|
|
58
|
+
* 載せると block した当の内容をモデルへ流すことになる。
|
|
59
|
+
*/
|
|
49
60
|
export declare function buildPromptBlockReason(detections: DetectionMeta[]): string;
|
|
50
61
|
/** hook の評価オプション (#205: UserPromptSubmit の block 制御)。 */
|
|
51
62
|
export interface HookEvaluationOptions {
|
|
@@ -53,6 +64,10 @@ export interface HookEvaluationOptions {
|
|
|
53
64
|
blockOnPromptSubmit?: boolean;
|
|
54
65
|
/** block するしきい値 (この重大度以上)。既定 high。 */
|
|
55
66
|
blockPromptThreshold?: 'low' | 'medium' | 'high';
|
|
67
|
+
/** PreToolUse のブロック方針 (しきい値・除外)。既定は従来どおり high のみブロック。 */
|
|
68
|
+
preToolUse?: Partial<PreToolUsePolicy>;
|
|
69
|
+
/** 一時停止中か (disable-hooks)。true ならブロックしない。 */
|
|
70
|
+
paused?: boolean;
|
|
56
71
|
}
|
|
57
72
|
/** 評価結果。 */
|
|
58
73
|
export interface HookEvaluation {
|
|
@@ -64,13 +79,25 @@ export interface HookEvaluation {
|
|
|
64
79
|
output: HookDecisionOutput | null;
|
|
65
80
|
/** 終了コード。deny/block は exit 0 + JSON で制御 (exit 2 は非構造化 block)。 */
|
|
66
81
|
exitCode: 0 | 2;
|
|
82
|
+
/**
|
|
83
|
+
* ブロックを見送った理由。「なぜ通ったのか」をテスト・調査から確認するためのもの。
|
|
84
|
+
* - paused : disable-hooks による一時停止中
|
|
85
|
+
* - disabled : security.preToolUse.enabled = false
|
|
86
|
+
* - allowPath : 対象パスが allowPaths に一致
|
|
87
|
+
* - threshold : しきい値・disabledRules・allowStrings を適用した結果、対象が残らなかった
|
|
88
|
+
*/
|
|
89
|
+
suppressedBy?: 'paused' | 'disabled' | 'allowPath' | 'threshold';
|
|
67
90
|
}
|
|
68
91
|
/**
|
|
69
92
|
* hook イベントを評価する純粋関数。
|
|
70
|
-
* - PreToolUse:
|
|
93
|
+
* - PreToolUse: しきい値以上の検知で deny (ツール実行=exfiltration 防止)。
|
|
94
|
+
* 既定のしきい値は high。設定で引き上げ・ルール除外・パス除外・一時停止ができる。
|
|
71
95
|
* - UserPromptSubmit: opt-in (blockOnPromptSubmit) かつしきい値以上で block
|
|
72
96
|
* (貼り付け経路の leak-to-LLM 防止 #205)。既定 false なら観測のみ。
|
|
73
97
|
* - その他: 検知のみ付与 (ブロックはしない)。
|
|
98
|
+
*
|
|
99
|
+
* **除外はブロック判断だけに効く。** 検知メタは常に全件返し、記録・送信・マスクは
|
|
100
|
+
* 従来どおり行う。「見えなくする」のではなく「実行を止めない」だけにする。
|
|
74
101
|
*/
|
|
75
102
|
export declare function evaluateHook(event: HookEvent, input: HookInput, detector: SecretDetector, opts?: HookEvaluationOptions): HookEvaluation;
|
|
76
103
|
//# sourceMappingURL=claude-hook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hook.d.ts","sourceRoot":"","sources":["../../src/hooks/claude-hook.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"claude-hook.d.ts","sourceRoot":"","sources":["../../src/hooks/claude-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EAEd,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAA;AAc5B;;;;;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;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,CAW7D;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;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GAAG,wBAAwB,CAAA;AAqD9E,uDAAuD;AACvD,wBAAgB,eAAe,CAC7B,UAAU,EAAE,aAAa,EAAE,EAC3B,QAAQ,GAAE,gBAAgB,EAAO,GAChC,MAAM,CAQR;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,MAAM,CAS1E;AAiDD,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,sCAAsC;IACtC,oBAAoB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;IAChD,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACtC,6CAA6C;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,YAAY;AACZ,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,OAAO,EAAE,OAAO,CAAA;IAChB,gCAAgC;IAChC,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,yDAAyD;IACzD,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAA;IACjC,iEAAiE;IACjE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAA;CACjE;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,cAAc,EACxB,IAAI,GAAE,qBAA0B,GAC/B,cAAc,CAgDhB"}
|
|
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SUPPORTED_EVENTS = void 0;
|
|
4
4
|
exports.isHookEvent = isHookEvent;
|
|
5
5
|
exports.extractRiskText = extractRiskText;
|
|
6
|
+
exports.extractTargetPaths = extractTargetPaths;
|
|
6
7
|
exports.buildDenyReason = buildDenyReason;
|
|
7
8
|
exports.buildPromptBlockReason = buildPromptBlockReason;
|
|
8
9
|
exports.evaluateHook = evaluateHook;
|
|
9
10
|
const secret_detector_1 = require("../secret-detector");
|
|
11
|
+
const pretooluse_policy_1 = require("./pretooluse-policy");
|
|
10
12
|
// =============================================
|
|
11
13
|
// Claude Code hooks アダプタ (Issue #67 / Epic #66 P1) — 純粋ロジック
|
|
12
14
|
// =============================================
|
|
@@ -48,6 +50,24 @@ function extractRiskText(event, input) {
|
|
|
48
50
|
// Bash の command、Write/Edit の content 等が含まれる。
|
|
49
51
|
return (0, secret_detector_1.collectStrings)(input.tool_input ?? {});
|
|
50
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* tool_input から「作業対象のパス」を拾う。allowPaths の判定に使う。
|
|
55
|
+
* Bash のようにパスを持たないツールでは cwd だけが手掛かりになる。
|
|
56
|
+
*/
|
|
57
|
+
function extractTargetPaths(input) {
|
|
58
|
+
const t = input.tool_input;
|
|
59
|
+
const out = [];
|
|
60
|
+
if (t && typeof t === 'object') {
|
|
61
|
+
for (const key of ['file_path', 'notebook_path', 'path']) {
|
|
62
|
+
const v = t[key];
|
|
63
|
+
if (typeof v === 'string' && v)
|
|
64
|
+
out.push(v);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (typeof input.cwd === 'string' && input.cwd)
|
|
68
|
+
out.push(input.cwd);
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
51
71
|
const SEVERITY_LABEL = { high: '重大', medium: '中', low: '低' };
|
|
52
72
|
const CATEGORY_LABEL = {
|
|
53
73
|
secret: 'シークレット',
|
|
@@ -55,28 +75,69 @@ const CATEGORY_LABEL = {
|
|
|
55
75
|
pii_jp: '個人情報(日本)',
|
|
56
76
|
custom: '社内機密',
|
|
57
77
|
};
|
|
58
|
-
/**
|
|
59
|
-
|
|
78
|
+
/**
|
|
79
|
+
* 検知メタを「・カテゴリ / ルール (重大度, 件数, 例)」の行に整形 (生機密は出さない)。
|
|
80
|
+
* contexts があれば、その下に行番号とマスク済み抜粋・ルールの説明を添える。
|
|
81
|
+
*
|
|
82
|
+
* ルール ID とマスク済みプレビュー数文字だけでは、原因語が特定できない。
|
|
83
|
+
* 誤検知のとき利用者は二分探索で切り分ける羽目になるので、位置と抜粋を必ず出す。
|
|
84
|
+
*/
|
|
85
|
+
function detectionLines(detections, contexts = []) {
|
|
86
|
+
const byRule = new Map(contexts.map((c) => [c.ruleId, c]));
|
|
60
87
|
return [...detections]
|
|
61
88
|
.sort((a, b) => severityRank(b.severity) - severityRank(a.severity))
|
|
62
89
|
.slice(0, 5)
|
|
63
|
-
.map((d) =>
|
|
64
|
-
|
|
90
|
+
.map((d) => {
|
|
91
|
+
const head = `・${CATEGORY_LABEL[d.category] ?? d.category} / ${ruleLabel(d.ruleId)} [${d.ruleId}] ` +
|
|
92
|
+
`(重大度: ${SEVERITY_LABEL[d.severity] ?? d.severity}, ${d.count} 件, 例: ${d.maskedPreview})`;
|
|
93
|
+
const lines = [head];
|
|
94
|
+
const ctx = byRule.get(d.ruleId);
|
|
95
|
+
// 行番号はツール入力全体 (file_path + content など) を 1 本に繋いだものの
|
|
96
|
+
// 中での位置。ファイルの行番号とは一致しないので、そう分かる書き方にする。
|
|
97
|
+
if (ctx)
|
|
98
|
+
lines.push(` ツール入力の ${ctx.line} 行目: ${ctx.snippet}`);
|
|
99
|
+
const hint = RULE_HINT[d.ruleId];
|
|
100
|
+
if (hint)
|
|
101
|
+
lines.push(` 判定基準: ${hint}`);
|
|
102
|
+
return lines.join('\n');
|
|
103
|
+
})
|
|
65
104
|
.join('\n');
|
|
66
105
|
}
|
|
106
|
+
/** 誤検知だったときの逃げ道。ブロック理由の末尾に必ず添える。 */
|
|
107
|
+
function escapeHatchLines(ruleIds) {
|
|
108
|
+
const sample = ruleIds.length > 0 ? ruleIds : ['<ruleId>'];
|
|
109
|
+
const quoted = sample.map((r) => `"${r}"`).join(', ');
|
|
110
|
+
return [
|
|
111
|
+
'',
|
|
112
|
+
'誤検知の場合は、次のいずれかで回避できます (hook の登録を外す必要はありません):',
|
|
113
|
+
` 1. このルールを除外する — ~/.promptkaizen/agent.config.json の`,
|
|
114
|
+
` security.preToolUse.disabledRules に ${quoted} を追加`,
|
|
115
|
+
' 2. このリポジトリを除外する — security.preToolUse.allowPaths にパスの glob を追加',
|
|
116
|
+
' 3. 一時的に止める — promptkaizen-agent disable-hooks --pre-tool-use --duration 10m',
|
|
117
|
+
' (期限が来れば自動で元に戻ります)',
|
|
118
|
+
].join('\n');
|
|
119
|
+
}
|
|
67
120
|
/** 検知メタから日本語の deny 理由を組み立てる (PreToolUse=ツール実行ブロック)。 */
|
|
68
|
-
function buildDenyReason(detections) {
|
|
121
|
+
function buildDenyReason(detections, contexts = []) {
|
|
69
122
|
return ('PromptKaizen のポリシーにより、このツール実行をブロックしました。\n' +
|
|
70
123
|
'以下の機密情報が含まれています:\n' +
|
|
71
|
-
detectionLines(detections) +
|
|
72
|
-
'\n
|
|
124
|
+
detectionLines(detections, contexts) +
|
|
125
|
+
'\n\n機密値を削除するか、環境変数・シークレットマネージャ経由に変更してから再実行してください。\n' +
|
|
126
|
+
escapeHatchLines(detections.map((d) => d.ruleId)));
|
|
73
127
|
}
|
|
74
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* UserPromptSubmit の block 理由 (#205)。送信前にモデル到達を止めた旨を伝える。
|
|
130
|
+
*
|
|
131
|
+
* contexts は渡さない。こちらの入力はまだモデルに届いていないので、抜粋を理由文に
|
|
132
|
+
* 載せると block した当の内容をモデルへ流すことになる。
|
|
133
|
+
*/
|
|
75
134
|
function buildPromptBlockReason(detections) {
|
|
76
135
|
return ('PromptKaizen のポリシーにより、このプロンプトの送信をブロックしました。\n' +
|
|
77
136
|
'機密情報がモデルに送信される前に停止しました:\n' +
|
|
78
137
|
detectionLines(detections) +
|
|
79
|
-
'\n
|
|
138
|
+
'\n\n機密値を削除するか、環境変数・シークレットマネージャ経由に変更してから送信し直してください。\n' +
|
|
139
|
+
'\n誤検知の場合は ~/.promptkaizen/agent.config.json の security.blockPromptThreshold を上げるか、' +
|
|
140
|
+
'security.blockOnPromptSubmit を false にしてください。');
|
|
80
141
|
}
|
|
81
142
|
function severityRank(s) {
|
|
82
143
|
return s === 'high' ? 2 : s === 'medium' ? 1 : 0;
|
|
@@ -99,29 +160,55 @@ const RULE_LABEL = {
|
|
|
99
160
|
jp_address: '住所',
|
|
100
161
|
credit_card: 'クレジットカード番号',
|
|
101
162
|
email: 'メールアドレス',
|
|
163
|
+
generic_credential: '汎用クレデンシャル (ラベル付きの値)',
|
|
164
|
+
jp_bank_account: '銀行口座番号',
|
|
165
|
+
jp_bank_branch: '金融機関名・支店名',
|
|
166
|
+
jp_account_holder: '口座名義',
|
|
167
|
+
jp_person_name: '人名 (ラベル判定)',
|
|
168
|
+
jp_person_name_honorific: '人名 (敬称判定)',
|
|
169
|
+
jp_wareki_date: '和暦の日付',
|
|
102
170
|
};
|
|
103
171
|
function ruleLabel(id) {
|
|
104
172
|
return RULE_LABEL[id] ?? id;
|
|
105
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* ルールごとの「誤検知しやすい形」。ブロック理由に添える。
|
|
176
|
+
* ルール ID だけ出しても、利用者にはそれが何を見ているのか分からない。
|
|
177
|
+
*/
|
|
178
|
+
const RULE_HINT = {
|
|
179
|
+
generic_credential: 'password / secret / token 等のラベルの直後にある値を機密とみなします。ソースコードの変数名が該当することがあります。',
|
|
180
|
+
jp_person_name: '担当者・氏名などのラベルの直後を人名とみなします。',
|
|
181
|
+
jp_person_name_honorific: '様・さん・部長などの敬称の直前を人名とみなします。',
|
|
182
|
+
high_entropy: 'ランダムに見える 20 文字以上の文字列を機密とみなします。ハッシュ値や ID が該当することがあります。',
|
|
183
|
+
jp_bank_branch: '「〜銀行」「〜信用金庫」の形を金融機関名とみなします。',
|
|
184
|
+
};
|
|
106
185
|
/** severity が threshold 以上か (high>=high のみ true 等)。 */
|
|
107
186
|
function meetsThreshold(severity, threshold) {
|
|
108
187
|
return severityRank(severity) >= severityRank(threshold);
|
|
109
188
|
}
|
|
110
189
|
/**
|
|
111
190
|
* hook イベントを評価する純粋関数。
|
|
112
|
-
* - PreToolUse:
|
|
191
|
+
* - PreToolUse: しきい値以上の検知で deny (ツール実行=exfiltration 防止)。
|
|
192
|
+
* 既定のしきい値は high。設定で引き上げ・ルール除外・パス除外・一時停止ができる。
|
|
113
193
|
* - UserPromptSubmit: opt-in (blockOnPromptSubmit) かつしきい値以上で block
|
|
114
194
|
* (貼り付け経路の leak-to-LLM 防止 #205)。既定 false なら観測のみ。
|
|
115
195
|
* - その他: 検知のみ付与 (ブロックはしない)。
|
|
196
|
+
*
|
|
197
|
+
* **除外はブロック判断だけに効く。** 検知メタは常に全件返し、記録・送信・マスクは
|
|
198
|
+
* 従来どおり行う。「見えなくする」のではなく「実行を止めない」だけにする。
|
|
116
199
|
*/
|
|
117
200
|
function evaluateHook(event, input, detector, opts = {}) {
|
|
118
201
|
const text = extractRiskText(event, input);
|
|
119
|
-
const detections = text ? detector.detect(text) : [];
|
|
120
|
-
// PreToolUse の deny は無条件ブロックなので誤検知の影響が大きい。
|
|
121
|
-
// 重大度 high (重大) のみをブロック対象とし、medium/low は観測のみ
|
|
122
|
-
// (記録・送信は全件残す) に留めて通常の開発作業を妨げない。
|
|
123
202
|
if (event === 'PreToolUse') {
|
|
124
|
-
const
|
|
203
|
+
const policy = { ...pretooluse_policy_1.DEFAULT_PRE_TOOL_USE_POLICY, ...(opts.preToolUse ?? {}) };
|
|
204
|
+
// 検知メタは除外前のテキストから作る (記録・送信は従来どおり全件)。
|
|
205
|
+
const { detections, contexts } = text
|
|
206
|
+
? detector.detectWithContext(text)
|
|
207
|
+
: { detections: [], contexts: [] };
|
|
208
|
+
const suppressed = preToolUseSuppression(input, detections, policy, opts.paused === true);
|
|
209
|
+
if (suppressed)
|
|
210
|
+
return { blocked: false, detections, output: null, exitCode: 0, suppressedBy: suppressed };
|
|
211
|
+
const blocking = blockingDetections(text, detector, detections, policy);
|
|
125
212
|
if (blocking.length > 0) {
|
|
126
213
|
return {
|
|
127
214
|
blocked: true,
|
|
@@ -130,13 +217,15 @@ function evaluateHook(event, input, detector, opts = {}) {
|
|
|
130
217
|
hookSpecificOutput: {
|
|
131
218
|
hookEventName: 'PreToolUse',
|
|
132
219
|
permissionDecision: 'deny',
|
|
133
|
-
permissionDecisionReason: buildDenyReason(blocking),
|
|
220
|
+
permissionDecisionReason: buildDenyReason(blocking, contexts),
|
|
134
221
|
},
|
|
135
222
|
},
|
|
136
223
|
exitCode: 0,
|
|
137
224
|
};
|
|
138
225
|
}
|
|
226
|
+
return { blocked: false, detections, output: null, exitCode: 0, suppressedBy: 'threshold' };
|
|
139
227
|
}
|
|
228
|
+
const detections = text ? detector.detect(text) : [];
|
|
140
229
|
// UserPromptSubmit の block (#205, opt-in)。貼り付けた機密がモデルへ到達する前に止める。
|
|
141
230
|
if (event === 'UserPromptSubmit' && opts.blockOnPromptSubmit) {
|
|
142
231
|
const threshold = opts.blockPromptThreshold ?? 'high';
|
|
@@ -152,4 +241,30 @@ function evaluateHook(event, input, detector, opts = {}) {
|
|
|
152
241
|
}
|
|
153
242
|
return { blocked: false, detections, output: null, exitCode: 0 };
|
|
154
243
|
}
|
|
244
|
+
/** 検知の中身によらずブロック自体を見送る条件 (一時停止・方針オフ・パス除外)。 */
|
|
245
|
+
function preToolUseSuppression(input, detections, policy, paused) {
|
|
246
|
+
if (detections.length === 0)
|
|
247
|
+
return null;
|
|
248
|
+
if (paused)
|
|
249
|
+
return 'paused';
|
|
250
|
+
if (!policy.enabled)
|
|
251
|
+
return 'disabled';
|
|
252
|
+
if ((0, pretooluse_policy_1.matchesAllowPaths)(extractTargetPaths(input), policy.allowPaths))
|
|
253
|
+
return 'allowPath';
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* ブロック対象の検知を選ぶ。
|
|
258
|
+
* allowStrings は検知メタからは判定できない (生値を保持していない) ので、
|
|
259
|
+
* 除外後のテキストで検知をやり直し、そこに残ったルールだけをブロック対象にする。
|
|
260
|
+
*/
|
|
261
|
+
function blockingDetections(text, detector, detections, policy) {
|
|
262
|
+
let candidates = detections.filter((d) => (0, pretooluse_policy_1.meetsSeverityThreshold)(d.severity, policy.threshold) && !policy.disabledRules.includes(d.ruleId));
|
|
263
|
+
if (candidates.length > 0 && policy.allowStrings.length > 0) {
|
|
264
|
+
const stripped = (0, pretooluse_policy_1.stripAllowStrings)(text, policy.allowStrings);
|
|
265
|
+
const remaining = new Set(detector.detect(stripped).map((d) => d.ruleId));
|
|
266
|
+
candidates = candidates.filter((d) => remaining.has(d.ruleId));
|
|
267
|
+
}
|
|
268
|
+
return candidates;
|
|
269
|
+
}
|
|
155
270
|
//# sourceMappingURL=claude-hook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-hook.js","sourceRoot":"","sources":["../../src/hooks/claude-hook.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"claude-hook.js","sourceRoot":"","sources":["../../src/hooks/claude-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** 停止できる範囲。 */
|
|
2
|
+
export type HookPauseScope = 'preToolUse' | 'promptSubmit';
|
|
3
|
+
export declare const HOOK_PAUSE_SCOPES: readonly HookPauseScope[];
|
|
4
|
+
/** 一時停止の上限。これ以上長い停止は「無効化」であって一時停止ではない。 */
|
|
5
|
+
export declare const MAX_PAUSE_MS: number;
|
|
6
|
+
export interface HookPause {
|
|
7
|
+
/** 停止する範囲。 */
|
|
8
|
+
scopes: HookPauseScope[];
|
|
9
|
+
/** 失効時刻 (ISO8601)。これを過ぎたら自動的に無効。 */
|
|
10
|
+
until: string;
|
|
11
|
+
/** 指定時はこのディレクトリ配下でのみ停止する。null なら全体。 */
|
|
12
|
+
cwd: string | null;
|
|
13
|
+
createdAt: string;
|
|
14
|
+
/** 任意のメモ (なぜ止めたか)。 */
|
|
15
|
+
reason?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function hookPausePath(): string;
|
|
18
|
+
/**
|
|
19
|
+
* 期間指定のパース。`30s` / `10m` / `2h` を受け取る。単位なしは分とみなす。
|
|
20
|
+
* 上限は MAX_PAUSE_MS。不正な入力は null。
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseDuration(input: string): number | null;
|
|
23
|
+
/** 残り時間を「あと N 分」の形に整える。 */
|
|
24
|
+
export declare function formatRemaining(until: string, now?: number): string;
|
|
25
|
+
/**
|
|
26
|
+
* 停止設定を読む。存在しない・壊れている・期限切れなら null
|
|
27
|
+
* (= 停止していない)。hook から毎回呼ばれるので失敗は必ず握りつぶす。
|
|
28
|
+
*/
|
|
29
|
+
export declare function readHookPause(now?: number, filePath?: string): Promise<HookPause | null>;
|
|
30
|
+
export declare function writeHookPause(pause: HookPause, filePath?: string): Promise<void>;
|
|
31
|
+
export declare function clearHookPause(filePath?: string): Promise<boolean>;
|
|
32
|
+
/** この scope / cwd でブロックを止めるべきか。 */
|
|
33
|
+
export declare function isPaused(pause: HookPause | null, scope: HookPauseScope, cwd: string | null): boolean;
|
|
34
|
+
//# sourceMappingURL=hook-pause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-pause.d.ts","sourceRoot":"","sources":["../../src/hooks/hook-pause.ts"],"names":[],"mappings":"AAqBA,eAAe;AACf,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,cAAc,CAAA;AAE1D,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAAmC,CAAA;AAE1F,0CAA0C;AAC1C,eAAO,MAAM,YAAY,QAAsB,CAAA;AAE/C,MAAM,WAAW,SAAS;IACxB,cAAc;IACd,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU1D;AAED,2BAA2B;AAC3B,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAM/E;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,GAAG,GAAE,MAAmB,EACxB,QAAQ,GAAE,MAAwB,GACjC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAyB3B;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,SAAS,EAChB,QAAQ,GAAE,MAAwB,GACjC,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,cAAc,CAAC,QAAQ,GAAE,MAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAOzF;AAED,mCAAmC;AACnC,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,KAAK,EAAE,cAAc,EACrB,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAQT"}
|
|
@@ -0,0 +1,111 @@
|
|
|
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.MAX_PAUSE_MS = exports.HOOK_PAUSE_SCOPES = void 0;
|
|
7
|
+
exports.hookPausePath = hookPausePath;
|
|
8
|
+
exports.parseDuration = parseDuration;
|
|
9
|
+
exports.formatRemaining = formatRemaining;
|
|
10
|
+
exports.readHookPause = readHookPause;
|
|
11
|
+
exports.writeHookPause = writeHookPause;
|
|
12
|
+
exports.clearHookPause = clearHookPause;
|
|
13
|
+
exports.isPaused = isPaused;
|
|
14
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
15
|
+
const os_1 = __importDefault(require("os"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
exports.HOOK_PAUSE_SCOPES = ['preToolUse', 'promptSubmit'];
|
|
18
|
+
/** 一時停止の上限。これ以上長い停止は「無効化」であって一時停止ではない。 */
|
|
19
|
+
exports.MAX_PAUSE_MS = 24 * 60 * 60 * 1000;
|
|
20
|
+
function hookPausePath() {
|
|
21
|
+
return path_1.default.join(os_1.default.homedir(), '.promptkaizen', 'hook-pause.json');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 期間指定のパース。`30s` / `10m` / `2h` を受け取る。単位なしは分とみなす。
|
|
25
|
+
* 上限は MAX_PAUSE_MS。不正な入力は null。
|
|
26
|
+
*/
|
|
27
|
+
function parseDuration(input) {
|
|
28
|
+
const m = /^(\d+(?:\.\d+)?)\s*(s|sec|secs|m|min|mins|h|hr|hrs)?$/i.exec(input.trim());
|
|
29
|
+
if (!m)
|
|
30
|
+
return null;
|
|
31
|
+
const value = Number(m[1]);
|
|
32
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
33
|
+
return null;
|
|
34
|
+
const unit = (m[2] ?? 'm').toLowerCase();
|
|
35
|
+
const factor = unit.startsWith('s') ? 1000 : unit.startsWith('h') ? 3_600_000 : 60_000;
|
|
36
|
+
const ms = Math.round(value * factor);
|
|
37
|
+
if (ms > exports.MAX_PAUSE_MS)
|
|
38
|
+
return null;
|
|
39
|
+
return ms;
|
|
40
|
+
}
|
|
41
|
+
/** 残り時間を「あと N 分」の形に整える。 */
|
|
42
|
+
function formatRemaining(until, now = Date.now()) {
|
|
43
|
+
const left = new Date(until).getTime() - now;
|
|
44
|
+
if (!Number.isFinite(left) || left <= 0)
|
|
45
|
+
return '期限切れ';
|
|
46
|
+
const mins = Math.ceil(left / 60_000);
|
|
47
|
+
if (mins < 60)
|
|
48
|
+
return `あと約 ${mins} 分`;
|
|
49
|
+
return `あと約 ${Math.round((mins / 60) * 10) / 10} 時間`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 停止設定を読む。存在しない・壊れている・期限切れなら null
|
|
53
|
+
* (= 停止していない)。hook から毎回呼ばれるので失敗は必ず握りつぶす。
|
|
54
|
+
*/
|
|
55
|
+
async function readHookPause(now = Date.now(), filePath = hookPausePath()) {
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = JSON.parse(await promises_1.default.readFile(filePath, 'utf8'));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (!parsed || typeof parsed !== 'object')
|
|
64
|
+
return null;
|
|
65
|
+
const p = parsed;
|
|
66
|
+
if (typeof p.until !== 'string')
|
|
67
|
+
return null;
|
|
68
|
+
const until = new Date(p.until).getTime();
|
|
69
|
+
if (!Number.isFinite(until) || until <= now)
|
|
70
|
+
return null;
|
|
71
|
+
const scopes = Array.isArray(p.scopes)
|
|
72
|
+
? p.scopes.filter((s) => exports.HOOK_PAUSE_SCOPES.includes(s))
|
|
73
|
+
: [];
|
|
74
|
+
if (scopes.length === 0)
|
|
75
|
+
return null;
|
|
76
|
+
return {
|
|
77
|
+
scopes,
|
|
78
|
+
until: p.until,
|
|
79
|
+
cwd: typeof p.cwd === 'string' && p.cwd ? p.cwd : null,
|
|
80
|
+
createdAt: typeof p.createdAt === 'string' ? p.createdAt : new Date(now).toISOString(),
|
|
81
|
+
reason: typeof p.reason === 'string' ? p.reason : undefined,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function writeHookPause(pause, filePath = hookPausePath()) {
|
|
85
|
+
await promises_1.default.mkdir(path_1.default.dirname(filePath), { recursive: true });
|
|
86
|
+
await promises_1.default.writeFile(filePath, JSON.stringify(pause, null, 2) + '\n', { mode: 0o600 });
|
|
87
|
+
}
|
|
88
|
+
async function clearHookPause(filePath = hookPausePath()) {
|
|
89
|
+
try {
|
|
90
|
+
await promises_1.default.unlink(filePath);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** この scope / cwd でブロックを止めるべきか。 */
|
|
98
|
+
function isPaused(pause, scope, cwd) {
|
|
99
|
+
if (!pause)
|
|
100
|
+
return false;
|
|
101
|
+
if (!pause.scopes.includes(scope))
|
|
102
|
+
return false;
|
|
103
|
+
if (!pause.cwd)
|
|
104
|
+
return true;
|
|
105
|
+
if (!cwd)
|
|
106
|
+
return false;
|
|
107
|
+
const base = path_1.default.resolve(pause.cwd);
|
|
108
|
+
const target = path_1.default.resolve(cwd);
|
|
109
|
+
return target === base || target.startsWith(base + path_1.default.sep);
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=hook-pause.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-pause.js","sourceRoot":"","sources":["../../src/hooks/hook-pause.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DetectionSeverity } from '../secret-detector';
|
|
2
|
+
export interface PreToolUsePolicy {
|
|
3
|
+
/** false ならブロックしない (検知・記録は続ける)。 */
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
/** この重大度以上のみブロックする。 */
|
|
6
|
+
threshold: DetectionSeverity;
|
|
7
|
+
/** ブロック対象から外すルール ID。 */
|
|
8
|
+
disabledRules: string[];
|
|
9
|
+
/** ここに一致するパス配下ではブロックしない (glob、~ 展開あり)。 */
|
|
10
|
+
allowPaths: string[];
|
|
11
|
+
/** 検知対象から外す文字列 (完全一致の部分文字列)。 */
|
|
12
|
+
allowStrings: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare const DEFAULT_PRE_TOOL_USE_POLICY: PreToolUsePolicy;
|
|
15
|
+
/** severity が threshold 以上か。 */
|
|
16
|
+
export declare function meetsSeverityThreshold(severity: string, threshold: string): boolean;
|
|
17
|
+
/** 先頭の ~ をホームディレクトリに展開する。 */
|
|
18
|
+
export declare function expandHome(p: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* glob → RegExp。`**` は区切りをまたぐ、`*` はまたがない、`?` は 1 文字。
|
|
21
|
+
* 依存を増やさないための最小実装 (config.exclude と同じ方針)。
|
|
22
|
+
*/
|
|
23
|
+
export declare function globToRegExp(pattern: string): RegExp;
|
|
24
|
+
/** パスのいずれかが allowPaths に一致するか。 */
|
|
25
|
+
export declare function matchesAllowPaths(paths: Array<string | null | undefined>, allow: string[]): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* allowStrings を検知対象テキストから取り除く。
|
|
28
|
+
*
|
|
29
|
+
* 検知メタには生の値が残らないので、「この文字列は無視」をメタ側で判定することは
|
|
30
|
+
* できない。除外はテキストを渡す前に行う必要がある。ブロック判定用のテキストだけに
|
|
31
|
+
* 適用し、観測 (PostToolUse) 側の検知・マスクには影響させない。
|
|
32
|
+
*/
|
|
33
|
+
export declare function stripAllowStrings(text: string, allowStrings: string[]): string;
|
|
34
|
+
//# sourceMappingURL=pretooluse-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pretooluse-policy.d.ts","sourceRoot":"","sources":["../../src/hooks/pretooluse-policy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAc3D,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,uBAAuB;IACvB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,wBAAwB;IACxB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,gCAAgC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,eAAO,MAAM,2BAA2B,EAAE,gBAMzC,CAAA;AAID,gCAAgC;AAChC,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEnF;AAED,6BAA6B;AAC7B,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA0BpD;AAED,kCAAkC;AAClC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAQnG;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAO9E"}
|
|
@@ -0,0 +1,97 @@
|
|
|
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.DEFAULT_PRE_TOOL_USE_POLICY = void 0;
|
|
7
|
+
exports.meetsSeverityThreshold = meetsSeverityThreshold;
|
|
8
|
+
exports.expandHome = expandHome;
|
|
9
|
+
exports.globToRegExp = globToRegExp;
|
|
10
|
+
exports.matchesAllowPaths = matchesAllowPaths;
|
|
11
|
+
exports.stripAllowStrings = stripAllowStrings;
|
|
12
|
+
const os_1 = __importDefault(require("os"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
exports.DEFAULT_PRE_TOOL_USE_POLICY = {
|
|
15
|
+
enabled: true,
|
|
16
|
+
threshold: 'high',
|
|
17
|
+
disabledRules: [],
|
|
18
|
+
allowPaths: [],
|
|
19
|
+
allowStrings: [],
|
|
20
|
+
};
|
|
21
|
+
const SEVERITY_RANK = { high: 2, medium: 1, low: 0 };
|
|
22
|
+
/** severity が threshold 以上か。 */
|
|
23
|
+
function meetsSeverityThreshold(severity, threshold) {
|
|
24
|
+
return (SEVERITY_RANK[severity] ?? 0) >= (SEVERITY_RANK[threshold] ?? 2);
|
|
25
|
+
}
|
|
26
|
+
/** 先頭の ~ をホームディレクトリに展開する。 */
|
|
27
|
+
function expandHome(p) {
|
|
28
|
+
if (p === '~')
|
|
29
|
+
return os_1.default.homedir();
|
|
30
|
+
if (p.startsWith('~/') || p.startsWith('~\\'))
|
|
31
|
+
return path_1.default.join(os_1.default.homedir(), p.slice(2));
|
|
32
|
+
return p;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* glob → RegExp。`**` は区切りをまたぐ、`*` はまたがない、`?` は 1 文字。
|
|
36
|
+
* 依存を増やさないための最小実装 (config.exclude と同じ方針)。
|
|
37
|
+
*/
|
|
38
|
+
function globToRegExp(pattern) {
|
|
39
|
+
const normalized = expandHome(pattern).replace(/\\/g, '/');
|
|
40
|
+
let out = '';
|
|
41
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
42
|
+
const c = normalized[i];
|
|
43
|
+
if (c === '*') {
|
|
44
|
+
if (normalized[i + 1] === '*') {
|
|
45
|
+
// `**/` は「0 階層以上」。`a/**/b` が `a/b` にも当たるようにする。
|
|
46
|
+
if (normalized[i + 2] === '/') {
|
|
47
|
+
out += '(?:.*/)?';
|
|
48
|
+
i += 2;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
out += '.*';
|
|
52
|
+
i += 1;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
out += '[^/]*';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (c === '?') {
|
|
60
|
+
out += '[^/]';
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
out += c.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// ディレクトリ指定 (末尾 / なし) はその配下も含める。
|
|
67
|
+
return new RegExp(`^${out}(?:/.*)?$`, process.platform === 'win32' ? 'i' : '');
|
|
68
|
+
}
|
|
69
|
+
/** パスのいずれかが allowPaths に一致するか。 */
|
|
70
|
+
function matchesAllowPaths(paths, allow) {
|
|
71
|
+
if (allow.length === 0)
|
|
72
|
+
return false;
|
|
73
|
+
const regexes = allow.map(globToRegExp);
|
|
74
|
+
return paths.some((p) => {
|
|
75
|
+
if (!p)
|
|
76
|
+
return false;
|
|
77
|
+
const normalized = path_1.default.resolve(p).replace(/\\/g, '/');
|
|
78
|
+
return regexes.some((re) => re.test(normalized));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* allowStrings を検知対象テキストから取り除く。
|
|
83
|
+
*
|
|
84
|
+
* 検知メタには生の値が残らないので、「この文字列は無視」をメタ側で判定することは
|
|
85
|
+
* できない。除外はテキストを渡す前に行う必要がある。ブロック判定用のテキストだけに
|
|
86
|
+
* 適用し、観測 (PostToolUse) 側の検知・マスクには影響させない。
|
|
87
|
+
*/
|
|
88
|
+
function stripAllowStrings(text, allowStrings) {
|
|
89
|
+
let out = text;
|
|
90
|
+
for (const s of allowStrings) {
|
|
91
|
+
if (!s)
|
|
92
|
+
continue;
|
|
93
|
+
out = out.split(s).join(' ');
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=pretooluse-policy.js.map
|