diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 83dc3be8..1ae736a6 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -86,6 +86,18 @@ if [ -n "${GH_TOKEN:-${GITHUB_TOKEN:-}}" ]; then git_config_count=$((git_config_count + 1)) export "GIT_CONFIG_KEY_${git_config_count}=url.https://${git_host}/.insteadOf" export "GIT_CONFIG_VALUE_${git_config_count}=git@${git_host}:" + git_config_count=$((git_config_count + 1)) + + # Prevent automatic submodule operations from leaking the credential + # token to repositories not explicitly listed in the scan inventory. + # A malicious .gitmodules inside a scanned repository could otherwise + # trigger fetches to attacker-controlled repos on the same host, + # causing the credential helper to hand out the token. + export "GIT_CONFIG_KEY_${git_config_count}=submodule.recurse" + export "GIT_CONFIG_VALUE_${git_config_count}=false" + git_config_count=$((git_config_count + 1)) + export "GIT_CONFIG_KEY_${git_config_count}=fetch.recurseSubmodules" + export "GIT_CONFIG_VALUE_${git_config_count}=false" export GIT_CONFIG_COUNT=$((git_config_count + 1)) fi diff --git a/docker/git-credential.sh b/docker/git-credential.sh index afdf3f32..1851de5b 100644 --- a/docker/git-credential.sh +++ b/docker/git-credential.sh @@ -6,6 +6,18 @@ if [ "${1:-}" != get ]; then exit 0 fi +# Refuse to hand out credentials when Git is operating inside a submodule. +# Git sets GIT_DIR to a path under the parent repository's .git/modules/ +# directory during submodule operations, which distinguishes a submodule +# fetch from a top-level clone. Without this guard a malicious .gitmodules +# inside a scanned repository could point to another repo on the same host +# and receive the scan credential token. +case "${GIT_DIR:-}" in + */.git/modules/*|*.git/modules/*) + exit 0 + ;; +esac + protocol= host= diff --git a/sdk/typescript/src/multiscan.ts b/sdk/typescript/src/multiscan.ts index 4795bcfd..39abaa4e 100644 --- a/sdk/typescript/src/multiscan.ts +++ b/sdk/typescript/src/multiscan.ts @@ -482,6 +482,8 @@ async function checkoutRevision( [ "-c", "core.hooksPath=/dev/null", + "-c", + "submodule.recurse=false", ...buildGitHubCredentialArgs(githubHost), "-C", path,