Agent/MCP Audit Sprint

Self-owned dogfood audit report

jackjin1997/agentgap

No-execution dogfood sample for an agent config and MCP bridge. The review is based on commit ebaf3dfb07ab90b50a2879f3ce06bb37aeac2f65. It is not a commissioned audit, private vulnerability disclosure, or certification.

TargetAgent config and MCP bridge
ValidationStatic source review + scanner
Scanner Score42/100 heuristic score
ExecutionNo target code run

Scope

Out of scope: private agent configurations, real user tokens, running configured MCP servers, executing agentgap sync against a live workspace, and unpublished branches.

Executive Summary

agentgap is a good dogfood target because it turns one bridge.yaml into the files that coding agents read as instructions and MCP server configuration. That is useful tooling, but it means a bad or unreviewed config can change how multiple agents behave and which tools they can launch.

The repo is small and easier to reason about than a full agent product. The main risk is configuration supply-chain drift: syncing a project-local file can rewrite CLAUDE.md, AGENTS.md, Cursor rule files, and MCP server maps in one command.

Before positioning this as a reusable agent config bridge, it should make the trust boundary explicit: preview first, require an explicit apply path for writes, validate MCP transports and command shapes, normalize rule names, and add regression tests around file output and merge behavior.

Boundary Map

AreaEvidenceRisk Notes
Config sourceinternal/config/config.go:62-99, bridge.yaml:6-60bridge.yaml controls agent rules, MCP server command/args/env/url fields, and target agents.
Sync commandcmd/root.go:125-148agentgap sync calls SyncAll(false), so the default sync path writes files.
Agent instruction writesclaude.go:31-43, codex.go:30-42, cursor.go:30-53Rule content becomes future Claude, Codex, and Cursor instruction surface.
MCP config writesclaude.go:46-69, codex.go:45-68, cursor.go:56-79The tool merges and writes project MCP JSON for three agent clients.
MCP merge behaviorinternal/mcpio/mcpio.go:41-69Existing servers are preserved, but same-name servers from bridge.yaml replace existing entries. MCP JSON files are written 0600.
MCP server schemainternal/mcpio/mcpio.go:75-96Supported transports are mapped into JSON, while invalid or incomplete definitions need stronger rejection.
Example MCP config.cursor/mcp.json:21-27The sample includes my-custom-tool --port 8080; this needs documented bind/auth assumptions.
Validation gatespublic treeNo tests, CI workflow, or README were visible in the public tarball reviewed.

Findings

HighDefault sync writes agent instructions and MCP configs without a preview-first guardrail

Evidence: cmd/root.go:125-148 makes agentgap sync call SyncAll(false). The adapters write CLAUDE.md, AGENTS.md, Cursor rule files, and MCP JSON directly.

Recommended fix: make diff/preview the default and require an explicit apply flag for writes. Add backups and print same-name MCP server overwrites before applying changes.

MediumMCP server definitions need stricter validation before they become executable agent config

Evidence: internal/config/config.go:84-91 validates only the MCP server name and defaults an empty transport to stdio. internal/mcpio/mcpio.go:80-92 maps supported transports but does not surface errors for unknown or incomplete definitions.

Recommended fix: reject unknown transports, require command for stdio, require url for remote transports, warn on unpinned package runners, and redact env values in logs and diffs.

MediumRule names and prompt content need a clearer trust model

Evidence: internal/config/config.go:74-82 requires non-empty rule names and content, while internal/adapter/cursor/cursor.go:40-48 uses the rule name to build .cursor/rules/agentgap-<name>.mdc.

Recommended fix: normalize rule names to a conservative slug, reject path separators, detect duplicate normalized names, and add generated-file provenance with source path and content hash.

MediumExample port-based MCP config lacks transport exposure notes

Evidence: .cursor/mcp.json:21-27 includes a sample my-custom-tool command with --port 8080. The scanner flagged this as a remote listener signal; manual review did not confirm public network exposure from this alone.

Recommended fix: replace the sample with a clearly local-only example, or add docs for bind address, auth proxy, TLS, trusted clients, logging, and write-tool policy.

LowTests and CI are missing for a security-sensitive config writer

Evidence: no test files or .github/workflows entries were visible in the public tarball. The scanner also reported no obvious tests or CI.

Recommended fix: add Go tests for config validation, MCP server conversion, merge precedence, permissions, adapter output, and invalid config fixtures. Add CI for go test ./..., go vet ./..., and scanner output generation.

Positive Signals

Priority Fix Plan

  1. Make preview/diff the default path and require an explicit apply flag for writes.
  2. Add validation for transport, command, URL, duplicate names, and normalized rule slugs.
  3. Add backup and same-name overwrite reporting for MCP config merges.
  4. Add tests for adapter output, MCP JSON permissions, merge behavior, and invalid configs.
  5. Add CI with go test ./..., go vet ./..., and scanner report generation.

Example Validation Commands

node tools/agent-mcp-audit.mjs /path/to/agentgap --json
node tools/agent-mcp-audit.mjs /path/to/agentgap --sarif > agent-mcp-audit.sarif
go test ./...
go vet ./...
agentgap diff
agentgap sync --check

What the Paid Sprint Adds

The paid sprint would go deeper than this public dogfood sample: implementation-ready validation patches, fixture tests, CI workflow, safer sync UX, generated-file provenance, and a short operator guide for using bridge.yaml as trusted agent policy.