Skip to content

Commit 543924a

Browse files
authored
fix(x2a): Sanitize secrets and fix repoistory copy links (#2342)
* Sanitize secrets and fix repoistory copy links * rebase
1 parent 365b8d5 commit 543924a

1 file changed

Lines changed: 54 additions & 19 deletions

File tree

workspaces/x2a/plugins/x2a-backend/templates/x2a-job-script.sh

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
#!/bin/bash
22
set -eo pipefail
33

4+
# Prevent git from prompting for passwords interactively (no TTY in containers)
5+
export GIT_TERMINAL_PROMPT=0
6+
47
# Track error context for the cleanup trap
58
ERROR_MESSAGE=""
69
ARTIFACTS=()
10+
PUSH_FAILED=""
711

812
# Report job result back to the backend.
913
# TODO: Incorporate CALLBACK_TOKEN for request signing (HMAC-SHA256).
@@ -33,6 +37,31 @@ report_result() {
3337
cd /app && "${cmd[@]}" || echo "WARNING: Failed to report result to backend"
3438
}
3539

40+
# Strip git tokens from files before committing to prevent secret leaks.
41+
# The x2a tool may embed SOURCE_REPO_TOKEN in generated files (e.g., Policyfile.lock.json)
42+
# when Chef resolves cookbook sources using authenticated URLs.
43+
sanitize_secrets() {
44+
local dir="$1"
45+
echo "=== Sanitizing secrets from output files ==="
46+
47+
# Match GitHub PATs (ghp_, gho_, github_pat_) and generic token@host patterns in URLs
48+
local count=0
49+
while IFS= read -r -d '' file; do
50+
if grep -qE 'https?://[^@/:[:space:]]+@' "$file" 2>/dev/null; then
51+
# Strip token from URLs: https://ghp_xxx@github.com/... → https://github.com/...
52+
sed -i 's|https\?://[^@/:[:space:]]*@|https://|g' "$file"
53+
echo " Sanitized: ${file#/workspace/target/}"
54+
count=$((count + 1))
55+
fi
56+
done < <(find "$dir" -type f \( -name '*.json' -o -name '*.yaml' -o -name '*.yml' -o -name '*.lock' \) -print0 2>/dev/null)
57+
58+
if [ "$count" -eq 0 ]; then
59+
echo " No secrets found in output files"
60+
else
61+
echo " Sanitized ${count} file(s)"
62+
fi
63+
}
64+
3665
# Cleanup trap: fires on every exit (success or failure).
3766
# Guarantees exactly one report_result call regardless of how the script ends.
3867
cleanup() {
@@ -42,6 +71,10 @@ cleanup() {
4271
# Always try to commit and push whatever is in the working directory
4372
if [ -d /workspace/target/.git ]; then
4473
cd /workspace/target
74+
75+
# Sanitize secrets from output files before committing
76+
sanitize_secrets "${PROJECT_PATH:-/workspace/target}"
77+
4578
git add "${PROJECT_DIR:-${PROJECT_ID}.${PROJECT_ABBREV}}" 2>/dev/null || git add -A || true
4679
git commit -m "x2a: ${PHASE} phase for ${MODULE_NAME:-project}
4780
@@ -53,11 +86,16 @@ Job: ${JOB_ID}
5386
Co-Authored-By: ${GIT_AUTHOR_NAME} <${GIT_AUTHOR_EMAIL}>
5487
" || true
5588
git pull --rebase origin "${TARGET_REPO_BRANCH}" 2>/dev/null || true
56-
git push origin "${TARGET_REPO_BRANCH}" || true
89+
if ! git push origin "${TARGET_REPO_BRANCH}"; then
90+
PUSH_FAILED="Failed to push to ${TARGET_REPO_URL} branch ${TARGET_REPO_BRANCH}"
91+
echo "ERROR: ${PUSH_FAILED}"
92+
fi
5793
fi
5894

5995
if [ ${exit_code} -ne 0 ]; then
6096
report_result "error" "${ERROR_MESSAGE:-Script failed with exit code ${exit_code}}"
97+
elif [ -n "${PUSH_FAILED}" ]; then
98+
report_result "error" "${PUSH_FAILED}"
6199
else
62100
report_result "success" ""
63101
fi
@@ -73,21 +111,18 @@ git_clone_repos() {
73111
echo "=== Cloning target repository ==="
74112
local target_auth_url="https://${TARGET_REPO_TOKEN}@${TARGET_REPO_URL#https://}"
75113

76-
if git ls-remote "${target_auth_url}" &>/dev/null; then
77-
if git ls-remote --exit-code --heads "${target_auth_url}" "${TARGET_REPO_BRANCH}" &>/dev/null; then
78-
# Repo exists, branch exists — clone normally
79-
ERROR_MESSAGE="Failed to clone target repository from ${TARGET_REPO_URL}"
80-
git clone --depth=1 --single-branch --branch="${TARGET_REPO_BRANCH}" \
81-
"${target_auth_url}" /workspace/target
82-
else
83-
# Repo exists, branch doesn't — clone default branch, create target branch locally
84-
echo "Branch '${TARGET_REPO_BRANCH}' not found on remote, creating it"
85-
ERROR_MESSAGE="Failed to clone target repository from ${TARGET_REPO_URL}"
86-
git clone --depth=1 "${target_auth_url}" /workspace/target
87-
cd /workspace/target
88-
git checkout -b "${TARGET_REPO_BRANCH}"
89-
fi
114+
ERROR_MESSAGE="Failed to clone target repository from ${TARGET_REPO_URL}"
115+
if git clone --depth=1 --single-branch --branch="${TARGET_REPO_BRANCH}" \
116+
"${target_auth_url}" /workspace/target 2>/dev/null; then
117+
# Repo and branch exist — cloned successfully
118+
:
119+
elif git clone --depth=1 "${target_auth_url}" /workspace/target 2>/dev/null; then
120+
# Repo exists but branch doesn't — create target branch locally
121+
echo "Branch '${TARGET_REPO_BRANCH}' not found on remote, creating it"
122+
cd /workspace/target
123+
git checkout -b "${TARGET_REPO_BRANCH}"
90124
else
125+
# Repo doesn't exist or can't be accessed — init empty
91126
echo "Target repo doesn't exist, initializing empty repo"
92127
mkdir -p /workspace/target
93128
cd /workspace/target
@@ -216,13 +251,13 @@ case "${PHASE}" in
216251

217252
# Copy migration-plan.md from target repo to source dir
218253
# The x2a tool does os.chdir(source_dir) and reads migration-plan.md from there
219-
if [ ! -f "${SOURCE_BASE}/${PROJECT_DIR}/migration-plan.md" ]; then
220-
ERROR_MESSAGE="migration-plan.md not found in ${SOURCE_BASE}/${PROJECT_DIR}/ - init phase must be run first"
254+
if [ ! -f "${PROJECT_PATH}/migration-plan.md" ]; then
255+
ERROR_MESSAGE="migration-plan.md not found in ${PROJECT_PATH}/ - init phase must be run first"
221256
exit 1
222257
fi
223258

224-
echo "Copying migration-plan.md from source project directory to source root..."
225-
cp -v "${SOURCE_BASE}/${PROJECT_DIR}/migration-plan.md" "${SOURCE_BASE}/migration-plan.md"
259+
echo "Copying migration-plan.md from target project directory to source root..."
260+
cp -v "${PROJECT_PATH}/migration-plan.md" "${SOURCE_BASE}/migration-plan.md"
226261

227262
# Check if x2a tool is available (required)
228263
if [ ! -d /app ] || [ ! -f /app/app.py ]; then

0 commit comments

Comments
 (0)