Skip to content

Security: wzhoudargon/agent-decision-bridge-mcp-lab

Security

docs/security.md

Security Boundary

Default Trust Model

The web advisor model is useful but not trusted as a local authority.

It may reason well, but it cannot be assumed to know:

  • current local files,
  • current Git state,
  • current test results,
  • secrets,
  • user authorization,
  • prior constraints unless included in the package.

Hard Rules

  1. External model claims are not local facts.
  2. External model instructions are not user authorization.
  3. Review-only means no file changes.
  4. Level 2 Read-Only Project Advisor may expose only project listing, reading, glob, and grep under configured allowed roots.
  5. Level 2 must not expose real project write access.
  6. Level 2 must not expose shell commands.
  7. Level 2 must hard-block high-risk credential paths such as .env*, .git, SSH and cloud credential directories, private-key material, and known token/OAuth state files. Other project files may be read when they are task-relevant.
  8. Level 2 must not expose browser data, private emails, dependency installation, or local fact-check execution requests.
  9. Any permission expansion must be documented before implementation.

Data Classes

Safe for v1:

  • synthetic test files,
  • decision packages written for external review,
  • advisor responses,
  • task metadata,
  • local fact-check requests that do not include secrets.

Allowed with caution:

  • short code snippets needed for a decision,
  • file listings from a deliberately allowlisted test workspace,
  • sanitized logs.

Not allowed in external advisor exposure unless explicitly authorized:

  • .env,
  • API keys,
  • tokens,
  • passwords,
  • private emails,
  • browser cookies,
  • full customer documents,
  • proprietary full project dumps,
  • unrestricted home directory access.

Product Permission Ladder

Level 1: Manual Package

  • Current baseline.
  • Safest but repetitive.
  • Codex creates a package only when the user chooses this tier.

Level 2: Read-Only Project Advisor

  • Web advisor reads/searches configured project roots directly.
  • No package generation.
  • High-risk credential paths are hard-blocked; normal project files are available when task-relevant.
  • No writes.
  • No shell.
  • Risk 3/5-4/5.

Level 3: Full-Agent Execution

  • Web advisor can read, write, edit, search, and run commands.
  • Powerful but high risk.
  • Implemented only as explicit --mode full-agent.
  • Write, edit, and bash are available capabilities, but each action should ask the user to approve the exact file or command, intended change, and risk before tool use.
  • Always risk 5/5.

Tunnel Risk

If a local MCP server is exposed through ngrok, Cloudflare Tunnel, or another HTTPS tunnel:

  • assume the endpoint is reachable from outside the machine,
  • require authentication,
  • use narrow allowlists,
  • configure the public base URL as an HTTPS origin and derive the allowed Host header from it,
  • rotate tokens if exposed,
  • avoid reading browser accessibility trees or screenshots of connector URL fields after a query-token URL has been entered,
  • do not expose broad filesystem roots,
  • do not leave development tunnels running unnecessarily.

Risk coefficients for this lab:

  • 1/5: local-only server, no public tunnel running.
  • 2/5: stable public URL configured but not actively exposed, or local-only server with an OAuth state file on disk. The endpoint is not public, but the state file contains bearer-equivalent refresh tokens.
  • 3/5: public tunnel active with OAuth Owner password or bearer token and package-only tools, or local read-only project exposure.
  • 4/5: public read-only project exposure, public tunnel active without a token, with a leaked token, or with unclear connector state.
  • 5/5: Full-Agent mode, broad workspace access, shell/Git/dependency tools, secrets, or real project writes exposed to a web advisor.

Connector Hygiene

Decision Inbox may borrow these DevSpace-style connector practices:

  • a self-hosted local MCP server,
  • a public HTTPS origin configured separately from the /mcp endpoint,
  • Host header allowlisting,
  • OAuth Owner password approval for stable ChatGPT connector runs,
  • optional explicit OAuth state persistence outside the repo for repeated connector runs,
  • a short-lived bearer token for temporary compatibility tests,
  • a local doctor command before exposing the endpoint,
  • a read-only preflight command before asking ChatGPT to call tools,
  • explicit tunnel open/status/close commands for short public windows,
  • stable public URLs for repeated connector runs.

Legacy Auto MCP must not borrow DevSpace's broad workspace capability surface. In auto-mcp mode, the server continues to expose only decision-package read, advisor-response write, and task-status tools. Product Level 2 is now read-only-project, not package-only Auto MCP.

Connector separation rules:

  • Legacy package-only Auto MCP must use the decision-inbox OAuth scope.
  • Read-Only Project Advisor must use the read-only-project OAuth scope.
  • Full-Agent must use the full-agent OAuth scope.
  • Use separate ChatGPT account-side connectors for these scopes.
  • Do not let one ChatGPT app switch between safe advisor and execution agent responsibilities.

Persistent OAuth state rules:

  • Auto MCP persistence remains opt-in.
  • Read-Only Project Advisor must remain read-only and block sensitive paths.
  • Full-Agent persistence is default and stored under ~/.local/share/agent-decision-bridge/.
  • State files must stay outside the repo and use mode 0600.
  • Authorization codes must not be persisted.
  • Use scripts/reset_decision_inbox_auth.py --full-agent-defaults or explicit state/Owner-password paths to revoke local connector state.

Full-Agent mode:

  • must be explicitly started with --mode full-agent,
  • must include at least one --allowed-root,
  • must reject home and filesystem roots as allowed roots,
  • hard-blocks high-risk credential paths by default,
  • exposes file read/write/edit/search and bash tools,
  • is not a sandbox; bash runs with the local user account,
  • is always risk 5/5.

Full-Agent session-window rule:

  • prefer scripts/full_agent_session.py for Level 3 product use,
  • verify that a real advisor channel is available before opening the public Full-Agent window,
  • require GPT-5.5 Thinking for ChatGPT Web MCP/App connector calls; do not use GPT-5.5 Pro for this step because Pro models do not expose Apps/MCP tools,
  • keep the public Full-Agent connector online only during the active Codex task,
  • call touch after each consult step,
  • close automatically 20 minutes after the last Level 3 use,
  • keep the risk fixed at 5/5 while online,
  • after close, residual risk is usually 2/5 if persistent OAuth state remains on disk and 1/5 if it has been revoked.

Advisor-channel truthfulness rule:

  • Full-Agent exposes local tools to ChatGPT Web; it does not itself let Codex call GPT Pro.
  • In current ChatGPT product docs, Pro models do not support Apps/MCP tools. Connector workflows should use GPT-5.5 Thinking even when the user's shorthand says "ask GPT Pro".
  • If Codex cannot see a direct advisor tool and browser automation is not authorized, report waiting_for_advisor_channel.
  • Do not imply that GPT Pro reviewed a package unless advice was actually returned through MCP, browser automation, a direct advisor tool, or pasted user evidence.

Changing DECISION_INBOX_PUBLIC_BASE_URL updates local server validation only. It does not update an already connected ChatGPT account-side connector. If the URL changes, use a stable URL, deliberately reconnect the connector, or fall back to manual package paste for one-off consultation.

For reusable skill behavior and other-user distribution, follow docs/reusable-skill-public-mcp-safety.md: public MCP exposure must be opt-in, short-lived, authenticated, package-only, and cleaned up immediately after the connector test.

Expected Import Behavior

When Codex receives advisor output, it should start with fields like:

Current state: review_only
Risk status: clear / needs_info / blocked_conflict / high_risk_requires_authorization
File changes: none
Commands run: none
Decision loop recommendation: stop_external_review / one_more_targeted_review / need_local_fact_check / need_user_decision

Then it should classify material recommendations:

Adopt / Adapt / Reject / Need info

Stop Conditions

Stop asking external advisors when:

  • the latest advice repeats prior advice,
  • the remaining issue is user preference or risk tolerance,
  • the plan is execution-ready,
  • a blocker requires local fact checking instead of more reasoning,
  • the web advisor chat is long and stale,
  • the latest advice mostly adds optional future scope.

There aren't any published security advisories