Skip to content

feat(security): harden query, serve, and validate read surfaces#180

Merged
SutuSebastian merged 7 commits into
mainfrom
fix/security-hardening-wave1
Jun 11, 2026
Merged

feat(security): harden query, serve, and validate read surfaces#180
SutuSebastian merged 7 commits into
mainfrom
fix/security-hardening-wave1

Conversation

@SutuSebastian

@SutuSebastian SutuSebastian commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Close the formatted-query query_only gap: printFormattedQuery routes through queryRows, with E2E DML guards across sarif/badge/mermaid/annotations/codeclimate.
  • Require --token on non-loopback codemap serve binds (enforced in CLI + runHttpServer); treat full 127.0.0.0/8 as loopback for token policy.
  • Harden codemap validate with per-row rejected status + reason for paths that escape the project root, resolve outside via symlink, or are broken symlinks — reads go through readUtf8WithinProjectRoot (realpath re-check before read).
  • Add program docs (orchestrator + PR 2/3 plans) and consumer-surface parity (CLI help, MCP, glossary, agent-content, changeset).

Test plan

  • bun test src/cli/cmd-query-formatted.test.ts src/cli/cmd-serve.test.ts src/cli/cmd-validate.test.ts src/application/path-containment.test.ts src/application/serve-bind-policy.test.ts
  • Pre-commit hook green on all commits
  • CI green on PR

Summary by CodeRabbit

Release Notes

  • New Features

    • codemap validate now reports rejected status with detailed reasons for unsafe paths (escaping project root, symlink traversals, broken symlinks).
  • Bug Fixes

    • codemap query --format now enforces the same read-only protection as --json, blocking mutations.
    • codemap serve requires --token for non-loopback hosts; loopback addresses (127.0.0.0/8) remain optional.
    • Enhanced path validation detects and rejects symlink-based escapes and TOCTOU vulnerabilities.
  • Documentation

    • Updated help text and guides to reflect stricter authentication and expanded validation statuses.

Close the formatted-query query_only gap, require --token on non-loopback
serve binds, and reject validate paths that escape the project root or
symlink outside it.
Add changeset and serve-bind-policy with runHttpServer enforcement;
align validate/serve consumer surfaces (CLI help, MCP, glossary, README,
agent-content); extend symlink containment tests.
Add realpath-safe validate reads, broken-symlink rejection, 127.0.0.0/8
loopback token policy, expanded DML/format tests, and consumer-surface parity.
@changeset-bot

changeset-bot Bot commented Jun 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2e4cdfc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@stainless-code/codemap Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@SutuSebastian, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 13 minutes and 30 seconds. Learn how PR review limits work.

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a941f490-5a6a-4938-9b34-d239b0ce147b

📥 Commits

Reviewing files that changed from the base of the PR and between d4589db and 2e4cdfc.

📒 Files selected for processing (16)
  • .agents/skills/harden-pr/LEDGER.md
  • .agents/skills/harden-pr/SKILL.md
  • .changeset/read-surface-hardening.md
  • docs/architecture.md
  • docs/glossary.md
  • docs/plans/security-hardening-orchestrator.md
  • docs/roadmap.md
  • src/application/http-server.ts
  • src/application/serve-bind-policy.test.ts
  • src/application/serve-bind-policy.ts
  • src/cli/cmd-mcp.ts
  • src/cli/cmd-query-formatted.test.ts
  • src/cli/cmd-serve.test.ts
  • src/cli/cmd-serve.ts
  • src/cli/cmd-validate.test.ts
  • templates/agent-content/skill/10-recipes-context.md
📝 Walkthrough

Walkthrough

This PR hardens codemap's read-surface by enforcing read-only guards on formatted queries, requiring authentication tokens for non-loopback HTTP binds, and rejecting unsafe file paths that traverse symlinks or escape the project root.

Changes

Read-surface security hardening

Layer / File(s) Summary
Serve bind token policy
src/application/serve-bind-policy.ts, src/application/serve-bind-policy.test.ts, src/application/http-server.ts, src/cli/cmd-serve.ts, src/cli/cmd-serve.test.ts, src/cli/bootstrap.ts
New module implements loopback-host detection (IPv4 127.x.x.x, IPv6 ::1, localhost) and enforces token requirement for non-loopback binds. HTTP server validates bind policy at startup via assertServeBindRequiresToken. CLI parser validates --host/--token combinations early. Tests cover loopback variants and error cases.
Validate path safety with rejected status
src/application/path-containment.ts, src/application/path-containment.test.ts, src/test/symlink-capable.ts, src/application/validate-engine.ts, src/application/mcp-server.ts, src/cli/cmd-validate.ts, src/cli/cmd-validate.test.ts
New module detects symlink-based path traversal and realpath escapes via pathTraversesSymlinkOutsideRoot and pathRealpathEscapesProjectRoot. ValidateRow extended with rejected status and optional reason. computeValidateRows uses these checks to mark unsafe paths as rejected rather than attempting unsafe file reads. Tests cover directory traversal, symlink escapes, and broken symlinks.
Query format read-only enforcement
src/cli/cmd-query.ts, src/cli/cmd-query-formatted.test.ts
printFormattedQuery refactored to route through queryRows helper instead of opening its own database connection, ensuring formatted query output uses the same read-only PRAGMA query_only = 1 guard as --json queries. Test verifies DML mutations are blocked across multiple --format values.
Documentation, planning, and roadmap updates
.changeset/read-surface-hardening.md, README.md, docs/architecture.md, docs/glossary.md, docs/plans/security-hardening-orchestrator.md, docs/plans/security-hardening-wave1.md, docs/plans/impact-inpath-homonyms.md, docs/plans/runtime-test-isolation.md, docs/roadmap.md, templates/agent-content/skill/*
Changeset, README, architecture, glossary, and agent skill templates updated to document new semantics: token optional for loopback binds, required for non-loopback; validate now reports four statuses including rejected with specific reasons. Five planning documents added for security-hardening initiative covering orchestrator, wave-1 details, impact/inPath homonyms, runtime test isolation, and roadmap entry.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • stainless-code/codemap#35: The MCP server metadata update for the validate tool in this PR directly extends the prior PR that introduced the MCP server/tooling layer.
  • stainless-code/codemap#43: Both PRs touch codemap query --format execution (this PR refactors formatted query routing through queryRows with read-only guarding, while the referenced PR introduced the --format formatter plumbing).
  • stainless-code/codemap#44: Both PRs harden the codemap serve HTTP implementation—the referenced PR introduced HTTP server and CSRF machinery, and this PR further hardens it with loopback-aware token enforcement and centralized host-validation logic.

Poem

🐰 Three surfaces now shine bright with care,
Query guards with PRAGMA flair,
Token walls guard loopback's gate,
Symlink-safe paths navigate,
Read-surface hardened, secure, and fair! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(security): harden query, serve, and validate read surfaces' directly and clearly summarizes the main changes: security hardening across three key surfaces (query, serve, and validate). It aligns with the PR objectives and the substantial code changes across these areas.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/security-hardening-wave1

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/application/serve-bind-policy.ts`:
- Around line 13-16: isLoopbackHost currently treats the bracketed IPv6 literal
"[::1]" as valid loopback, but server.listen expects unbracketed "::1"; update
isLoopbackHost (or the caller that passes opts.host to server.listen) to
normalize bracketed IPv6 by converting "[::1]" to "::1" before returning/using
it, or remove "[::1]" from the accepted values so callers must normalize.
Specifically, modify isLoopbackHost (and/or the code that forwards opts.host to
server.listen) to strip surrounding brackets from IPv6 literals (e.g., transform
"[::1]" -> "::1") so server.listen receives a non-bracketed IPv6 address.

In `@src/cli/cmd-query-formatted.test.ts`:
- Around line 1-4: Update the top-of-file header comment in
src/cli/cmd-query-formatted.test.ts to accurately describe the test scope:
replace the phrase "on the sarif path" with wording that indicates multiple
formatted-output paths are covered (e.g., "on the formatted output paths
(`sarif`, `badge`, `mermaid`, `annotations`, `codeclimate`)") so the comment for
the test file accurately reflects that DML/blocking via queryRows and PRAGMA
query_only is asserted across all those formats.

In `@src/cli/cmd-validate.test.ts`:
- Around line 201-214: Replace the fixed temp directory creation in the "rejects
absolute paths outside the project root" test with a unique tmp dir created via
mkdtempSync (use os.tmpdir()/mkdtempSync) and ensure cleanup happens in a
finally block; update the test to write the outsideFile inside that mkdtempSync
directory, call computeValidateRows(db, tmpRoot, [outsideFile]) as before, and
rmSync the mkdtemp-created directory in the finally to avoid cross-run
collisions and flaky cleanup.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 027384fd-df05-4b01-b7a6-ec40b41530b2

📥 Commits

Reviewing files that changed from the base of the PR and between 8595173 and d4589db.

📒 Files selected for processing (26)
  • .changeset/read-surface-hardening.md
  • README.md
  • docs/architecture.md
  • docs/glossary.md
  • docs/plans/impact-inpath-homonyms.md
  • docs/plans/runtime-test-isolation.md
  • docs/plans/security-hardening-orchestrator.md
  • docs/plans/security-hardening-wave1.md
  • docs/roadmap.md
  • src/application/http-server.ts
  • src/application/mcp-server.ts
  • src/application/path-containment.test.ts
  • src/application/path-containment.ts
  • src/application/serve-bind-policy.test.ts
  • src/application/serve-bind-policy.ts
  • src/application/validate-engine.ts
  • src/cli/bootstrap.ts
  • src/cli/cmd-query-formatted.test.ts
  • src/cli/cmd-query.ts
  • src/cli/cmd-serve.test.ts
  • src/cli/cmd-serve.ts
  • src/cli/cmd-validate.test.ts
  • src/cli/cmd-validate.ts
  • src/test/symlink-capable.ts
  • templates/agent-content/skill/10-recipes-context.md
  • templates/agent-content/skill/50-maintenance.md

Comment thread src/application/serve-bind-policy.ts
Comment thread src/cli/cmd-query-formatted.test.ts
Comment thread src/cli/cmd-validate.test.ts
Adds missing-test eval fixture, LEDGER.md, vet/reconcile/quick modes,
score-probe recall scorer, and test:harden-probes smoke. Live probe run:
recall 1.0 on golden finding.
Keep harden-pr skill, LEDGER.md, and tracer-bullets wiring; remove
fixtures/harden-probes, score-probe harness, and related docs.
Strip [::1] to ::1 in parseServeRest and runHttpServer; tighten test
hygiene and formatted-query test header per review.
Align validate reason docs across consumer surfaces, extend formatted-query
DML coverage to diff formats, retire security-hardening-wave1 plan with
orchestrator/roadmap updates.
@SutuSebastian SutuSebastian merged commit a5caca8 into main Jun 11, 2026
11 checks passed
@SutuSebastian SutuSebastian deleted the fix/security-hardening-wave1 branch June 11, 2026 05:40
@github-actions github-actions Bot mentioned this pull request Jun 11, 2026
SutuSebastian added a commit that referenced this pull request Jun 11, 2026
Delete orchestrator plan and check off roadmap now that #180#182 are shipped.
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