Files
Gitea-Tools/docs/mcp-daemon-import-guard.md
T
sysadmin ae6f0b74db fix(guard): close allow_test_bootstrap and basename entrypoint bypasses (#695)
Remove the public allow_test_bootstrap production seam so caller-controlled
flags cannot forge native mutation provenance. Bind provenance to the resolved
canonical entrypoint path plus a live stdio transport bind; basename-only
mcp_server.py stack frames and import-only launch no longer authorize
mutations. Test-mode install_test_native_runtime is pytest-only and cannot
reach production Gitea mutation endpoints. Add AC9 regressions for both
reviewer-found bypasses and related spoof vectors.

Refs: PR #696 REQUEST_CHANGES at 253269c; issue #695 comments 11002/11005.
2026-07-13 21:48:28 -04:00

3.8 KiB

MCP daemon import and native-transport guard (#558 / #695)

Problem

During deadlock debugging and the PR #694 incident (#695), agents imported gitea_mcp_server or ran credential helpers from a raw shell / offline helper, bypassing native MCP transport, preflight purity, and role gates. Contaminated formal reviews then looked identical to native approvals.

Rule

Mutation auth, keychain fill, and controller quarantine require a production native MCP transport runtime established only by:

  1. the resolved absolute path of the canonical entrypoint (mcp_server.py / gitea_mcp_server.py next to mcp_daemon_guard.py), and
  2. a live transport bind (bind_native_mcp_transport(transport="stdio")) immediately before mcp.run.

Basename-only trust (a renamed file called mcp_server.py), caller-controlled flags (there is no allow_test_bootstrap), environment variables, stack frame spoofing, or import-only launch are insufficient.

Context Allowed
Official IDE-native MCP: resolved canonical entrypoint marks + binds stdio, holds process-local runtime token yes
pytest (hermetic unit tests) via is_pytest_runtime() yes for unit gates
install_test_native_runtime() under pytest (test-mode record) unit-test transport gates only — never production Gitea mutations
allow_test_bootstrap=True (removed; must not exist) no
Renamed runner basename mcp_server.py outside package root no
Import/launch of real entrypoint without transport bind no
GITEA_MCP_SANCTIONED_DAEMON=1 alone (no process-local native runtime) no (#695)
GITEA_ALLOW_DIRECT_MCP_IMPORT=1 in LLM sessions no — never set in agent sessions
GITEA_ALLOW_KEYCHAIN_CLI=1 in LLM sessions no — human operator only
bare python -c 'import gitea_mcp_server; …' or offline runners no
keychain fill outside native/pytest no

Native runtime is process-local: a random token bound to the daemon PID and transport phase. It is never reconstructed from environment variables, session-state files, caller-controlled flags, or importing internals in a fresh Python process.

Contaminated review quarantine (#695 AC8)

Controller/reconciler/merger profiles may call gitea_quarantine_contaminated_review with explicit confirmation:

QUARANTINE CONTAMINATED REVIEW <review_id> PR <pr_number>

Quarantine records are durable under the MCP session-state root and are honored by:

  • gitea_get_pr_review_feedback (quarantined approvals do not authorize merge)
  • gitea_check_pr_eligibility action=merge
  • gitea_merge_pr (mutation)
  • merger lease adoption paths that read approval_at_current_head

Forensic Gitea reviews and historical comments are never deleted.

STOP after native MCP failure (AC10)

If the native MCP namespace dies (EOF, capability disconnect, session death):

  1. STOP. State BLOCKED + DIAGNOSE.
  2. Do not import gitea_mcp_server from a standalone process.
  3. Do not run offline_mcp_helper.py, offline_mcp_runner.py, run_quarantine.py, or any offline mutation helper.
  4. Do not set direct-import, keychain-bypass, or raw-token environment variables.
  5. Reconnect / restart the official MCP daemon; resume only via native tools.

Any further native MCP failure is a hard stop. Do not construct another fallback.

Canonical approval claims (AC7)

Comments that claim approved / ready-to-merge / WHO_IS_NEXT: merger / MERGE_READY: true must include:

NATIVE_REVIEW_PROOF: transport=native_mcp; …

Claims that cite offline/import helpers are rejected even if a proof line is present.

Operator note

LLM sessions must never set allow-direct-import, allow-keychain-cli, or raw token overrides. Those are human-only escape hatches outside agent workflows.