Please report security issues privately via GitHub Security Advisories (or open a minimal issue asking for a private channel — do not include exploit details in a public issue). We aim to acknowledge within a few days.
mcagit is a local-first CLI. Its strongest guarantees hold when you run it on worlds and repositories you control. The notes below consolidate the trust assumptions so you can decide what is safe to expose.
- Path confinement. Untrusted relative paths — manifest keys, patch paths, and ref names that can arrive over the network — are confined with
PathGuard.Confine(root, rel)before any filesystem access, so a crafted name like../../HEADcannot escape the intended directory (checkout, patch apply, andrefs/heads/refs/tags/ remote-tracking writes). - Object-id validation. Object hashes must pass
ObjectStore.IsValidHash(64 lowercase hex) before they are turned into a path; a malicious id cannot address an arbitrary file. - Hash verification on receive.
ObjectStore.ImportRawre-hashes incoming objects, so a hostile remote cannot poison the store with mismatched content. - Resource caps. Inbound sizes are bounded (object inflate, server request body, frame length, packfile index count) and NBT recursion is capped (
NbtCanonical.MaxDepth) so a deeply nested or oversized payload cannot exhaust memory or stack. - Constant-time token compare. Server auth tokens are compared with
CryptographicOperations.FixedTimeEquals. - Non-destructive by construction.
diff/extract/statusnever modify a world;applyonly writes a fresh output directory; onlycheckout/reset --hard/merge/rebase/bisect/clean/stashtouch the bound worktree. - Inter-process lock.
commitandpushtake a repository lock so concurrent runs cannot race branch advancement.
- The built-in HTTP server has no TLS and a single shared push token. Reads are anonymous by default; pushes require
--allow-pushplus the token. Put it behind a reverse proxy forhttps, and treat the push token as a shared secret. There is no per-user auth or read token yet. serve-stdiotrusts the SSH layer. It runs over an authenticated SSH session and currently grants write to any caller that reaches it — confidentiality, integrity, and authorization are SSH's job (keys /authorized_keysrestrictions). Do not expose it to principals you would not give push access.- Cloud bucket objects are not encrypted at rest by mcagit. A world's NBT is recoverable by anyone who can read the bucket. Rely on the provider's server-side encryption and tight bucket ACLs, and scope credentials per backup. Client-side (record-level) encryption is future work — see
docs/cloud-backend.md. applyandcheckoutwrite files derived from patch / snapshot content. Path handling is confined (above), but only apply patches and check out repositories from sources you trust, as withgit.- Signatures are SSH-key based, not GPG.
commit -S/tag -ssign with an SSH key;tag -vverifies against an allowed-signers file. There is no web-of-trust.
mcagit is pre-1.0; security fixes land on main and ship in the next tagged release. Build self-contained binaries from a recent main for the latest fixes.