Skip to content

Latest commit

 

History

History
120 lines (105 loc) · 7.33 KB

File metadata and controls

120 lines (105 loc) · 7.33 KB

Sanitized Git execution profile v1

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.

Trusted command envelope

  1. Resolve absolute git and gh executables outside the checkout. Stop if an executable resolves inside the repository or through an ambiguous shim.
  2. Create a disposable verified-empty hooks directory and verified-empty Git system/global configuration files outside the checkout.
  3. 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 inherited GIT_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.
  4. Suppress system and global Git config for the run. Supply the already-vetted author name/email explicitly when committing.
  5. Every Git invocation must override core.hooksPath to the verified-empty directory, set core.fsmonitor=false, disable automatic maintenance and commit/tag signing, set core.protectHFS=true and core.protectNTFS=true, and deny ext, file, and SSH transports. Allow only HTTPS. If signed commits are a repository requirement, stop; do not invoke a repository-selected signer.
  6. 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.
  7. Add --no-ext-diff --no-textconv to every diff-producing inspection. Use --no-recurse-submodules for 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.

Filesystem containment

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.

Repository config and attribute audit

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.

Manifest record

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-https credential 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.