v3.4.1

Released September 19, 2026 · View on GitHub →

TL;DR — Security release: a repository's own .git/config could make git run a program of its choosing, and opening the folder was enough. Codeep now neutralises those settings on every git call it makes.

A follow-up to 3.4.0, from the same review applied to the macOS app: git reads settings from the repository it is run in, and several of them name a program git then runs. Codeep runs git by itself — the status line alone runs git status when a project opens — so a folder that arrived with its own .git (a zip, a tarball, a shared drive) could execute code before anything was typed. Reproduced, then closed, then attacked again over seven rounds of adversarial review with real git 2.54.

Security

git call Codeep makes now neutralises the settings that name a command — core.fsmonitor, content filters (filter.<driver>.clean/smudge/process), diff.external and diff drivers, textconv, merge drivers, the gpg.* cluster, credential.helper, core.sshCommand, core.askPass, core.gitProxy, interactive.diffFilter, trailer commands, submodule.<name>.update, remote.<name>.uploadpack and receivepack, uploadpack.packObjectsHook, core.alternateRefsCommand, every alias the repository defines, and the pager, editor and signature-display settings. Settings in your own global config are left alone.

/diff, @git, the review, execute_command, a skill's command steps, and the terminal an editor runs commands in over ACP.

in .git/modules/<name>/config, which the superproject's own config listing never shows.

out) now refuses the git call instead of running it unprotected, and GIT_CONFIG_PARAMETERS is removed from the environment so it cannot re-enable anything.

--git-dir, --work-tree, --exec-path, --config-env, --attr-source, and -c for include.path, includeIf.*.path, attr.tree or any key that names a program. git -C is allowed and the repository it points at is the one that gets checked.

confirmation mode, and fails when there is nobody to ask: anything under .git/, the hook directory the repository actually uses (including .githooks and .husky), .codeep/hooks/, .codeep/skills/, .codeep/agents/, .codeep/mcp_servers.json, .mcp.json and .codeep/config.json. The prompt says what the file controls. This covers the tools that take a path; it is not a boundary against a shell command you approved, which can write the same file with node, cp or tee.

sent over ACP carried every variable of the Codeep process, including API keys, and the ACP debug log mirrored them. Only the settings the hardening needs and the ordinary shell variables are sent now.

Upgrade notes

calls, unless the filter is one of the known integrations (git-lfs, git-crypt, nbstripout, git-annex, also when spelled with an absolute path). The message names the driver and the exact git config --unset. Turning off filter.<driver>.required is not** a fix: it makes git store the file's contents unfiltered. The same applies to a repo-set remote.<name>.uploadpack or receivepack, which no override can reach.

at it today.** Deciding that it is unused would mean re-implementing git's attribute lookup, which a security release is not the place for.

for the commits and checkouts you trigger, as they do in your terminal.

external diff drivers**, so a repo that renders binaries for display shows the raw diff.

says so and names the alias.

14 ms in a repository with submodules.

Fixed

missing from its name.

and did nothing at all in a repository with no commits yet.

git; it now says so once, with the setting and the command that clears it.

Internal

watching the test fail.

git credential fill reached the editor's askpass helper and waited for a password dialog, which stalled a release.

Downloads

Install with npm install -g codeep@3.4.1.