MCPcopy
hub / github.com/vercel-labs/just-bash / ReadWriteFs

Class ReadWriteFs

packages/just-bash/src/fs/read-write-fs/read-write-fs.ts:69–901  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

67}
68
69export class ReadWriteFs implements IFileSystem {
70 private readonly root: string;
71 private readonly canonicalRoot: string;
72 private readonly maxFileReadSize: number;
73 private readonly allowSymlinks: boolean;
74
75 constructor(options: ReadWriteFsOptions) {
76 this.root = nodePath.resolve(options.root);
77 this.maxFileReadSize = options.maxFileReadSize ?? 10485760;
78 this.allowSymlinks = options.allowSymlinks ?? false;
79
80 // Verify root exists and is a directory
81 validateRootDirectory(this.root, "ReadWriteFs");
82
83 // Compute canonical root (resolves symlinks like /var -> /private/var on macOS)
84 this.canonicalRoot = fs.realpathSync(this.root);
85 }
86
87 /**
88 * Validate that a resolved real path stays within the sandbox root and
89 * return the canonical (symlink-resolved) path for use in subsequent I/O.
90 * This closes the TOCTOU gap where the original path could be swapped
91 * between validation and use.
92 * Throws EACCES if the path escapes the root.
93 */
94 private resolveAndValidate(realPath: string, virtualPath: string): string {
95 const canonical = this.allowSymlinks
96 ? resolveCanonicalPath(realPath, this.canonicalRoot)
97 : resolveCanonicalPathNoSymlinks(realPath, this.root, this.canonicalRoot);
98 if (canonical === null) {
99 throw new Error(
100 `EACCES: permission denied, '${virtualPath}' resolves outside sandbox`,
101 );
102 }
103 return canonical;
104 }
105
106 /**
107 * Validate the parent directory of a path (for operations like lstat/readlink
108 * that should not follow the final component's symlink).
109 * Returns the canonical parent joined with the original basename.
110 */
111 private validateParent(realPath: string, virtualPath: string): string {
112 const parent = nodePath.dirname(realPath);
113 const canonicalParent = this.resolveAndValidate(parent, virtualPath);
114 return nodePath.join(canonicalParent, nodePath.basename(realPath));
115 }
116
117 /**
118 * Convert a virtual path to a real filesystem path.
119 */
120 private toRealPath(virtualPath: string): string {
121 const normalized = normalizePath(virtualPath);
122 const realPath = nodePath.join(this.root, normalized);
123 return nodePath.resolve(realPath);
124 }
125
126 async readFile(

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…