Skip to content

Commit de2a283

Browse files
authored
fix(x2a): Fix/policy lock token leak (#2636)
* fix policy lock json secret commit * changeset * option 1: sanitization and fixes * strip token from url, and sanatize * Added module-deps and cache now succeeds
1 parent a98cbba commit de2a283

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@red-hat-developer-hub/backstage-plugin-x2a-backend': patch
3+
---
4+
5+
Fix SCM token leak in committed files: improve URL credential sanitization regex to handle user:token@host patterns and extend file type coverage to include markdown files

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

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,16 @@ sanitize_secrets() {
5656
local dir="$1"
5757
echo "=== Sanitizing secrets from output files ==="
5858

59-
# Match GitHub PATs (ghp_, gho_, github_pat_) and generic token@host patterns in URLs
59+
# Match credentials embedded in URLs: https://token@host or https://user:token@host
6060
local count=0
6161
while IFS= read -r -d '' file; do
62-
if grep -qE 'https?://[^@/:[:space:]]+@' "$file" 2>/dev/null; then
63-
# Strip token from URLs: https://ghp_xxx@github.com/... → https://github.com/...
64-
sed -i 's|https\?://[^@/:[:space:]]*@|https://|g' "$file"
62+
if grep -qE 'https?://[^@/[:space:]]+@' "$file" 2>/dev/null; then
63+
# Strip credentials from URLs: https://user:token@host/... → https://host/...
64+
sed -i 's|https\?://[^@/[:space:]]*@|https://|g' "$file"
6565
echo " Sanitized: ${file#/workspace/target/}"
6666
count=$((count + 1))
6767
fi
68-
done < <(find "$dir" -type f \( -name '*.json' -o -name '*.yaml' -o -name '*.yml' -o -name '*.lock' \) -print0 2>/dev/null)
68+
done < <(find "$dir" -type f \( -name '*.json' -o -name '*.yaml' -o -name '*.yml' -o -name '*.lock' -o -name '*.md' \) -print0 2>/dev/null)
6969

7070
if [ "$count" -eq 0 ]; then
7171
echo " No secrets found in output files"
@@ -123,6 +123,12 @@ git_clone_repos() {
123123
"https://${SOURCE_REPO_TOKEN}@${SOURCE_REPO_URL#https://}" \
124124
/workspace/source
125125

126+
# Strip the token from the git remote URL so that tools like Chef's
127+
# CookbookProfiler::Git (which reads `git config --get remote.origin.url`)
128+
# never see the credential. This prevents tokens from leaking into
129+
# generated files such as Policyfile.lock.json.
130+
git -C /workspace/source remote set-url origin "${SOURCE_REPO_URL}"
131+
126132
echo "=== Cloning target repository ==="
127133
local target_auth_url="https://${TARGET_REPO_TOKEN}@${TARGET_REPO_URL#https://}"
128134

@@ -299,8 +305,12 @@ case "${PHASE}" in
299305
# Note: x2a tool produces migration-plan-{module_name}.md (spaces replaced with underscores)
300306
echo "Copying output to ${OUTPUT_DIR}/"
301307
cp -v "${SOURCE_BASE}/migration-plan-${MODULE_NAME_SANITIZED}.md" "${OUTPUT_DIR}/"
302-
cp -v "${SOURCE_BASE}"/*.json "${OUTPUT_DIR}/" 2>/dev/null || true
303308
cp -v "${SOURCE_BASE}"/*.yaml "${OUTPUT_DIR}/" 2>/dev/null || true
309+
cp -rv "${SOURCE_BASE}/migration-dependencies" "${OUTPUT_DIR}/" 2>/dev/null || true
310+
311+
# Update project-level Policyfile.lock.json — chef-cli may have updated it
312+
# during dependency resolution. Keep it at project root only, not per-module.
313+
cp -v "${SOURCE_BASE}/Policyfile.lock.json" "${PROJECT_PATH}/" 2>/dev/null || true
304314

305315
echo ""
306316
echo "=== Output directory contents ==="
@@ -334,6 +344,14 @@ case "${PHASE}" in
334344
echo "Copying migration-plan.md from target to source directory..."
335345
cp -v "${PROJECT_PATH}/migration-plan.md" "${SOURCE_BASE}/migration-plan.md"
336346

347+
# Copy migration-dependencies from target repo back to source dir.
348+
# The analyze phase created this directory and committed it to the target repo.
349+
# The migrate phase runs in a separate pod, so we need to restore it.
350+
if [ -d "${PROJECT_PATH}/migration-dependencies" ]; then
351+
echo "Copying migration-dependencies from target to source directory..."
352+
cp -rv "${PROJECT_PATH}/migration-dependencies" "${SOURCE_BASE}/"
353+
fi
354+
337355
# Check if x2a tool is available (required)
338356
if [ ! -d /app ] || [ ! -f /app/app.py ]; then
339357
ERROR_MESSAGE="/app/app.py not found - x2a tool is required"
@@ -361,7 +379,6 @@ case "${PHASE}" in
361379
# Note: x2a tool writes to ansible/roles/{module}/ in the source directory
362380
echo "Copying output to ${OUTPUT_DIR}/"
363381
cp -rv "${SOURCE_BASE}/ansible" "${OUTPUT_DIR}/" 2>/dev/null || true
364-
cp -v "${SOURCE_BASE}"/*.json "${OUTPUT_DIR}/" 2>/dev/null || true
365382
cp -v "${SOURCE_BASE}"/*.yaml "${OUTPUT_DIR}/" 2>/dev/null || true
366383

367384
echo ""

0 commit comments

Comments
 (0)