Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Bound checkout credential include cleanup iterations
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
  • Loading branch information
Copilot and pelikhan authored Oct 7, 2026
commit 9e95d7c548e67106fe89533aaf750e12ac5df5c2
6 changes: 6 additions & 0 deletions actions/setup/sh/clean_git_credentials.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ clean_git_config() {
done || true

# Checkout stores persisted credentials in a separate config reached via includeIf.
local include_iterations=0 max_include_iterations=1000
while IFS= read -r -d '' entry; do
if (( include_iterations >= max_include_iterations )); then
echo "ERROR: Checkout credential include cleanup exceeded ${max_include_iterations} iterations" >&2
exit 1
fi
include_iterations=$((include_iterations + 1))
local key="${entry%%$'\n'*}" include_path="${entry#*$'\n'}"
if [[ "$include_path" =~ (^|/)git-credentials-[0-9a-f-]+\.config$ ]] &&
git config --file "${GIT_CONFIG_PATH}" --fixed-value --get-all "$key" "$include_path" >/dev/null; then
Expand Down
26 changes: 26 additions & 0 deletions actions/setup/sh/clean_git_credentials_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,32 @@ assert "credential file outside runner temp retained" "[ -f '${TEST_WORKSPACE}/g
assert "unrelated include preserved" "git --git-dir='${REPO}/.git' config --file '${REPO}/.git/config' --includes core.ignorecase | grep -q true"
echo ""

# ── Test 10: Include cleanup iteration boundary ────────────────────────────
echo "Test 10: Include cleanup succeeds at the iteration limit"
REPO="${TEST_WORKSPACE}/repo10"
make_git_config "${REPO}" '[includeIf "gitdir:/workspace/.git"]'
for ((i = 0; i < 1000; i++)); do
printf '\tpath = /nonexistent/git-credentials-abc123.config\n' >>"${REPO}/.git/config"
done
assert "cleanup succeeds at 1000 includes" "GITHUB_WORKSPACE='${REPO}' bash '${CLEAN_SCRIPT}' >/dev/null 2>&1"
assert "all credential includes removed at limit" "! git config --file '${REPO}/.git/config' --get-regexp '^includeif\\..*\\.path$' 2>/dev/null"
echo ""

# ── Test 11: Include cleanup iteration limit exceeded ──────────────────────
echo "Test 11: Include cleanup fails when the iteration limit is exceeded"
make_git_config "${REPO}" '[includeIf "gitdir:/workspace/.git"]'
for ((i = 0; i < 1001; i++)); do
printf '\tpath = /nonexistent/other.config\n' >>"${REPO}/.git/config"
done
printf '\tpath = /nonexistent/git-credentials-abc123.config\n' >>"${REPO}/.git/config"
EXIT_CODE=0
OUTPUT=$(GITHUB_WORKSPACE="${REPO}" bash "${CLEAN_SCRIPT}" 2>&1) || EXIT_CODE=$?
assert "cleanup exits 1 when limit exceeded" "[ ${EXIT_CODE} -eq 1 ]"
assert "reports iteration limit without include values" "echo '${OUTPUT}' | grep -q 'ERROR: Checkout credential include cleanup exceeded 1000 iterations'"
assert "credential include beyond limit is not processed" "git config --file '${REPO}/.git/config' --get-regexp '^includeif\\..*\\.path$' | grep -q 'git-credentials-abc123.config'"
rm -rf "${REPO}"
echo ""

# ── Summary ──────────────────────────────────────────────────────────────────
echo "Tests passed: ${TESTS_PASSED}"
echo "Tests failed: ${TESTS_FAILED}"
Expand Down
Loading