Skip to content

Follow-up: deferred review finding from PR #466 (Codex live projector's in-band cwd reaches the .hypignore gate unpredicated) #471

Description

@philcunliffe

Deferred from PR #466's triage (round 2, unreviewed head)

PR #466 (fix/issue-465, head 1f7fdac) fixed two review-round-1 findings by
requiring a rollout-sourced Codex cwd to be non-blank and absolute
before it reaches the .hypignore policy gate (sessionMetaCwd in
src/core/codex/rollout_session_meta.js, shared with the codex backfill).
The PR's own new doc, LLP 0143 #usable-cwd,
records one remaining gap on purpose rather than silently. This issue tracks
that gap so it doesn't only live in a decision doc's "Still outstanding" bullet.

The finding

hypaware-core/plugins-workspace/codex/src/exchange-projector.js:120-123

const cwd = firstString(codexContext?.cwd, readRecordedCwd(reqBody))
  ?? (codexContext?.session_id ? rolloutCwd?.resolve(codexContext.session_id) : undefined)
if (cwd) {
  const policy = resolver.resolve(cwd)
  if (policy.class === 'ignore') { ... return USAGE_POLICY_DROP }
}

codexContext?.cwd and readRecordedCwd(reqBody) (defined at
exchange-projector.js:880, reading reqBody.cwd / metadata.cwd /
metadata.user_id.cwd) are the Codex in-band cwd — the API-key route's
fast path (LLP 0083). Neither is passed through sessionMetaCwd or any other
absoluteness check. A relative value here reaches resolver.resolve(cwd)
directly, whose first act is path.resolve(cwd) against the daemon's
process cwd — the exact hazard PR #466 just closed for the rollout-fallback
source, reached through a different (in-band) source. This is the policy
gate itself, not only the row's stamped content (the same cwd value is
also passed to resolveRecordedContext at line 164 for enrichment, but line
120-123 is the drop decision).

Why PR #466 didn't fix this too

Per LLP 0143's consequences section, it is a different source with a
different trust story (client-supplied per-request, not a locally-written
rollout file), tightening it also touches row content (line 164), not only
the drop decision, so it is not a mechanical consequence of sharing
sessionMetaCwd. The branch was also already conflicting with #458 and #462
in this same file's neighborhood; a third change here was judged to add
avoidable conflict surface for a fix already at its 2-round review budget.

Why this issue is not blocked on #466

This code is already on master, unmodified by PR #466 (git diff c551d6e..1f7fdac -- hypaware-core/plugins-workspace/codex/src/exchange-projector.js
is empty). Whether or not #466 merges has no effect on this exposure either
way — it is actionable independent of #466's fate.

Suggested shape

Extend the same sessionMetaCwd-shaped predicate (or a general one) to
codexContext?.cwd / readRecordedCwd(reqBody) before they reach
resolver.resolve, deciding explicitly what happens to the stamped row
content when an in-band cwd is refused (null cwd vs. some other enrichment
fallback), since unlike the rollout source this value currently does double
duty as both gate input and recorded content.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    neutral:fixDelegate this issue to neutral for an autonomous fix attempt (reproduce -> fix -> PR)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions