Announcing Beacon: Self-improving memory for coding agents
← All MCP servers
MCP server

io.github.wkoverfield/quilt

mcp:wkoverfield/quilt

Track which AI agent wrote which lines in a shared Git checkout; each commits only its own lines.

Verdict
Suspicious

Risky behavior the analysis could not rule out.

Analyzed Oct 26, 2026, 12:40 UTC at fc6b0a4

Dispute security verdict

If you believe this verdict is incorrect, submit a dispute and we'll review it.

2
findings
high
highest severity
2
threat classes
135
files scanned
1,395/1,395
checks satisfied
0
package advisories

Why this verdict

  • suspicious: finding mcp-server:.:src/transcripts.ts:139:RECON
  • suspicious: unverified finding mcp-server:.:src/gitguard.ts:1:PERSIST

Security findings 2

Persistence

highUnverifiedmedium confidence

Setup installs a git pre-commit hook shim at the repository's effective hooks path, which is a host-config write beyond the MCP tool surface; it is documented, fail-open, and chains any pre-existing hook.

The shim `quilt setup` installs at `.git/hooks/pre-commit`.
vector:code

Reconnaissance

infoContextual riskmedium confidence

Undeclared: the server locates and reads local Claude/Codex session transcripts (~/.claude/projects, ~/.codex) to extract the user's past prompts for attribution, a capability beyond coordination state; no off-host send is seen in this batch.

const root = options.claudeDir ?? process.env.QUILT_CLAUDE_DIR ?? join(homedir(), ".claude", "projects");
vector:code
Counter-argument considered

The best case against the finding is that the code is read-only and scoped to the actor's own session prefix and the repo cwd, with no network sink in this file. That does not refute it: the server still reads private Claude/Codex transcripts, nothing declares this, and the refutation would rest only on the absence of a chain. The finding stays a contextual risk.

Refuted findings 9

Candidates the review stage examined and rejected, kept for transparency.

Data exfiltration

criticalRefutedlow confidence

The CLI ships an undeclared telemetry subsystem whose daily heartbeat is on by default (opt-out, not opt-in), sending usage data off-host; the destination and payload are not visible in this batch.

Show or change anonymous usage telemetry (daily heartbeat on by default; command events opt-in)
Why it was refuted

The served telemetry.ts shows the heartbeat posts only an event name, version, platform, node major and a random UUID to PostHog. Nothing user-identifying or content-bearing is sent, and the behavior is openly declared in the command's own description and the setup disclosure. Kill switches are QUILT_TELEMETRY=0, DO_NOT_TRACK and `quilt telemetry off`.

Persistence

criticalRefutedmedium confidence

The setup command writes agent control-plane files (.claude/settings.json hooks and CLAUDE.md instructions) and a git pre-commit hook, which the server.json description (tracking authorship) does not mention, although the CLI help text and setup output disclose it.

const settingsPath = join(wsRoot, ".claude", "settings.json");
Why it was refuted

Writing capture hooks and the CLAUDE.md snippet is the declared purpose of the user-invoked `quilt setup` command, which is documented as a wiring command and supports --dry-run. That is the core capability, not a concealed persistence mechanism.

Data exfiltration

criticalRefutedmedium confidence

Ordinary CLI commands send a default-on daily telemetry heartbeat (version, OS, random id) off-host, which is not declared in server.json metadata, though setup prints a disclosure and offers opt-out.

if (name !== "setup") maybeSendHeartbeat();
Why it was refuted

The heartbeat call on ordinary commands sends only version, platform, node major and a random id, per buildEventPayload. Setup prints an unconditional disclosure that names exactly these fields and the opt-out, so the behavior is neither concealed nor harmful exfiltration.

Persistence

criticalRefutedmedium confidence

The onboarding module writes a coordination snippet into agent rules files (CLAUDE.md/AGENTS.md) and wires hooks and MCP config, including the user-global ~/.codex/hooks.json. This is the product's declared setup purpose, but it persistently alters agent control-plane files and steers future agent behavior.

Magical onboarding: detect the agent orchestrator in a repo and wire Quilt in
Why it was refuted

The module is the product's own setup step. It is explicit about what it writes, and its merges are additive and refuse to touch files that are not valid JSON. It writes only the product's own server entry, hooks and coordination snippet, so this is the declared core capability, not hidden persistence.

Data exfiltration

criticalRefutedmedium confidence

Undeclared usage telemetry: a default-on daily heartbeat (version, OS, node version, random id) is POSTed to PostHog via a detached child process, with the endpoint overridable by the QUILT_TELEMETRY_ENDPOINT env var; no declaration covers this, though the payload is coarse and an opt-out exists.

const endpoint = process.env.QUILT_TELEMETRY_ENDPOINT ?? POSTHOG_ENDPOINT;
Why it was refuted

The payload is a coarse, anonymous heartbeat. It is disclosed to users and can be turned off with QUILT_TELEMETRY=0, DO_NOT_TRACK or `quilt telemetry off`. The endpoint override is an env var that only the local user controls, so no sensitive data is exfiltrated.

Code execution

highRefutedlow confidence

`quilt update` spawns an install command (derived from detectInstallManager) with inherited stdio to self-update from the npm registry; it is user-invoked, but the command string comes from update.ts, which is not shown.

const res = spawnSync(argv[0]!, argv.slice(1), { stdio: "inherit" });
Why it was refuted

`quilt update` is an explicit, user-invoked subcommand whose declared purpose is updating Quilt to the latest published version. It does not run silently, and nothing in it contradicts that declaration.

Code execution

highRefutedlow confidence

The undeclared repoVisibility helper spawns the external `gh` CLI in the repo to query visibility (skippable with QUILT_NO_GH, 3s timeout); a benign-looking local probe, but not declared.

spawnSync("gh", ["repo", "view", "--json", "visibility", "-q", ".visibility"], {
Why it was refuted

The `gh` call uses fixed arguments with no agent or user input, a 3s timeout and a QUILT_NO_GH opt-out. Its output is reduced to public/private/null. It is a benign local probe with no harmful sink.

Data exfiltration

highRefutedmedium confidence

The server package ships telemetry that is on by default (a daily heartbeat to a PostHog endpoint with version, OS and a random id), which is not part of its declared coordination purpose; it is anonymous, documented in code, and has an opt-out.

The daily HEARTBEAT (version, OS, random id,
Why it was refuted

The heartbeat carries only version, OS and a random id. The code states a counts-never-content rule and provides opt-outs, so nothing sensitive leaves the host.

Data exfiltration

highRefutedmedium confidence

The dashboard page loads fonts from Google Fonts and Fontshare, contradicting the in-code claims 'nothing fetched remotely' and 'No remote state', which leaks the visitor's IP to third parties.

<link href="https://api.fontshare.com/v2/css?f[]=gambetta@500,600,700&f[]=switzer@400,500,600&display=swap" rel="stylesheet">
Why it was refuted

The page links static font stylesheets that the user's browser fetches. No session or repo data is sent to those hosts, so this is a stale comment, not exfiltration.

Coverage gaps 2

Parts of the artifact the static analysis could not fully examine.

unanalyzable_binary binary content is only byte-scanned
src/bashcapture.ts
unanalyzable_binary binary content is only byte-scanned
src/claims.ts