Skip to content

Surface config syntax errors as findings + Codex multi-project trust + IPv6 loopback#47

Merged
Conalh merged 1 commit into
mainfrom
config-syntax-and-endpoint-hardening
May 22, 2026
Merged

Surface config syntax errors as findings + Codex multi-project trust + IPv6 loopback#47
Conalh merged 1 commit into
mainfrom
config-syntax-and-endpoint-hardening

Conversation

@Conalh
Copy link
Copy Markdown
Owner

@Conalh Conalh commented May 22, 2026

Summary

Four issues from the latest inspection round, all in the "silent failure looks clean" category — exactly the failure mode a trust-focused reviewer can't afford. Test count goes 54 → 59 with regression coverage for every fix.

Findings addressed

# Bug Fix
P1 Malformed .codex/config.toml returned rating: "none" instead of failing loudly Emit scope_trail.codex_config_syntax_error (high); short-circuit the rest of the detector
P1 Malformed .mcp.json / .claude/settings.json crashed the CLI with raw SyntaxError, bypassing fail-on semantics Catch JSON.parse in readJsonObjectWithSource; detectors emit mcp_config_syntax_error (high), mcp_sample_config_syntax_error (low), claude_settings_syntax_error (high)
P2 Codex [projects.*] sections collapsed to one bucket — second new trusted project went undetected when one already existed Iterate parseToml(text).projects per-path; subject now includes the project path so reviewers see which one changed
P3 IPv6 loopback [::1] flagged as remote (Node's URL parser returns hostname with brackets, exclusion list had ::1 without) Include [::1] alongside ::1 in the loopback list

Why "silent failure" matters

ScopeTrail is advertised as a trust-focused permission-drift reviewer. The worst outcome isn't a false positive — it's a clean report that hides real drift. P1 and P2 were exactly this shape: a malformed config or a stealth second-trusted-project produced findingCount: 0 while the underlying state got more permissive. This PR converts those into loud failures.

Test plan

  • npm test — 59/59 passing locally (up from 54)
  • npm run build clean
  • All four bugs have dedicated regression tests
  • Existing detects Codex config permission drift test updated for the new per-path subject (projects.c:\dev\example.trust_level)
  • CI green

Severity calibration

  • Active config syntax errors → high (file is live, reviewer needs to fix before merge)
  • Sample config syntax errors → low (advisory examples; broken sample doesn't compromise the repo, just makes the example unhelpful)
  • Codex project trust → high (unchanged)
  • IPv6 loopback — no severity change, just stops false positives

🤖 Generated with Claude Code

…back

Four issues from the latest inspection round, all in the "silent
failure looks clean" category — exactly the failure mode a
trust-focused reviewer can't afford.

1. **Malformed .codex/config.toml returned a clean report.**
   `parseToml` failure in `readCodexMcpServers` was swallowed,
   returning an empty server map. A hand-edited config containing
   risky settings produced `rating: "none"`, `findingCount: 0`.
   Surface as a high-severity `scope_trail.codex_config_syntax_error`
   and short-circuit the rest of the Codex detector (partial parses
   produce noise, not signal).

2. **Malformed .mcp.json / .claude/settings.json crashed the CLI.**
   `JSON.parse` in `readJsonObjectWithSource` had no try/catch — a
   syntax error escaped, the CLI exited 1 with a raw SyntaxError, and
   the report pipeline + `fail-on` semantics were bypassed entirely.
   Wrap parsing; return `{ json: {}, text: raw, parseError }`. Each
   JSON-reading detector now emits a `*_config_syntax_error` finding
   at first contact:
   - `scope_trail.mcp_config_syntax_error` (high) — active configs
   - `scope_trail.mcp_sample_config_syntax_error` (low) — samples
   - `scope_trail.claude_settings_syntax_error` (high)

3. **Codex `[projects.*]` sections collapsed to one bucket.**
   `normalizeSection` mapped `projects.<path>` → `projects` and
   `normalizeKey` produced `projects.trust_level` for any project,
   so Map keys overwrote. A second new trusted project went
   undetected when a first trusted project already existed.
   Replace with a `readTrustedProjects(root)` helper that iterates
   `parseToml(text).projects` and emits one finding per
   newly-trusted project path. Subject now includes the path
   (`projects.<path>.trust_level`) so reviewers see which project
   changed.

4. **IPv6 loopback `[::1]` was treated as remote.**
   `new URL('http://[::1]:3000').hostname` returns `[::1]` with
   brackets in Node, but the exclusion list only had `::1` without.
   Local IPv6 MCP endpoints were getting flagged as remote.
   Include `[::1]` alongside `::1`.

Regression tests for all four. Existing
`detects Codex config permission drift` test updated for the new
per-path subject format.

Test count: 54 → 59.
@Conalh Conalh merged commit 084b6b6 into main May 22, 2026
3 checks passed
@Conalh Conalh deleted the config-syntax-and-endpoint-hardening branch May 22, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant