read user-scope Claude config files via a read allow-list (D-80)
The reader opened repo-local .claude markdown but rejected user-scope files under ~/.claude with "path outside workspace" — that dir is global, outside the repo, and files.read was repo-confined (T-102). Per D-76 the Claude config surface is clide-managed, so files.read now resolves a path under an allow-list: the workspace root plus trusted extra read roots (FilesService.extraReadRoots), wired in main.dart to ~/.claude when present. Reads widen; writes stay repo-confined, and the symlink re-check still refuses a config-root symlink that escapes. Off- root paths and `..` traversal are rejected as before. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ class FilesService {
|
||||
required this.root,
|
||||
required this.events,
|
||||
IgnoreSet? ignore,
|
||||
this.extraReadRoots = const [],
|
||||
}) : ignore = ignore ?? _defaultIgnore(root);
|
||||
|
||||
/// Build from the current working directory, walking up to the git
|
||||
@@ -39,6 +40,10 @@ class FilesService {
|
||||
final IgnoreSet ignore;
|
||||
final DaemonEventSink events;
|
||||
|
||||
/// Trusted read-only roots outside the workspace that `files.read`
|
||||
/// also accepts (the Claude config dirs, D-80). Writes ignore these.
|
||||
final List<Directory> extraReadRoots;
|
||||
|
||||
FileWatcher? _watcher;
|
||||
|
||||
Future<void> startWatching() async {
|
||||
@@ -81,8 +86,9 @@ void registerFilesCommands(DaemonDispatcher d, FilesService files) {
|
||||
final String absPath;
|
||||
try {
|
||||
// Follow symlinks + re-check containment so a `config -> /etc/shadow`
|
||||
// symlink under the workspace can't be read (T-102).
|
||||
absPath = resolveUnderRootFollowingSymlinks(files.root, path);
|
||||
// symlink can't be read (T-102). Accepts the workspace root plus
|
||||
// the trusted extra read roots (Claude config dirs, D-80).
|
||||
absPath = resolveUnderRootsFollowingSymlinks(files.root, files.extraReadRoots, path);
|
||||
} on PathOutsideRoot {
|
||||
return IpcResponse.err(id: req.id, error: IpcError(code: IpcExitCode.toolError, kind: IpcErrorKind.toolError, message: 'path outside workspace: $path'));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user