Skip to content

fix: 6 proactive bugs in wayfind_runner, map_step_runner, and settings deny globs - #403

Merged
azalio merged 1 commit into
mainfrom
claude/compassionate-cerf-36jera
Aug 7, 2026
Merged

fix: 6 proactive bugs in wayfind_runner, map_step_runner, and settings deny globs#403
azalio merged 1 commit into
mainfrom
claude/compassionate-cerf-36jera

Conversation

@azalio

@azalio azalio commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Summary

Proactive bug audit of recently changed files surfaced 6 actionable issues. All fixes are in the jinja source files and propagated via make render-templates.

Bug 3 — wayfind_runner: absolute path inside map dir bypassed containment check

_resolve_evidence_path now rejects absolute paths before constructing the candidate path. On POSIX, Path(base) / "/absolute/path" discards base, so an absolute path pointing inside the map dir previously passed the containment check and was stored verbatim in state.json, breaking all markdown link targets in map.md, handoff.md, and ticket files.

Bug 4 — wayfind_runner: graduated fog entry accepted as from_fog

add_ticket now validates that the from_fog fog entry has status == "open" before accepting it. Previously a graduated or retired fog ID could be re-used as a from_fog source.

Bug 6 — map_step_runner: OSError from _resolve_subtask_diff_base escaped validate_mutation_boundary

_resolve_subtask_diff_base was called outside the try/except (OSError, TimeoutExpired) block, so subprocess failures (e.g. git not on PATH) propagated as uncaught exceptions instead of returning {"status": "error"}. Moved the call inside the try block.

Bug 7 — map_step_runner: record_scope_baseline wrote non-atomically

Baseline JSON is now written atomically via _write_json_file() (temp-file + replace()). Also renamed the loop-shadowing variable path to baseline_path.

Bug 8 — map_step_runner: porcelain-quoted paths with spaces lost from actual/baseline

git status --porcelain v1 double-quotes paths containing spaces (e.g. ?? "file with spaces.txt"). Both validate_mutation_boundary and record_scope_baseline now strip surrounding quotes so such files are correctly included in actual_set and the scope baseline.

Security Gap 12 — settings.json: Write and MultiEdit deny globs were missing

Claude Code treats Edit, Write, and MultiEdit as distinct tools — an Edit(...) deny rule does not block Write(...). The previous settings had only Edit(...) patterns for .env*, *credentials*, and *secret* files. Added matching Write(...) and MultiEdit(...) patterns for all 11 sensitive globs (33 new deny rules total, up from 11 Edit-only).

Changes

  • src/mapify_cli/templates_src/map/scripts/wayfind_runner.py.jinja — Bugs 3, 4
  • src/mapify_cli/templates_src/map/scripts/map_step_runner.py.jinja — Bugs 6, 7, 8
  • src/mapify_cli/templates_src/settings.json.jinja — Security Gap 12
  • Generated trees updated via make render-templates (.claude/, .map/scripts/, src/mapify_cli/templates/)
  • tests/test_wayfind_runner.py — regression tests for Bugs 3, 4
  • tests/test_map_step_runner.py — regression tests for Bugs 6, 8
  • tests/test_settings_deny_globs.py — regression tests for Security Gap 12

Test plan

  • uv run pytest tests/test_wayfind_runner.py::TestEvidencePathContainment — 9 passed (includes new Bug 3 test)
  • uv run pytest tests/test_wayfind_runner.py::TestFogGraduation — passes (includes new Bug 4 test)
  • uv run pytest tests/test_map_step_runner.py::TestValidateMutationBoundary — 18 passed (includes new Bug 6, 8 tests)
  • uv run pytest tests/test_settings_deny_globs.py — 148 passed (includes new Write/MultiEdit tests)
  • uv run pytest — 4318 passed, 4 skipped
  • make lint — ruff, mypy, pyright all clean

Generated by Claude Code

Summary by CodeRabbit

  • Security

    • Expanded protection for environment, credential, and secret files by blocking additional modification operations.
  • Bug Fixes

    • Improved handling of quoted file paths, including paths containing spaces or special characters.
    • Added safer error handling when resolving comparison baselines.
    • Prevented absolute evidence paths from bypassing map-relative storage rules.
    • Prevented closed or completed fog entries from being reused when creating tickets.
  • Reliability

    • Improved baseline file creation and persistence for more consistent workflow behavior.

…s deny globs

Bug 3 (wayfind_runner): _resolve_evidence_path now rejects absolute paths
BEFORE constructing the candidate. On POSIX, Path(base) / "/abs/path"
discards base, so an absolute path inside the map dir previously passed the
containment check and was stored verbatim in state.json, breaking all markdown
link targets.

Bug 4 (wayfind_runner): add_ticket now validates that the from_fog entry has
status "open" before accepting it. Previously a graduated or retired fog entry
could be re-used as a from_fog source.

Bug 6 (map_step_runner): _resolve_subtask_diff_base is now called INSIDE the
try/except (OSError, TimeoutExpired) block in validate_mutation_boundary so
subprocess OSErrors (e.g. git not on PATH) are caught and returned as
status="error" rather than propagating as an uncaught exception.

Bug 7 (map_step_runner): record_scope_baseline now writes the baseline JSON
atomically via _write_json_file() (temp-file + replace) and renames the
loop-shadowing variable `path` to `baseline_path` to avoid confusion.

Bug 8 (map_step_runner): validate_mutation_boundary and record_scope_baseline
now strip surrounding double-quotes from git porcelain v1 entries so files
with spaces in their names (e.g. "file with spaces.txt") are correctly
included in actual_set and the baseline, rather than being stored with literal
quote characters.

Security Gap 12 (settings.json): Write(**) and MultiEdit(**) deny patterns
now mirror the Edit(**) patterns for .env*, *credentials*, and *secret* files.
Claude Code treats Edit, Write, and MultiEdit as separate tools; the previous
settings only denied Edit operations on these sensitive file globs.

All changes implemented as jinja source edits and propagated via
make render-templates. Tests added for all 6 fixes across
test_wayfind_runner.py, test_map_step_runner.py, and test_settings_deny_globs.py.
4318 tests pass, lint clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJ7HcC1k6tCEm5qSuGHcg1
@azalio
azalio merged commit db028b6 into main Aug 7, 2026
1 of 2 checks passed
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d448354-6afc-4b39-82db-457592c59ec3

📥 Commits

Reviewing files that changed from the base of the PR and between b7059f5 and 1a5a649.

📒 Files selected for processing (12)
  • .claude/settings.json
  • .map/scripts/map_step_runner.py
  • .map/scripts/wayfind_runner.py
  • src/mapify_cli/templates/map/scripts/map_step_runner.py
  • src/mapify_cli/templates/map/scripts/wayfind_runner.py
  • src/mapify_cli/templates/settings.json
  • src/mapify_cli/templates_src/map/scripts/map_step_runner.py.jinja
  • src/mapify_cli/templates_src/map/scripts/wayfind_runner.py.jinja
  • src/mapify_cli/templates_src/settings.json.jinja
  • tests/test_map_step_runner.py
  • tests/test_settings_deny_globs.py
  • tests/test_wayfind_runner.py

📝 Walkthrough

Walkthrough

The change hardens Git path parsing and error handling, rejects unsafe evidence paths, restricts fog ticket sources to open entries, and expands sensitive-file deny rules for Write and MultiEdit operations.

Changes

Validation and sensitive-file hardening

Layer / File(s) Summary
Mutation boundary path and error handling
.map/scripts/map_step_runner.py, src/mapify_cli/templates/map/scripts/map_step_runner.py, src/mapify_cli/templates_src/map/scripts/map_step_runner.py.jinja, tests/test_map_step_runner.py
Git porcelain paths are unquoted before comparison. Baseline files use _write_json_file. Subtask diff-base errors are handled by the existing error path. Regression tests cover quoted paths and OSError handling.
Wayfinding evidence and fog validation
.map/scripts/wayfind_runner.py, src/mapify_cli/templates/map/scripts/wayfind_runner.py, src/mapify_cli/templates_src/map/scripts/wayfind_runner.py.jinja, tests/test_wayfind_runner.py
Absolute evidence paths are rejected. from_fog must reference an existing open fog entry. Regression tests cover absolute paths and graduated fog entries.
Sensitive-file write restrictions
.claude/settings.json, src/mapify_cli/templates/settings.json, src/mapify_cli/templates_src/settings.json.jinja, tests/test_settings_deny_globs.py
The settings deny list blocks Write and MultiEdit for .env, credential, and secret files across supported extensions. Tests cover root and subdirectory paths.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

  • Issue 402: The pull request implements the fixes and regression tests described by the issue.

Possibly related PRs

Poem

I hop through quoted paths with care,
And guard the secrets hidden there.
Old fog fades; open fog stays,
Safe little tickets find their ways.
The burrow’s rules now firmly glow.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/compassionate-cerf-36jera

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

2 participants