* Checks if a resolved path is allowed for the given operation type. * Mirrors the logic in BashTool/pathValidation.ts isPathAllowed.
( resolvedPath: string, context: ToolPermissionContext, operationType: FileOperationType, precomputedPathsToCheck?: readonly string[], )
| 861 | * Mirrors the logic in BashTool/pathValidation.ts isPathAllowed. |
| 862 | */ |
| 863 | function isPathAllowed( |
| 864 | resolvedPath: string, |
| 865 | context: ToolPermissionContext, |
| 866 | operationType: FileOperationType, |
| 867 | precomputedPathsToCheck?: readonly string[], |
| 868 | ): PathCheckResult { |
| 869 | const permissionType = operationType === 'read' ? 'read' : 'edit' |
| 870 | |
| 871 | // 1. Check deny rules first |
| 872 | const denyRule = matchingRuleForInput( |
| 873 | resolvedPath, |
| 874 | context, |
| 875 | permissionType, |
| 876 | 'deny', |
| 877 | ) |
| 878 | if (denyRule !== null) { |
| 879 | return { |
| 880 | allowed: false, |
| 881 | decisionReason: { type: 'rule', rule: denyRule }, |
| 882 | } |
| 883 | } |
| 884 | |
| 885 | // 2. For write/create operations, check internal editable paths (plan files, scratchpad, agent memory, job dirs) |
| 886 | // This MUST come before checkPathSafetyForAutoEdit since .claude is a dangerous directory |
| 887 | // and internal editable paths live under ~/.claude/ — matching the ordering in |
| 888 | // checkWritePermissionForTool (filesystem.ts step 1.5) |
| 889 | if (operationType !== 'read') { |
| 890 | const internalEditResult = checkEditableInternalPath(resolvedPath, {}) |
| 891 | if (internalEditResult.behavior === 'allow') { |
| 892 | return { |
| 893 | allowed: true, |
| 894 | decisionReason: internalEditResult.decisionReason, |
| 895 | } |
| 896 | } |
| 897 | } |
| 898 | |
| 899 | // 2.5. For write/create operations, check safety validations |
| 900 | if (operationType !== 'read') { |
| 901 | const safetyCheck = checkPathSafetyForAutoEdit( |
| 902 | resolvedPath, |
| 903 | precomputedPathsToCheck, |
| 904 | ) |
| 905 | if (!safetyCheck.safe) { |
| 906 | return { |
| 907 | allowed: false, |
| 908 | decisionReason: { |
| 909 | type: 'safetyCheck', |
| 910 | reason: safetyCheck.message, |
| 911 | classifierApprovable: safetyCheck.classifierApprovable, |
| 912 | }, |
| 913 | } |
| 914 | } |
| 915 | } |
| 916 | |
| 917 | // 3. Check if path is in allowed working directory |
| 918 | const isInWorkingDir = pathInAllowedWorkingPath( |
| 919 | resolvedPath, |
| 920 | context, |
no test coverage detected