Skip to content

fix: safely classify PostHog command wrapper reads - #109

Merged
mohanagy merged 4 commits into
developmentfrom
fix/106-posthog-command-wrapper-scheduling
Jul 20, 2026
Merged

fix: safely classify PostHog command wrapper reads#109
mohanagy merged 4 commits into
developmentfrom
fix/106-posthog-command-wrapper-scheduling

Conversation

@mohanagy

@mohanagy mohanagy commented Jul 20, 2026

Copy link
Copy Markdown
Owner

What changed

Fixes #106, fixes #107, fixes #108, fixes #110, fixes #114.

Miftah now recognizes the strict PostHog command-wrapper grammar only when the configured upstream is the literal canonical endpoint https://mcp.posthog.com/mcp. Read/discovery commands can run under destructive-routing safeguards without a per-user routing rule.

The change also:

  • classifies malformed, shell-like, unknown, noncanonical, and generic exec commands as destructive;
  • preserves local override and trusted-annotation precedence;
  • shares the existing risk-name patterns between the outer classifier and nested command adapter, preventing classification drift;
  • shares the local policy-enforcement check between real calls and miftah_route_preview, so preview no longer reports allow when the real call is blocked;
  • keeps command text out of the added audit metadata;
  • fixes the preset changelog-contract test so a valid nonempty Unreleased section does not hide historical release-note assertions;
  • rejects an explicit :443 port rather than relying on URL normalization;
  • documents every new or materially changed security-sensitive helper, including the fail-closed parser and literal origin boundary.

Root cause

The official PostHog MCP exposes a generic exec wrapper. Miftah correctly treated the unknown outer name as destructive, but that blocked documented read commands. Route preview evaluated policy without the subsequent explicit-routing enforcement step, so it could disagree with an actual call.

Validation

  • npm test — 1,063 passed, 22 platform-gated skips
  • npm run test:core
  • npm run test:coverage — 1,063 passed, 95.49% lines / 92.03% branches
  • npm run lint
  • npm run typecheck
  • npm run build
  • npm run smoke:cli
  • npm run check:pack
  • npm run test:package

Focused coverage includes canonical read behavior, write/destructive/malformed rejection, noncanonical query and explicit-port rejection, override precedence, preview/actual enforcement parity, audit redaction, and documented helper contracts.

Summary by CodeRabbit

  • New Features
    • Improved policy-aware routing for PostHog command-wrapper calls at the official MCP endpoint with fail-closed handling for malformed, nested, or unrecognized forms.
    • Route previews now include richer policy decision details plus enforcement results, aligned with real tool calls.
    • Added argument-aware risk metadata for previewing and enforced precedence that can be superseded by local tooling risk overrides.
  • Documentation
    • Updated configuration, security, and architecture docs to clarify preview/contract details and stricter trust-annotation and adapter scope rules.
  • Tests
    • Expanded coverage for command classification, trust-boundary enforcement, preview alignment, and precedence behavior.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: de5b778b-d413-4238-9969-ad031b4b3e0a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Miftah adds strict PostHog command-wrapper risk classification, integrates argument-aware metadata into calls and route previews, and centralizes policy enforcement. Tests and documentation cover trusted canonical commands, fail-closed invalid cases, local overrides, and changelog contracts.

Changes

PostHog command risk and enforcement

Layer / File(s) Summary
Bounded command parsing and risk classification
src/policy/posthog-command-wrapper.ts, src/policy/risk-classifier.ts, src/policy/risk-name-patterns.ts, src/policy/policy-types.ts, tests/posthog-command-wrapper.test.ts
Recognized PostHog discovery and call commands receive risk levels; malformed or unsupported commands remain destructive and use the trusted-command-adapter source.
Shared enforcement and route-preview integration
src/mcp/server/operation-pipeline.ts, src/mcp/server/miftah-server.ts
Tool calls and route previews use argument-derived PostHog metadata and the shared policy-enforcement evaluator.
Wrapper integration and regression coverage
tests/fixtures/fake-upstream.mjs, tests/mcp-wrapper.test.ts
Tests cover canonical reads, blocked mutations, untrusted origins, and local risk overrides using a command-wrapper fixture.
Security and documentation contracts
docs/config.md, docs/security.md, docs/architecture.md, CHANGELOG.md, tests/*docs*, tests/preset-docs-contract.test.ts
Documentation and contract tests describe the canonical adapter scope, bounded grammar, preview response, shared enforcement, and fail-closed behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

  • mohanagy/miftah#60: Modifies the same routing-preview flow and routing-context evidence plumbing.
  • mohanagy/miftah#64: Modifies the same tool risk-classification pipeline and risk-source handling.

Poem

A rabbit hops through commands so tight,
“tools” and “search” are judged just right.
Unknown paths meet a cautious gate,
Preview and calls share the same fate.
Safe reads pass; wild writes stay low—
Audit carrots sparkle in a row!


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Docstring Coverage ❌ Error Docstring coverage is 20.00% 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
Title check ✅ Passed The title is concise and describes the main change: safer PostHog command-wrapper read classification.
Description check ✅ Passed It includes a clear summary, security notes, and validation results, though it doesn't use the template's exact headings.
Linked Issues check ✅ Passed The changes address #106, #107, #108, #110, and #114 with matching code, tests, and docs for classification, preview parity, ports, and coverage.
Out of Scope Changes check ✅ Passed The diff stays within the stated PostHog policy, docs, and test-contract work; no unrelated changes are evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/106-posthog-command-wrapper-scheduling

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

@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: 1

🤖 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/policy/posthog-command-wrapper.ts`:
- Around line 9-11: Extract destructivePattern, writePattern, and readPattern
from src/policy/risk-classifier.ts lines 5-7 into a shared module such as
src/policy/risk-patterns.ts, then import and reuse them in both
src/policy/risk-classifier.ts lines 5-7 and
src/policy/posthog-command-wrapper.ts lines 9-11; remove the duplicate
declarations while preserving the existing regex behavior.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3076e4cf-2cef-4314-87c0-fece4c94adbb

📥 Commits

Reviewing files that changed from the base of the PR and between 6f0a17d and 0bff102.

📒 Files selected for processing (14)
  • CHANGELOG.md
  • docs/architecture.md
  • docs/config.md
  • docs/security.md
  • src/mcp/server/miftah-server.ts
  • src/mcp/server/operation-pipeline.ts
  • src/policy/policy-types.ts
  • src/policy/posthog-command-wrapper.ts
  • src/policy/risk-classifier.ts
  • tests/fixtures/fake-upstream.mjs
  • tests/mcp-wrapper.test.ts
  • tests/posthog-command-wrapper.test.ts
  • tests/preset-docs-contract.test.ts
  • tests/risk-classification-docs-contract.test.ts

Comment thread src/policy/posthog-command-wrapper.ts Outdated

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Review-state note for #110: the only inline finding is resolved by CodeRabbit on commit 57f6e2e, and the CodeRabbit status check is successful. GitHub still retains the original CHANGES_REQUESTED review object anchored to 0bff102. Requesting a fresh current-head review so the review state reflects the resolved thread.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

@mohanagy: Triggering a fresh review of the current head to refresh the review state.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/mcp/server/miftah-server.ts (1)

1526-1539: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Recognize one-entry named upstream configurations in cold previews.

With upstreams: { posthog: ... } containing one canonical PostHog endpoint, this returns no metadata because config.upstream is absent. A later discovered exec target carries its named upstream and can classify the same command as read, so preview and invocation can disagree. Derive the sole configured upstream name when config.upstreams has exactly one entry; keep multi-upstream previews conservative.

🤖 Prompt for 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.

In `@src/mcp/server/miftah-server.ts` around lines 1526 - 1539, Update
isOfficialPosthogCommandToolName to derive the sole configured upstream name
from config.upstreams when it contains exactly one entry, then pass that name to
isOfficialPosthogCommandUpstream for cold-preview classification. Preserve the
existing config.upstream behavior, and remain conservative by returning no
metadata when multiple named upstreams are configured.
🤖 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.

Outside diff comments:
In `@src/mcp/server/miftah-server.ts`:
- Around line 1526-1539: Update isOfficialPosthogCommandToolName to derive the
sole configured upstream name from config.upstreams when it contains exactly one
entry, then pass that name to isOfficialPosthogCommandUpstream for cold-preview
classification. Preserve the existing config.upstream behavior, and remain
conservative by returning no metadata when multiple named upstreams are
configured.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d276e7ca-3076-40f5-93b1-d3b89f1c9e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 57f6e2e and 7b12551.

📒 Files selected for processing (4)
  • src/mcp/server/miftah-server.ts
  • src/mcp/server/operation-pipeline.ts
  • src/policy/posthog-command-wrapper.ts
  • src/policy/risk-classifier.ts

@mohanagy

Copy link
Copy Markdown
Owner Author

Follow-up ticket #116 is fixed in 1a1e0c3. It adds cold-preview parity for exactly one named PostHog upstream and preserves conservative behavior for multiple named upstreams. Focused regression, parser tests, typecheck, lint, and build pass. @coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

@mohanagy: Reviewing the current changes, with attention to cold-preview parity for the single named PostHog upstream and fail-closed behavior when multiple named upstreams are configured.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment