@guilz-dev/belay 0.10.0 → 0.10.1
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/dist/adapters/claude/runtime-entry.js +5 -18
- package/dist/adapters/codex/runtime-entry.js +10 -11
- package/dist/adapters/cursor/hook-router.d.ts +1 -0
- package/dist/adapters/cursor/hook-router.js +26 -3
- package/dist/adapters/cursor/hook-routing-health.d.ts +1 -0
- package/dist/adapters/cursor/hook-routing-health.js +53 -0
- package/dist/adapters/shared/gate-runtime.d.ts +0 -2
- package/dist/adapters/shared/gate-runtime.js +2 -53
- package/dist/bundle/claude-runtime.mjs +446 -196
- package/dist/bundle/codex-runtime.mjs +449 -219
- package/dist/bundle/cursor-dispatcher.mjs +20 -3
- package/dist/bundle/cursor-runtime.mjs +441 -178
- package/dist/commands/doctor.js +4 -0
- package/dist/core/capability/index.d.ts +1 -1
- package/dist/core/capability/index.js +1 -1
- package/dist/core/capability/policy-engine.d.ts +19 -0
- package/dist/core/capability/policy-engine.js +31 -0
- package/dist/core/classify-tool.js +372 -148
- package/dist/core/config.js +2 -2
- package/dist/core/gate-engine.js +2 -9
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1847,7 +1847,7 @@ function normalizeConfig(config) {
|
|
|
1847
1847
|
policy: {
|
|
1848
1848
|
unknownLocalEffect: v4.policy?.unknownLocalEffect === "deny" ? "deny" : v4.policy?.unknownLocalEffect === "allow_flagged" ? "allow_flagged" : DEFAULT_POLICY_V3.unknownLocalEffect,
|
|
1849
1849
|
unparseableShell: v4.policy?.unparseableShell === "deny" ? "deny" : v4.policy?.unparseableShell === "allow_flagged" ? "allow_flagged" : DEFAULT_POLICY_V3.unparseableShell,
|
|
1850
|
-
codexUnmappedTool:
|
|
1850
|
+
codexUnmappedTool: "allow",
|
|
1851
1851
|
fenceWarnThreshold: typeof v4.policy?.fenceWarnThreshold === "number" && v4.policy.fenceWarnThreshold > 0 && v4.policy.fenceWarnThreshold <= 1 ? v4.policy.fenceWarnThreshold : DEFAULT_FENCE_WARN_THRESHOLD,
|
|
1852
1852
|
confidenceThresholds: {
|
|
1853
1853
|
allow: typeof v4.policy?.confidenceThresholds?.allow === "number" ? v4.policy.confidenceThresholds.allow : DEFAULT_CONFIDENCE_THRESHOLDS.allow,
|
|
@@ -2149,7 +2149,7 @@ var init_config = __esm({
|
|
|
2149
2149
|
DEFAULT_POLICY_V3 = {
|
|
2150
2150
|
unknownLocalEffect: "allow_flagged",
|
|
2151
2151
|
unparseableShell: "deny",
|
|
2152
|
-
codexUnmappedTool: "
|
|
2152
|
+
codexUnmappedTool: "allow",
|
|
2153
2153
|
confidenceThresholds: { ...DEFAULT_CONFIDENCE_THRESHOLDS },
|
|
2154
2154
|
modelAssist: { ...DEFAULT_MODEL_ASSIST },
|
|
2155
2155
|
transactional: { ...DEFAULT_TRANSACTIONAL_V3 },
|
|
@@ -10874,6 +10874,40 @@ function evaluateFileMutationPolicy(analysis, config, auth) {
|
|
|
10874
10874
|
);
|
|
10875
10875
|
return { request, decision };
|
|
10876
10876
|
}
|
|
10877
|
+
function buildFileReadCapabilityRequest(analysis) {
|
|
10878
|
+
return {
|
|
10879
|
+
version: CAPABILITY_REQUEST_VERSION,
|
|
10880
|
+
principal: {
|
|
10881
|
+
adapter: analysis.adapter,
|
|
10882
|
+
repoRoot: analysis.repoRoot,
|
|
10883
|
+
sessionHash: hashSession(`${analysis.repoRoot}:${analysis.cwd}`)
|
|
10884
|
+
},
|
|
10885
|
+
action: "fs.read",
|
|
10886
|
+
resource: { kind: "path", path: analysis.resolvedPath },
|
|
10887
|
+
context: {
|
|
10888
|
+
cwd: analysis.cwd,
|
|
10889
|
+
inputFingerprint: analysis.inputFingerprint,
|
|
10890
|
+
hookKind: analysis.hookKind,
|
|
10891
|
+
analysisBasis: [`tool:${analysis.toolKind}`, `location:${analysis.locationLabel}`, "read"]
|
|
10892
|
+
},
|
|
10893
|
+
evidence: {
|
|
10894
|
+
level: analysis.locationLabel === "repo_local" ? "certain" : "possible",
|
|
10895
|
+
signals: [...analysis.signals, "effect.fs_read"]
|
|
10896
|
+
}
|
|
10897
|
+
};
|
|
10898
|
+
}
|
|
10899
|
+
function evaluateFileReadPolicy(analysis, config, auth) {
|
|
10900
|
+
const request = buildFileReadCapabilityRequest(analysis);
|
|
10901
|
+
const enriched = enrichAuthWithMaterializedGrants(request, config, {
|
|
10902
|
+
...auth,
|
|
10903
|
+
sensitivePaths: auth?.sensitivePaths ?? analysis.sensitivePaths
|
|
10904
|
+
});
|
|
10905
|
+
const decision = getDefaultPolicyEngine().evaluate(
|
|
10906
|
+
request,
|
|
10907
|
+
buildAuthorizationContext(config, analysis.trustedWorkspaceRoots, enriched)
|
|
10908
|
+
);
|
|
10909
|
+
return { request, decision };
|
|
10910
|
+
}
|
|
10877
10911
|
|
|
10878
10912
|
// src/core/capability/reasons.ts
|
|
10879
10913
|
var FS_SCOPE_REASONS = /* @__PURE__ */ new Set(["outside_repo_mutation", "outside_repo_redirect"]);
|
|
@@ -17144,17 +17178,41 @@ function verdictToClassifyResult(result, config, options = {}) {
|
|
|
17144
17178
|
|
|
17145
17179
|
// src/core/classify-tool.ts
|
|
17146
17180
|
var DEFAULT_SENSITIVE_PATHS = [".env", ".env.*", "**/credentials/**"];
|
|
17147
|
-
|
|
17148
|
-
|
|
17149
|
-
"
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
|
|
17181
|
+
function toolInputRecord(payload) {
|
|
17182
|
+
const toolInput = payload.tool_input;
|
|
17183
|
+
if (!toolInput || typeof toolInput !== "object" || Array.isArray(toolInput)) {
|
|
17184
|
+
return null;
|
|
17185
|
+
}
|
|
17186
|
+
return toolInput;
|
|
17187
|
+
}
|
|
17188
|
+
function hasMutationFields(input) {
|
|
17189
|
+
return typeof input.contents === "string" || typeof input.old_string === "string" || typeof input.new_string === "string" || typeof input.newContents === "string";
|
|
17190
|
+
}
|
|
17191
|
+
function inferToolPayloadEffect(payload, toolName) {
|
|
17192
|
+
if (extractShellCommand(payload)) {
|
|
17193
|
+
return "shell";
|
|
17194
|
+
}
|
|
17195
|
+
const input = toolInputRecord(payload);
|
|
17196
|
+
if (!input) {
|
|
17197
|
+
return "indeterminate";
|
|
17198
|
+
}
|
|
17199
|
+
if (hasMutationFields(input)) {
|
|
17200
|
+
return "file_mutation";
|
|
17201
|
+
}
|
|
17202
|
+
if (extractPatch(payload)) {
|
|
17203
|
+
return "apply_patch";
|
|
17204
|
+
}
|
|
17205
|
+
if (typeof input.pattern === "string" || typeof input.glob_pattern === "string") {
|
|
17206
|
+
return "search_read";
|
|
17207
|
+
}
|
|
17208
|
+
if (typeof input.file_path === "string") {
|
|
17209
|
+
return "file_read";
|
|
17210
|
+
}
|
|
17211
|
+
if (typeof input.path === "string" || typeof input.target_file === "string") {
|
|
17212
|
+
return normalizedToolName(toolName) === "delete" ? "file_delete" : "indeterminate";
|
|
17213
|
+
}
|
|
17214
|
+
return "indeterminate";
|
|
17215
|
+
}
|
|
17158
17216
|
function policyAuth(options) {
|
|
17159
17217
|
if (!options.grants && options.attestation === void 0 && options.egressProxyActive === void 0) {
|
|
17160
17218
|
return void 0;
|
|
@@ -17334,6 +17392,314 @@ function classifyFileMutationWithPolicy(params) {
|
|
|
17334
17392
|
boundaryProfile: params.options.boundaryProfile ?? BOUNDARY_PROFILE_L3_L4_ONLY
|
|
17335
17393
|
};
|
|
17336
17394
|
}
|
|
17395
|
+
function classifyFileReadWithPolicy(params) {
|
|
17396
|
+
const fingerprint = toolFingerprint(params.toolName, { path: params.filePath }, params.repoRoot);
|
|
17397
|
+
const { request, decision } = evaluateFileReadPolicy(
|
|
17398
|
+
{
|
|
17399
|
+
hookKind: "tool",
|
|
17400
|
+
toolKind: params.toolKind,
|
|
17401
|
+
filePath: params.filePath,
|
|
17402
|
+
resolvedPath: params.resolvedPath,
|
|
17403
|
+
repoRoot: params.repoRoot,
|
|
17404
|
+
cwd: params.cwd,
|
|
17405
|
+
inputFingerprint: fingerprint,
|
|
17406
|
+
signals: params.signals,
|
|
17407
|
+
locationLabel: params.locationLabel,
|
|
17408
|
+
trustedWorkspaceRoots: params.options.trustedWorkspaceRoots,
|
|
17409
|
+
sensitivePaths: params.options.sensitivePaths ?? params.config.classifier.sensitivePaths
|
|
17410
|
+
},
|
|
17411
|
+
params.config,
|
|
17412
|
+
policyAuth(params.options)
|
|
17413
|
+
);
|
|
17414
|
+
if (policyDecisionRequiresAsk(decision)) {
|
|
17415
|
+
return {
|
|
17416
|
+
verdict: "deny_pending_approval",
|
|
17417
|
+
reason: policyReasonToLegacyReason(decision),
|
|
17418
|
+
summary: params.filePath,
|
|
17419
|
+
fingerprint,
|
|
17420
|
+
assessment: {
|
|
17421
|
+
reversibility: "reversible",
|
|
17422
|
+
external: params.locationLabel === "outside_repo",
|
|
17423
|
+
blastRadius: params.locationLabel === "outside_repo" ? "outside the repository" : "sensitive repository file",
|
|
17424
|
+
confidence: 0.85,
|
|
17425
|
+
signals: [...params.signals, ...decision.signals]
|
|
17426
|
+
},
|
|
17427
|
+
capabilityRequests: [request],
|
|
17428
|
+
authorizationDecision: decision,
|
|
17429
|
+
boundaryProfile: params.options.boundaryProfile ?? BOUNDARY_PROFILE_L3_L4_ONLY
|
|
17430
|
+
};
|
|
17431
|
+
}
|
|
17432
|
+
return {
|
|
17433
|
+
verdict: "allow",
|
|
17434
|
+
reason: "effect.fs_read",
|
|
17435
|
+
summary: params.filePath,
|
|
17436
|
+
fingerprint,
|
|
17437
|
+
assessment: {
|
|
17438
|
+
reversibility: "reversible",
|
|
17439
|
+
external: false,
|
|
17440
|
+
blastRadius: "tool scope",
|
|
17441
|
+
confidence: 0.88,
|
|
17442
|
+
signals: [...params.signals, ...decision.signals]
|
|
17443
|
+
},
|
|
17444
|
+
capabilityRequests: [request],
|
|
17445
|
+
authorizationDecision: decision,
|
|
17446
|
+
boundaryProfile: params.options.boundaryProfile ?? BOUNDARY_PROFILE_L3_L4_ONLY
|
|
17447
|
+
};
|
|
17448
|
+
}
|
|
17449
|
+
function classifyFilePathMutation(params) {
|
|
17450
|
+
const {
|
|
17451
|
+
toolName,
|
|
17452
|
+
toolKind,
|
|
17453
|
+
filePath,
|
|
17454
|
+
repoRoot,
|
|
17455
|
+
cwd,
|
|
17456
|
+
config,
|
|
17457
|
+
options,
|
|
17458
|
+
sensitivePaths,
|
|
17459
|
+
protectedRoots,
|
|
17460
|
+
isDelete
|
|
17461
|
+
} = params;
|
|
17462
|
+
const signals = [];
|
|
17463
|
+
const resolvedPath = path51.isAbsolute(filePath) ? filePath : path51.resolve(cwd, filePath);
|
|
17464
|
+
const hitsProtectedRoot = protectedRoots.some((root) => pathWithinRoot(root, resolvedPath));
|
|
17465
|
+
if (hitsProtectedRoot) {
|
|
17466
|
+
signals.push("control_plane_path");
|
|
17467
|
+
return classifyFileMutationWithPolicy({
|
|
17468
|
+
toolName,
|
|
17469
|
+
toolKind,
|
|
17470
|
+
filePath,
|
|
17471
|
+
resolvedPath,
|
|
17472
|
+
repoRoot,
|
|
17473
|
+
cwd,
|
|
17474
|
+
config,
|
|
17475
|
+
options,
|
|
17476
|
+
signals,
|
|
17477
|
+
isDelete,
|
|
17478
|
+
locationLabel: "control_plane"
|
|
17479
|
+
});
|
|
17480
|
+
}
|
|
17481
|
+
const workspaceMatch = resolveWorkspaceRootMatch(
|
|
17482
|
+
repoRoot,
|
|
17483
|
+
options.trustedWorkspaceRoots,
|
|
17484
|
+
resolvedPath
|
|
17485
|
+
);
|
|
17486
|
+
if (workspaceMatch === null) {
|
|
17487
|
+
signals.push("outside_repo_path");
|
|
17488
|
+
return classifyFileMutationWithPolicy({
|
|
17489
|
+
toolName,
|
|
17490
|
+
toolKind,
|
|
17491
|
+
filePath,
|
|
17492
|
+
resolvedPath,
|
|
17493
|
+
repoRoot,
|
|
17494
|
+
cwd,
|
|
17495
|
+
config,
|
|
17496
|
+
options,
|
|
17497
|
+
signals,
|
|
17498
|
+
isDelete,
|
|
17499
|
+
locationLabel: "outside_repo"
|
|
17500
|
+
});
|
|
17501
|
+
}
|
|
17502
|
+
if (workspaceMatch.kind === "trusted") {
|
|
17503
|
+
signals.push("trusted_workspace_root");
|
|
17504
|
+
}
|
|
17505
|
+
const trustedCwd = resolveClassifierTrustedCwd(cwd, options);
|
|
17506
|
+
const workspacePrescan = mutationPrescanRequiresAsk({
|
|
17507
|
+
targets: [filePath],
|
|
17508
|
+
cwd,
|
|
17509
|
+
repoRoot,
|
|
17510
|
+
trustedCwd,
|
|
17511
|
+
trustedWorkspaceRoots: options.trustedWorkspaceRoots,
|
|
17512
|
+
sensitivePaths
|
|
17513
|
+
});
|
|
17514
|
+
if (workspacePrescan) {
|
|
17515
|
+
return classifyFileMutationWithPolicy({
|
|
17516
|
+
toolName,
|
|
17517
|
+
toolKind,
|
|
17518
|
+
filePath,
|
|
17519
|
+
resolvedPath,
|
|
17520
|
+
repoRoot,
|
|
17521
|
+
cwd,
|
|
17522
|
+
config,
|
|
17523
|
+
options,
|
|
17524
|
+
signals,
|
|
17525
|
+
isDelete,
|
|
17526
|
+
locationLabel: "sensitive_path"
|
|
17527
|
+
});
|
|
17528
|
+
}
|
|
17529
|
+
const relativePath = workspaceMatch.relativePath;
|
|
17530
|
+
if (matchesSensitivePath(relativePath, sensitivePaths)) {
|
|
17531
|
+
signals.push("sensitive_path");
|
|
17532
|
+
return classifyFileMutationWithPolicy({
|
|
17533
|
+
toolName,
|
|
17534
|
+
toolKind,
|
|
17535
|
+
filePath,
|
|
17536
|
+
resolvedPath,
|
|
17537
|
+
repoRoot,
|
|
17538
|
+
cwd,
|
|
17539
|
+
config,
|
|
17540
|
+
options,
|
|
17541
|
+
signals,
|
|
17542
|
+
isDelete,
|
|
17543
|
+
locationLabel: "sensitive_path"
|
|
17544
|
+
});
|
|
17545
|
+
}
|
|
17546
|
+
if (isDelete) {
|
|
17547
|
+
if (isGitPath(resolvedPath, repoRoot)) {
|
|
17548
|
+
signals.push("protected_artifact");
|
|
17549
|
+
return classifyFileMutationWithPolicy({
|
|
17550
|
+
toolName,
|
|
17551
|
+
toolKind,
|
|
17552
|
+
filePath,
|
|
17553
|
+
resolvedPath,
|
|
17554
|
+
repoRoot,
|
|
17555
|
+
cwd,
|
|
17556
|
+
config,
|
|
17557
|
+
options,
|
|
17558
|
+
signals,
|
|
17559
|
+
isDelete: true,
|
|
17560
|
+
locationLabel: "sensitive_path"
|
|
17561
|
+
});
|
|
17562
|
+
}
|
|
17563
|
+
signals.push("file_delete");
|
|
17564
|
+
return classifyFileMutationWithPolicy({
|
|
17565
|
+
toolName,
|
|
17566
|
+
toolKind,
|
|
17567
|
+
filePath,
|
|
17568
|
+
resolvedPath,
|
|
17569
|
+
repoRoot,
|
|
17570
|
+
cwd,
|
|
17571
|
+
config,
|
|
17572
|
+
options,
|
|
17573
|
+
signals,
|
|
17574
|
+
isDelete: true,
|
|
17575
|
+
locationLabel: "repo_local"
|
|
17576
|
+
});
|
|
17577
|
+
}
|
|
17578
|
+
signals.push("file_mutation");
|
|
17579
|
+
return classifyFileMutationWithPolicy({
|
|
17580
|
+
toolName,
|
|
17581
|
+
toolKind,
|
|
17582
|
+
filePath,
|
|
17583
|
+
resolvedPath,
|
|
17584
|
+
repoRoot,
|
|
17585
|
+
cwd,
|
|
17586
|
+
config,
|
|
17587
|
+
options,
|
|
17588
|
+
signals,
|
|
17589
|
+
isDelete: false,
|
|
17590
|
+
locationLabel: "repo_local"
|
|
17591
|
+
});
|
|
17592
|
+
}
|
|
17593
|
+
function classifyFilePathRead(params) {
|
|
17594
|
+
const {
|
|
17595
|
+
toolName,
|
|
17596
|
+
toolKind,
|
|
17597
|
+
filePath,
|
|
17598
|
+
repoRoot,
|
|
17599
|
+
cwd,
|
|
17600
|
+
config,
|
|
17601
|
+
options,
|
|
17602
|
+
sensitivePaths,
|
|
17603
|
+
protectedRoots
|
|
17604
|
+
} = params;
|
|
17605
|
+
const signals = ["effect.fs_read"];
|
|
17606
|
+
const resolvedPath = path51.isAbsolute(filePath) ? filePath : path51.resolve(cwd, filePath);
|
|
17607
|
+
if (protectedRoots.some((root) => pathWithinRoot(root, resolvedPath))) {
|
|
17608
|
+
signals.push("control_plane_path");
|
|
17609
|
+
return classifyFileReadWithPolicy({
|
|
17610
|
+
toolName,
|
|
17611
|
+
toolKind,
|
|
17612
|
+
filePath,
|
|
17613
|
+
resolvedPath,
|
|
17614
|
+
repoRoot,
|
|
17615
|
+
cwd,
|
|
17616
|
+
config,
|
|
17617
|
+
options,
|
|
17618
|
+
signals,
|
|
17619
|
+
locationLabel: "control_plane"
|
|
17620
|
+
});
|
|
17621
|
+
}
|
|
17622
|
+
const workspaceMatch = resolveWorkspaceRootMatch(
|
|
17623
|
+
repoRoot,
|
|
17624
|
+
options.trustedWorkspaceRoots,
|
|
17625
|
+
resolvedPath
|
|
17626
|
+
);
|
|
17627
|
+
if (workspaceMatch === null) {
|
|
17628
|
+
signals.push("outside_repo_path");
|
|
17629
|
+
return classifyFileReadWithPolicy({
|
|
17630
|
+
toolName,
|
|
17631
|
+
toolKind,
|
|
17632
|
+
filePath,
|
|
17633
|
+
resolvedPath,
|
|
17634
|
+
repoRoot,
|
|
17635
|
+
cwd,
|
|
17636
|
+
config,
|
|
17637
|
+
options,
|
|
17638
|
+
signals,
|
|
17639
|
+
locationLabel: "outside_repo"
|
|
17640
|
+
});
|
|
17641
|
+
}
|
|
17642
|
+
const relativePath = workspaceMatch.relativePath;
|
|
17643
|
+
if (matchesSensitivePath(relativePath, sensitivePaths)) {
|
|
17644
|
+
signals.push("sensitive_path");
|
|
17645
|
+
return classifyFileReadWithPolicy({
|
|
17646
|
+
toolName,
|
|
17647
|
+
toolKind,
|
|
17648
|
+
filePath,
|
|
17649
|
+
resolvedPath,
|
|
17650
|
+
repoRoot,
|
|
17651
|
+
cwd,
|
|
17652
|
+
config,
|
|
17653
|
+
options,
|
|
17654
|
+
signals,
|
|
17655
|
+
locationLabel: "sensitive_path"
|
|
17656
|
+
});
|
|
17657
|
+
}
|
|
17658
|
+
return classifyFileReadWithPolicy({
|
|
17659
|
+
toolName,
|
|
17660
|
+
toolKind,
|
|
17661
|
+
filePath,
|
|
17662
|
+
resolvedPath,
|
|
17663
|
+
repoRoot,
|
|
17664
|
+
cwd,
|
|
17665
|
+
config,
|
|
17666
|
+
options,
|
|
17667
|
+
signals,
|
|
17668
|
+
locationLabel: "repo_local"
|
|
17669
|
+
});
|
|
17670
|
+
}
|
|
17671
|
+
function indeterminateToolResult(toolName, payload, repoRoot, options) {
|
|
17672
|
+
const summary = canonicalStringify(scrubPayload(payload.tool_input ?? {}, options));
|
|
17673
|
+
const fingerprint = toolFingerprint(toolName, fingerprintPayload(payload, options), repoRoot);
|
|
17674
|
+
if (options.unknownLocalEffect === "deny") {
|
|
17675
|
+
return {
|
|
17676
|
+
verdict: "deny_pending_approval",
|
|
17677
|
+
reason: "indeterminate_tool_effect",
|
|
17678
|
+
summary,
|
|
17679
|
+
fingerprint,
|
|
17680
|
+
assessment: {
|
|
17681
|
+
reversibility: "irreversible",
|
|
17682
|
+
external: false,
|
|
17683
|
+
blastRadius: "unknown tool action",
|
|
17684
|
+
confidence: 0.5,
|
|
17685
|
+
signals: ["indeterminate_tool_effect"]
|
|
17686
|
+
}
|
|
17687
|
+
};
|
|
17688
|
+
}
|
|
17689
|
+
return {
|
|
17690
|
+
verdict: "allow_flagged",
|
|
17691
|
+
reason: "indeterminate_tool_effect",
|
|
17692
|
+
summary,
|
|
17693
|
+
fingerprint,
|
|
17694
|
+
assessment: {
|
|
17695
|
+
reversibility: "recoverable_with_cost",
|
|
17696
|
+
external: false,
|
|
17697
|
+
blastRadius: "tool scope",
|
|
17698
|
+
confidence: 0.5,
|
|
17699
|
+
signals: ["indeterminate_tool_effect"]
|
|
17700
|
+
}
|
|
17701
|
+
};
|
|
17702
|
+
}
|
|
17337
17703
|
async function classifyToolUse(payload, repoRoot, cwd, config, options = {}) {
|
|
17338
17704
|
const toolName = String(payload.tool_name ?? "");
|
|
17339
17705
|
const toolKind = normalizedToolName(toolName);
|
|
@@ -17380,9 +17746,10 @@ async function classifyToolUse(payload, repoRoot, cwd, config, options = {}) {
|
|
|
17380
17746
|
summary: command
|
|
17381
17747
|
};
|
|
17382
17748
|
}
|
|
17383
|
-
|
|
17384
|
-
|
|
17385
|
-
|
|
17749
|
+
const effect = inferToolPayloadEffect(payload, toolName);
|
|
17750
|
+
if (effect === "file_mutation" || effect === "file_delete") {
|
|
17751
|
+
const filePath2 = extractFilePath(payload);
|
|
17752
|
+
if (!filePath2) {
|
|
17386
17753
|
if (options.unknownLocalEffect === "deny") {
|
|
17387
17754
|
return {
|
|
17388
17755
|
verdict: "deny_pending_approval",
|
|
@@ -17412,138 +17779,20 @@ async function classifyToolUse(payload, repoRoot, cwd, config, options = {}) {
|
|
|
17412
17779
|
}
|
|
17413
17780
|
};
|
|
17414
17781
|
}
|
|
17415
|
-
|
|
17416
|
-
const resolvedPath = path51.isAbsolute(filePath) ? filePath : path51.resolve(cwd, filePath);
|
|
17417
|
-
const hitsProtectedRoot = protectedRoots.some((root) => pathWithinRoot(root, resolvedPath));
|
|
17418
|
-
if (hitsProtectedRoot) {
|
|
17419
|
-
signals.push("control_plane_path");
|
|
17420
|
-
return classifyFileMutationWithPolicy({
|
|
17421
|
-
toolName,
|
|
17422
|
-
toolKind,
|
|
17423
|
-
filePath,
|
|
17424
|
-
resolvedPath,
|
|
17425
|
-
repoRoot,
|
|
17426
|
-
cwd,
|
|
17427
|
-
config,
|
|
17428
|
-
options,
|
|
17429
|
-
signals,
|
|
17430
|
-
isDelete: FILE_DELETE_TOOL_NAMES.has(toolKind),
|
|
17431
|
-
locationLabel: "control_plane"
|
|
17432
|
-
});
|
|
17433
|
-
}
|
|
17434
|
-
const workspaceMatch = resolveWorkspaceRootMatch(
|
|
17435
|
-
repoRoot,
|
|
17436
|
-
options.trustedWorkspaceRoots,
|
|
17437
|
-
resolvedPath
|
|
17438
|
-
);
|
|
17439
|
-
if (workspaceMatch === null) {
|
|
17440
|
-
signals.push("outside_repo_path");
|
|
17441
|
-
return classifyFileMutationWithPolicy({
|
|
17442
|
-
toolName,
|
|
17443
|
-
toolKind,
|
|
17444
|
-
filePath,
|
|
17445
|
-
resolvedPath,
|
|
17446
|
-
repoRoot,
|
|
17447
|
-
cwd,
|
|
17448
|
-
config,
|
|
17449
|
-
options,
|
|
17450
|
-
signals,
|
|
17451
|
-
isDelete: FILE_DELETE_TOOL_NAMES.has(toolKind),
|
|
17452
|
-
locationLabel: "outside_repo"
|
|
17453
|
-
});
|
|
17454
|
-
}
|
|
17455
|
-
if (workspaceMatch.kind === "trusted") {
|
|
17456
|
-
signals.push("trusted_workspace_root");
|
|
17457
|
-
}
|
|
17458
|
-
const trustedCwd = resolveClassifierTrustedCwd(cwd, options);
|
|
17459
|
-
const workspacePrescan = mutationPrescanRequiresAsk({
|
|
17460
|
-
targets: [filePath],
|
|
17461
|
-
cwd,
|
|
17462
|
-
repoRoot,
|
|
17463
|
-
trustedCwd,
|
|
17464
|
-
trustedWorkspaceRoots: options.trustedWorkspaceRoots,
|
|
17465
|
-
sensitivePaths
|
|
17466
|
-
});
|
|
17467
|
-
if (workspacePrescan) {
|
|
17468
|
-
return classifyFileMutationWithPolicy({
|
|
17469
|
-
toolName,
|
|
17470
|
-
toolKind,
|
|
17471
|
-
filePath,
|
|
17472
|
-
resolvedPath,
|
|
17473
|
-
repoRoot,
|
|
17474
|
-
cwd,
|
|
17475
|
-
config,
|
|
17476
|
-
options,
|
|
17477
|
-
signals,
|
|
17478
|
-
isDelete: FILE_DELETE_TOOL_NAMES.has(toolKind),
|
|
17479
|
-
locationLabel: "sensitive_path"
|
|
17480
|
-
});
|
|
17481
|
-
}
|
|
17482
|
-
const relativePath = workspaceMatch.relativePath;
|
|
17483
|
-
if (matchesSensitivePath(relativePath, sensitivePaths)) {
|
|
17484
|
-
signals.push("sensitive_path");
|
|
17485
|
-
return classifyFileMutationWithPolicy({
|
|
17486
|
-
toolName,
|
|
17487
|
-
toolKind,
|
|
17488
|
-
filePath,
|
|
17489
|
-
resolvedPath,
|
|
17490
|
-
repoRoot,
|
|
17491
|
-
cwd,
|
|
17492
|
-
config,
|
|
17493
|
-
options,
|
|
17494
|
-
signals,
|
|
17495
|
-
isDelete: FILE_DELETE_TOOL_NAMES.has(toolKind),
|
|
17496
|
-
locationLabel: "sensitive_path"
|
|
17497
|
-
});
|
|
17498
|
-
}
|
|
17499
|
-
if (FILE_DELETE_TOOL_NAMES.has(toolKind)) {
|
|
17500
|
-
if (isGitPath(resolvedPath, repoRoot)) {
|
|
17501
|
-
signals.push("protected_artifact");
|
|
17502
|
-
return classifyFileMutationWithPolicy({
|
|
17503
|
-
toolName,
|
|
17504
|
-
toolKind,
|
|
17505
|
-
filePath,
|
|
17506
|
-
resolvedPath,
|
|
17507
|
-
repoRoot,
|
|
17508
|
-
cwd,
|
|
17509
|
-
config,
|
|
17510
|
-
options,
|
|
17511
|
-
signals,
|
|
17512
|
-
isDelete: true,
|
|
17513
|
-
locationLabel: "sensitive_path"
|
|
17514
|
-
});
|
|
17515
|
-
}
|
|
17516
|
-
signals.push("file_delete");
|
|
17517
|
-
return classifyFileMutationWithPolicy({
|
|
17518
|
-
toolName,
|
|
17519
|
-
toolKind,
|
|
17520
|
-
filePath,
|
|
17521
|
-
resolvedPath,
|
|
17522
|
-
repoRoot,
|
|
17523
|
-
cwd,
|
|
17524
|
-
config,
|
|
17525
|
-
options,
|
|
17526
|
-
signals,
|
|
17527
|
-
isDelete: true,
|
|
17528
|
-
locationLabel: "repo_local"
|
|
17529
|
-
});
|
|
17530
|
-
}
|
|
17531
|
-
signals.push("file_mutation");
|
|
17532
|
-
return classifyFileMutationWithPolicy({
|
|
17782
|
+
return classifyFilePathMutation({
|
|
17533
17783
|
toolName,
|
|
17534
17784
|
toolKind,
|
|
17535
|
-
filePath,
|
|
17536
|
-
resolvedPath,
|
|
17785
|
+
filePath: filePath2,
|
|
17537
17786
|
repoRoot,
|
|
17538
17787
|
cwd,
|
|
17539
17788
|
config,
|
|
17540
17789
|
options,
|
|
17541
|
-
|
|
17542
|
-
|
|
17543
|
-
|
|
17790
|
+
sensitivePaths,
|
|
17791
|
+
protectedRoots,
|
|
17792
|
+
isDelete: effect === "file_delete"
|
|
17544
17793
|
});
|
|
17545
17794
|
}
|
|
17546
|
-
if (
|
|
17795
|
+
if (effect === "apply_patch") {
|
|
17547
17796
|
const patch = extractPatch(payload);
|
|
17548
17797
|
const targets = patch ? applyPatchTargets2(patch) : [];
|
|
17549
17798
|
if (targets.length === 0) {
|
|
@@ -17581,7 +17830,7 @@ async function classifyToolUse(payload, repoRoot, cwd, config, options = {}) {
|
|
|
17581
17830
|
const result = await classifyToolUse(
|
|
17582
17831
|
{
|
|
17583
17832
|
tool_name: target.delete ? "Delete" : "Write",
|
|
17584
|
-
tool_input: { path: target.path }
|
|
17833
|
+
tool_input: target.delete ? { path: target.path } : { path: target.path, contents: " " }
|
|
17585
17834
|
},
|
|
17586
17835
|
repoRoot,
|
|
17587
17836
|
cwd,
|
|
@@ -17607,19 +17856,54 @@ async function classifyToolUse(payload, repoRoot, cwd, config, options = {}) {
|
|
|
17607
17856
|
}
|
|
17608
17857
|
};
|
|
17609
17858
|
}
|
|
17610
|
-
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
17614
|
-
fingerprint: toolFingerprint(toolName, fingerprintPayload(payload, options), repoRoot),
|
|
17615
|
-
assessment: {
|
|
17616
|
-
reversibility: "reversible",
|
|
17617
|
-
external: false,
|
|
17618
|
-
blastRadius: "tool scope",
|
|
17619
|
-
confidence: 0.5,
|
|
17620
|
-
signals: ["unclassified_tool"]
|
|
17859
|
+
if (effect === "file_read") {
|
|
17860
|
+
const filePath2 = extractFilePath(payload);
|
|
17861
|
+
if (!filePath2) {
|
|
17862
|
+
return indeterminateToolResult(toolName, payload, repoRoot, options);
|
|
17621
17863
|
}
|
|
17622
|
-
|
|
17864
|
+
return classifyFilePathRead({
|
|
17865
|
+
toolName,
|
|
17866
|
+
toolKind,
|
|
17867
|
+
filePath: filePath2,
|
|
17868
|
+
repoRoot,
|
|
17869
|
+
cwd,
|
|
17870
|
+
config,
|
|
17871
|
+
options,
|
|
17872
|
+
sensitivePaths,
|
|
17873
|
+
protectedRoots
|
|
17874
|
+
});
|
|
17875
|
+
}
|
|
17876
|
+
if (effect === "search_read") {
|
|
17877
|
+
return {
|
|
17878
|
+
verdict: "allow",
|
|
17879
|
+
reason: "effect.search_read",
|
|
17880
|
+
summary: canonicalStringify(scrubPayload(payload.tool_input ?? {}, options)),
|
|
17881
|
+
fingerprint: toolFingerprint(toolName, fingerprintPayload(payload, options), repoRoot),
|
|
17882
|
+
assessment: {
|
|
17883
|
+
reversibility: "reversible",
|
|
17884
|
+
external: false,
|
|
17885
|
+
blastRadius: "tool scope",
|
|
17886
|
+
confidence: 0.88,
|
|
17887
|
+
signals: ["effect.search_read"]
|
|
17888
|
+
}
|
|
17889
|
+
};
|
|
17890
|
+
}
|
|
17891
|
+
const filePath = extractFilePath(payload);
|
|
17892
|
+
if (filePath) {
|
|
17893
|
+
return classifyFilePathMutation({
|
|
17894
|
+
toolName,
|
|
17895
|
+
toolKind,
|
|
17896
|
+
filePath,
|
|
17897
|
+
repoRoot,
|
|
17898
|
+
cwd,
|
|
17899
|
+
config,
|
|
17900
|
+
options,
|
|
17901
|
+
sensitivePaths,
|
|
17902
|
+
protectedRoots,
|
|
17903
|
+
isDelete: toolKind === "delete"
|
|
17904
|
+
});
|
|
17905
|
+
}
|
|
17906
|
+
return indeterminateToolResult(toolName, payload, repoRoot, options);
|
|
17623
17907
|
}
|
|
17624
17908
|
|
|
17625
17909
|
// src/core/gate-engine.ts
|
|
@@ -17954,15 +18238,8 @@ function gateEnabledForAction(config, action) {
|
|
|
17954
18238
|
if (action.kind === "subagent") {
|
|
17955
18239
|
return config.gates.subagent;
|
|
17956
18240
|
}
|
|
17957
|
-
|
|
17958
|
-
|
|
17959
|
-
return config.gates.toolShell;
|
|
17960
|
-
}
|
|
17961
|
-
if (toolName === "Write" || toolName === "StrReplace" || toolName === "Delete") {
|
|
17962
|
-
return config.gates.fileMutation;
|
|
17963
|
-
}
|
|
17964
|
-
if (toolName === "Task") {
|
|
17965
|
-
return config.gates.subagent;
|
|
18241
|
+
if (action.kind === "tool") {
|
|
18242
|
+
return config.gates.fileMutation || config.gates.toolShell;
|
|
17966
18243
|
}
|
|
17967
18244
|
return true;
|
|
17968
18245
|
}
|
|
@@ -17999,7 +18276,7 @@ function hashDecisionConfig(config) {
|
|
|
17999
18276
|
init_fingerprint2();
|
|
18000
18277
|
|
|
18001
18278
|
// src/version.ts
|
|
18002
|
-
var PACKAGE_VERSION = "0.10.
|
|
18279
|
+
var PACKAGE_VERSION = "0.10.1";
|
|
18003
18280
|
|
|
18004
18281
|
// src/runtime-provenance.ts
|
|
18005
18282
|
function resolveRuntimeArtifactHash(artifactHash) {
|
|
@@ -21300,21 +21577,7 @@ async function evaluateGatedAction(ctx, deps, params) {
|
|
|
21300
21577
|
...authorization,
|
|
21301
21578
|
egressProxyActive
|
|
21302
21579
|
};
|
|
21303
|
-
|
|
21304
|
-
if (action.kind === "tool" && predicted.reason === "unclassified_tool" && (ctx.config.policy.codexUnmappedTool ?? "deny") === "deny") {
|
|
21305
|
-
predicted = {
|
|
21306
|
-
...predicted,
|
|
21307
|
-
verdict: "deny_pending_approval",
|
|
21308
|
-
reason: "unmapped_tool",
|
|
21309
|
-
assessment: {
|
|
21310
|
-
reversibility: "irreversible",
|
|
21311
|
-
external: false,
|
|
21312
|
-
blastRadius: "unknown tool action",
|
|
21313
|
-
confidence: 0.5,
|
|
21314
|
-
signals: ["unmapped_tool"]
|
|
21315
|
-
}
|
|
21316
|
-
};
|
|
21317
|
-
}
|
|
21580
|
+
const predicted = await classifyGatedActionAsync(action, ctx.config, enrichedClassifierOptions);
|
|
21318
21581
|
if (action.kind === "shell" && action.command && isContainedUnknownExecutionEligible(ctx.config, action, predicted)) {
|
|
21319
21582
|
const mediated = await mediateContainedUnknownExecution({
|
|
21320
21583
|
ctx,
|