Files
stack/packages/mosaic/framework/tools/git/git-credential-mosaic
T
marcieandorch-01 736b0affc1
ci/woodpecker/push/publish Pipeline was successful
compose: add wrapper-first dogfood workspace (#1488)
Co-authored-by: marcie <[email protected]>
2026-08-30 22:29:30 +00:00

65 lines
2.6 KiB
Python
Executable File

#!/usr/bin/python3
# git-credential-mosaic — production entrypoint (P0-SEC R4, rev-code-02 B1).
#
# WHY THIS IS NOT BASH: three review rounds falsified every in-bash startup
# guard. A non-interactive bash sources $BASH_ENV and imports exported
# functions BEFORE the first script line, so read(), unset(), exit(),
# declare(), printf() — every callable — can be shadows that fake the
# ancestry, defeat the scrub, or forge diagnostics (rev-code-02 probes 1 and
# 2, artifacts fc49e9d9 lineage). No in-language dispatch survives that.
#
# This entrypoint is unshapable at the bash level: python does not read
# BASH_ENV and imports no bash functions, and the interpreter is pinned by
# absolute shebang (no PATH resolution). It builds the child environment BY
# ALLOWLIST and execve's the bash implementation directly — the child bash
# starts with no BASH_ENV, no BASH_FUNC_*, no SHELLOPTS/BASHOPTS, and exactly
# the variables the credential protocol needs. stdin/stdout/stderr and argv
# pass through untouched.
#
# The implementation file (git-credential-mosaic.impl) refuses to run without
# the clean-mode marker, so it cannot be invoked directly as a shaped-entry
# bypass of this wrapper.
import os
import sys
IMPL = os.path.join(os.path.dirname(os.path.realpath(__file__)), "git-credential-mosaic.impl")
# Absolute-path candidates ONLY — never PATH resolution (an attacker-shaped
# PATH must not choose the interpreter). /usr/bin/bash is the fleet-host
# layout; /bin/bash is alpine and other FHS variants (found by the T125
# gateway-image verification: the hardcoded /usr/bin/bash made every call
# exit 127 inside node:22-alpine).
BASH_CANDIDATES = ("/usr/bin/bash", "/bin/bash")
BASH = next((p for p in BASH_CANDIDATES if os.access(p, os.X_OK)), None)
# Allowlist: everything else in the environment dies at this boundary. Adding
# a variable here is a security decision — it crosses into a shell that no
# longer has any startup shaping, but it also becomes the only context the
# implementation can see.
KEEP = (
"HOME",
"PATH",
"LANG",
"MOSAIC_GIT_IDENTITY",
"MOSAIC_AGENT_NAME",
"MOSAIC_BRAIN_HOME",
"MOSAIC_CREDENTIAL_SPOOL",
"MOSAIC_CREDENTIAL_LINEAGE_FENCE",
)
env = {"_MOSAIC_HELPER_CLEAN": "1"}
for name in KEEP:
value = os.environ.get(name)
if value is not None:
env[name] = value
argv = [BASH, IMPL] + sys.argv[1:]
if BASH is None:
sys.stderr.write("git-credential-mosaic: no executable bash at " + " or ".join(BASH_CANDIDATES) + "\n")
sys.exit(127)
try:
os.execve(BASH, argv, env)
except OSError as exc:
sys.stderr.write(f"git-credential-mosaic: entrypoint exec failed: {exc}\n")
sys.exit(127)