fix(mcp): stop tripping simple-git block-unsafe guard on every write#80
Merged
Conversation
simple-git >= 3.34 bundles @simple-git/argv-parser, whose block-unsafe guard rejects a git invocation when a guard-listed variable (EDITOR, GIT_ASKPASS, PAGER, GIT_SSH_COMMAND, ...) is passed EXPLICITLY through .env(). The transaction layer spread ...process.env into .env() to set the commit author, so once a transitive bump pulled simple-git to 3.36.0 every worktree write (content_save, model_save, merge) started failing with `Use of "EDITOR" is not permitted...` in any host that exports those variables (VS Code, Claude Code, CI). The guard only scans the object handed to .env(), never the inherited environment. - Commit identity now flows through `-c user.name`/`-c user.email` config (authorConfig) instead of .env(). These keys are on no unsafe list and git honours them for author + committer alike, so the guard is never touched. CONTENTRAIN_AUTHOR_NAME/EMAIL overrides preserved. - networkGit (push/fetch) legitimately needs the inherited askpass/SSH/ proxy environment, so it keeps .env() but opts out of the affected guard categories via `unsafe` (NETWORK_UNSAFE). Closes the same latent failure in contentrain_submit that the report missed. - Both concerns centralized in git/identity.ts so no future call site can reintroduce a process.env spread. simple-git pinned to ^3.36.0. Tests: tests/git/identity.test.ts (5) incl. a control asserting the old .env(process.env) path still trips the guard; existing tests/git suites (49) green; tsc + oxlint clean.
✅ Deploy Preview for contentrain-ai ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every worktree write (
content_save,model_save, merges) started failing on@contentrain/mcpwith:(or
GIT_ASKPASS,PAGER, …) in any host that exports those variables — VS Code, Claude Code, CI. No Contentrain code changed: a transitive bump pulledsimple-gitto>= 3.34, which now bundles@simple-git/[email protected]. Its block-unsafe guard rejects agitinvocation when a guard-listed variable (18 of them) is passed explicitly through.env(). The guard only scans the object handed to.env()— never the inherited process environment.The transaction layer spread
...process.envinto.env()to set the commit author, so the guard saw the host'sEDITOR/GIT_ASKPASSand refused to rungit commit.Fix
Centralized in a new
git/identity.tsso no future call site can reintroduce aprocess.envspread:-c user.name/-c user.emailconfig (authorConfig) instead of.env(). These keys are on no unsafe list and git honours them for author + committer alike, so the guard is never touched, regardless of what the host exports.CONTENTRAIN_AUTHOR_NAME/EMAILoverrides preserved.networkGit(push/fetch) legitimately needs the inherited askpass/SSH/proxy environment to authenticate, so it keeps.env()but opts out of the affected guard categories viaunsafe(NETWORK_UNSAFE), leaving arg-injection protections intact. This closes the same latent failure incontentrain_submitthat the initial diagnosis missed (third.env()spread).simple-gitpinned to^3.36.0so the dev tree matches the runtime and reproduces the guard.Three affected call sites
transaction.tscreateTransaction.env(authorEnv()){ config: authorConfig() }transaction.tsmergeBranch.env(authorEnv()){ config: authorConfig() }branch-lifecycle.tsnetworkGit.env({ ...process.env })+ unsafe: NETWORK_UNSAFEVerification
tests/git/identity.test.ts(5, new) — commits via config whileEDITOR/GIT_ASKPASSare set (guard not tripped) + author/committer correct; a control asserts the old.env(process.env)path still trips the guard;networkGit-style instance runs viaNETWORK_UNSAFEwith a matching control.tests/git/suites (49) green —transaction.test.ts(commit/merge/auto-merge/selectiveSync),branch-lifecycle+remote-branches(networkGit).tsc --noEmit0 errors ·oxlint0 warnings.🤖 Generated with Claude Code