fix(codex-config): close whole-branch review defects in the Codex panel
Plugins/marketplaces GET routes were silently empty because codex-cli.js
never unwrapped the CLI's {installed,available}/{marketplaces} objects
into arrays; backup writes bypassed the symlink-escape guard entirely;
readFileSafe was stricter than every other Codex reader, showing a
symlinked skill/rule in the list and then refusing to open it;
marketplaceAdd only accepted http(s) URLs, rejecting owner/repo sources
the CLI itself takes. Also: docs drift, a dead i18n key, and a scope-cast
hazard in the shared Editor/ConfirmDelete modals.
Fixes, one per finding: unwrap installed/marketplaces in codex-cli.js so
every list route keeps returning a bare list; guard the backup path in
codex-mutate.js with the same assertNotSymlinkEscape the write path
already used (Claude's cc-mutate.js has no such guard on its primary
write path either, so left untouched there); relax readFileSafe's
containment to lexical-only, matching the other four Codex readers,
while leaving the write side's realpath check untouched; reuse
cc-plugin-cli's assertSource for marketplaceAdd instead of a third
validator (ssh remains out of scope, no credential story for it yet).
Server: 1557/1557 (was 1548). Client: tsc -b clean, 469/469 tests.
This commit is contained in:
@@ -97,10 +97,11 @@ router.get("/config", (req, res) => {
|
||||
// GET /api/codex-config/file?path=/abs/path — return body of a single file.
|
||||
// Path must resolve under CODEX_HOME, the project .codex dir, or (only for a
|
||||
// file literally named AGENTS.md) the project root. codexDiscovery.readFileSafe
|
||||
// re-checks containment with the same leaf/ancestor symlink-escape guard the
|
||||
// write side uses (codex-mutate.js's assertNotSymlinkEscape) — a plain
|
||||
// string-only path check would let a symlink dropped under the root read
|
||||
// arbitrary files outside it.
|
||||
// checks that containment lexically — a symlink whose LOCATION is inside a
|
||||
// root is readable even when it resolves outside, matching the other four
|
||||
// discovery readers. The write side (codex-mutate.js) keeps the stricter
|
||||
// realpath-based assertNotSymlinkEscape — reads and writes intentionally
|
||||
// disagree on symlinks; see readFileSafe's doc comment for why.
|
||||
router.get("/file", (req, res) => {
|
||||
const p = req.query.path;
|
||||
if (typeof p !== "string" || !p) {
|
||||
|
||||
Reference in New Issue
Block a user