fix(codex): stop 502ing empty CLI output, GET /file no longer mkdirs or leaks paths
This commit is contained in:
@@ -300,6 +300,16 @@ function readOverview(opts = {}) {
|
||||
* symlink-escape guard the write side (codex-mutate.js) uses — a string-only
|
||||
* `isUnder` check alone would let a symlink dropped anywhere along the path
|
||||
* read arbitrary files outside the root.
|
||||
*
|
||||
* A GET has no filesystem side effect: `assertNotSymlinkEscape` is called
|
||||
* with `{create: false}` so it never mkdirs a caller-chosen root, and a
|
||||
* missing root or file both come back as `{notFound: true}` rather than the
|
||||
* write side's `EOUTOFROOT`. Failure messages never include the resolved
|
||||
* path — a `GET /file` response is not the place to reveal what does or
|
||||
* does not exist outside the root.
|
||||
*
|
||||
* @returns {{ok:true,file:string,size:number,mtime:number,truncated:boolean,text:string}
|
||||
* | {notFound:true} | {error:string}}
|
||||
*/
|
||||
function readFileSafe(absPath, opts = {}) {
|
||||
const codexHome = getCodexHome();
|
||||
@@ -323,13 +333,16 @@ function readFileSafe(absPath, opts = {}) {
|
||||
? projectCodexDir
|
||||
: projectRoot;
|
||||
try {
|
||||
assertNotSymlinkEscape(trustedRoot, resolved);
|
||||
assertNotSymlinkEscape(trustedRoot, resolved, { create: false });
|
||||
} catch (err) {
|
||||
return { error: err.message };
|
||||
// A root that doesn't exist yet (ENOENT from realpathSync, since this
|
||||
// call never mkdirs it) means there is nothing to find, not a refusal.
|
||||
if (err.code === "ENOENT") return { notFound: true };
|
||||
return { error: "path escapes the allowed root" };
|
||||
}
|
||||
|
||||
const r = safeReadText(resolved);
|
||||
if (!r) return { error: "file not readable" };
|
||||
if (!r) return { notFound: true };
|
||||
return { ok: true, file: resolved, ...r };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user