Repository Git configuration, attributes, and hooks are untrusted. They can run programs during apparently ordinary reads, staging, commits, and pushes. Apply this profile before the first Git command in a write-capable run and recompute its snapshots immediately before each staging, commit, fetch, or push batch.
- Resolve absolute
gitandghexecutables outside the checkout. Stop if an executable resolves inside the repository or through an ambiguous shim. - Create a disposable verified-empty hooks directory and verified-empty Git system/global configuration files outside the checkout.
- Use a minimal environment. Remove Git command-injection variables, including
GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS,GIT_SSH,GIT_SSH_COMMAND,GIT_ASKPASS,SSH_ASKPASS,GIT_EXEC_PATH, and inheritedGIT_CONFIG_*entries. Disable terminal prompting and paging. Preserve only the known GitHub CLI credential location and other values required by the trusted binaries; never expose unrelated credentials to repository-controlled code. - Suppress system and global Git config for the run. Supply the already-vetted author name/email explicitly when committing.
- Every Git invocation must override
core.hooksPathto the verified-empty directory, setcore.fsmonitor=false, disable automatic maintenance and commit/tag signing, setcore.protectHFS=trueandcore.protectNTFS=true, and denyext,file, and SSH transports. Allow only HTTPS. If signed commits are a repository requirement, stop; do not invoke a repository-selected signer. - Reset the credential-helper list, disable interactive credentials, and add only the resolved absolute GitHub CLI as the HTTPS credential helper. Build the HTTPS GitHub.com transport URL from the validated lowercase repository identity; do not use or print a configured raw URL. Hash the constructed URL into the manifest.
- Add
--no-ext-diff --no-textconvto every diff-producing inspection. Use--no-recurse-submodulesfor network operations. Never invoke a Git alias, difftool, mergetool, submodule update, or repository-provided helper.
Hash the complete ordered environment, executable paths, overrides, and flags as
invocation_sha256. A changed envelope invalidates approval.
Resolve and record the canonical worktree root, Git metadata directory, and Git
common directory under the sanitized envelope. For every read or write path,
resolve the nearest existing parent and then the target without following an
untrusted symlink. Require repository targets to remain inside the canonical
worktree and outside both resolved Git metadata roots. A path under .git, a
linked worktree's metadata directory, the common object/config directory, or an
alias of any of those locations is never an approvable repository path.
Hash the normalized resolved worktree/Git-directory/common-directory identities
and their fresh filesystem metadata as git_metadata_snapshot_sha256.
Run untrusted validation and dependency code with network disabled and exact
filesystem allowlists. Writes are limited to the canonical worktree and named
disposable temporary roots. Reads are limited to those roots plus explicit
read-only toolchain and dependency roots required by the approved command.
Deny the home directory generally, credential stores, SSH/GPG/keychain data,
agent sockets, cloud configuration, browser profiles, and unrelated local
files. Canonicalize, sort, and hash the complete read and write allowlists as
filesystem_read_scope_sha256 and filesystem_write_scope_sha256. If the
runtime cannot enforce either boundary, require exact risk acceptance that
names the additional reach; autonomous mode never supplies that acceptance.
Under the command envelope, inspect expanded Git config with origin and scope.
Hash the complete non-secret normalized result as config_snapshot_sha256.
Stop or obtain exact explicit risk acceptance if repository/worktree-scoped
configuration selects any command, helper, hook, proxy, transport, URL rewrite,
external object provider, signing program, editor, or pager. This includes, but
is not limited to, hooks paths, fsmonitor, SSH commands, askpass, credential
helpers, aliases, external diff/textconv commands, clean/smudge/process filters,
insteadOf rewrites, remote helpers/proxies, alternate-ref commands, signing
programs, and pack-object hooks.
Inspect .git/info/attributes, the applicable .gitattributes files, the global
attributes setting, and git check-attr --all results for every intended path.
Hash the normalized definitions and results as attributes_snapshot_sha256.
Treat intended paths as canonical POSIX repository paths: reject absolute,
drive-letter, UNC, backslash, colon/alternate-data-stream, empty, dot, dot-dot,
NUL, and .git-rooted forms. Reject every component ending in a dot or space.
After Unicode normalization and case folding, reject Windows device basenames
and aliases even when followed by an extension: CON, PRN, AUX, NUL,
CLOCK$, CONIN$, CONOUT$, COM1 through COM9, LPT1 through LPT9,
and the COM/LPT superscript-digit aliases. Do not rely on the host filesystem
to reject them. Also reject .git short-name aliases matching .git~N or
git~N for any positive decimal N.
Before reading or editing, use lstat plus resolved-parent/target checks and
require every existing target and every new path's nearest existing parent to
remain inside the resolved checkout root and outside the resolved Git metadata
and common directories. Stop on a symlink escape or alias collision; never
follow it and never treat approval as containment proof.
For every approved path, record path, lstat_chain_sha256,
resolved_target_sha256, inside_worktree: true, and
outside_git_metadata: true. Sort records by path and require an exact
one-to-one match with the manifest path list. Refresh and require identical
records immediately before editing and again immediately before staging.
Any active filter attribute is repository code execution during staging. The
safe profile requires active_clean_filters to be empty. Git LFS and other
clean-filter paths therefore require exact explicit risk acceptance or a stop.
External diff and textconv attributes remain disabled by command flags.
Recompute configuration, attributes, Git-metadata identity, filesystem-scope, and per-path snapshots after relevant changes and immediately before staging. Stop if any digest or path record differs from the approved manifest.
The safe profile is sanitized-gh-https-v1 and records:
- config, attribute, Git-metadata, invocation, and transport-URL SHA-256 digests;
- filesystem read-scope and write-scope SHA-256 digests;
- the exact
gh-cli-httpscredential strategy; - empty active clean filters; and
- true booleans for hooks, fsmonitor, external diff, textconv, signing,
protect_hfs_enabled,protect_ntfs_enabled, and protocol restrictions.
If any guarantee is unavailable, do not label the record safe. Use
explicit-risk-acceptance-v1 only after the user accepts the exact command,
executable, config/attribute snapshots, missing protections, credentials at
risk, and network/filesystem reach. Hash that canonical acceptance record in
risk_acceptance_sha256. Autonomous mode is never implicit acceptance.