MCPcopy
hub / github.com/codeaashu/claude-code / checkWritePermissionForTool

Function checkWritePermissionForTool

src/utils/permissions/filesystem.ts:1205–1412  ·  view source on GitHub ↗
(
  tool: Tool<Input>,
  input: z.infer<Input>,
  toolPermissionContext: ToolPermissionContext,
  precomputedPathsToCheck?: readonly string[],
)

Source from the content-addressed store, hash-verified

1203 * stale value would silently check deny rules for the wrong path.
1204 */
1205export function checkWritePermissionForTool<Input extends AnyObject>(
1206 tool: Tool<Input>,
1207 input: z.infer<Input>,
1208 toolPermissionContext: ToolPermissionContext,
1209 precomputedPathsToCheck?: readonly string[],
1210): PermissionDecision {
1211 if (typeof tool.getPath !== 'function') {
1212 return {
1213 behavior: 'ask',
1214 message: `Claude requested permissions to use ${tool.name}, but you haven't granted it yet.`,
1215 }
1216 }
1217 const path = tool.getPath(input)
1218
1219 // 1. Check for deny rules - check both the original path and resolved symlink path
1220 const pathsToCheck =
1221 precomputedPathsToCheck ?? getPathsForPermissionCheck(path)
1222 for (const pathToCheck of pathsToCheck) {
1223 const denyRule = matchingRuleForInput(
1224 pathToCheck,
1225 toolPermissionContext,
1226 'edit',
1227 'deny',
1228 )
1229 if (denyRule) {
1230 return {
1231 behavior: 'deny',
1232 message: `Permission to edit ${path} has been denied.`,
1233 decisionReason: {
1234 type: 'rule',
1235 rule: denyRule,
1236 },
1237 }
1238 }
1239 }
1240
1241 // 1.5. Allow writes to internal editable paths (plan files, scratchpad)
1242 // This MUST come before isDangerousFilePathToAutoEdit check since .claude is a dangerous directory
1243 const absolutePathForEdit = expandPath(path)
1244 const internalEditResult = checkEditableInternalPath(
1245 absolutePathForEdit,
1246 input,
1247 )
1248 if (internalEditResult.behavior !== 'passthrough') {
1249 return internalEditResult
1250 }
1251
1252 // 1.6. Check for .claude/** allow rules BEFORE safety checks
1253 // This allows session-level permissions to bypass the safety blocks for .claude/
1254 // We only allow this for session-level rules to prevent users from accidentally
1255 // permanently granting broad access to their .claude/ folder.
1256 //
1257 // matchingRuleForInput returns the first match across all sources. If the user
1258 // also has a broader Edit(.claude) rule in userSettings (e.g. from sandbox
1259 // write-allow conversion), that rule would be found first and its source check
1260 // below would fail. Scope the search to session-only rules so the dialog's
1261 // "allow Claude to edit its own settings for this session" option actually works.
1262 const claudeFolderAllowRule = matchingRuleForInput(

Callers 4

checkPermissionsFunction · 0.85
checkPermissionsFunction · 0.85
checkPermissionsFunction · 0.85

Calls 8

matchingRuleForInputFunction · 0.85
expandPathFunction · 0.85
getClaudeSkillScopeFunction · 0.85
generateSuggestionsFunction · 0.85
pathInAllowedWorkingPathFunction · 0.85

Tested by

no test coverage detected