Skip to content
Open
Changes from all commits
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
81 changes: 81 additions & 0 deletions .github/workflows/sync-secrets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Sync Secrets to Repositories

on:
workflow_dispatch:
inputs:
target_repo:
description: 'Target repository (org/repo format)'
required: true
default: 'game-ci/orchestrator'
type: choice
options:
- game-ci/orchestrator
- game-ci/cli
dry_run:
description: 'Dry run (list secrets to sync without writing)'
required: false
default: false
type: boolean

jobs:
sync-secrets:
name: Sync secrets to ${{ inputs.target_repo }}
runs-on: ubuntu-latest
steps:
Comment on lines +20 to +24
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/sync-secrets.yml

Repository: game-ci/unity-builder

Length of output: 3535


🏁 Script executed:

find .github/workflows -name "*.yml" -o -name "*.yaml" | head -5 | xargs grep -l "permissions:" 2>/dev/null

Repository: game-ci/unity-builder

Length of output: 49


🏁 Script executed:

find .github/workflows -name "*.yml" -o -name "*.yaml" | xargs head -30 | grep -A 5 "^jobs:" | head -20

Repository: game-ci/unity-builder

Length of output: 547


🏁 Script executed:

find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \) | wc -l

Repository: game-ci/unity-builder

Length of output: 67


🏁 Script executed:

find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \) -exec grep -l "^permissions:" {} \;

Repository: game-ci/unity-builder

Length of output: 195


🏁 Script executed:

grep -A 2 "^permissions:" .github/workflows/integrity-check.yml .github/workflows/orchestrator-async-checks.yml .github/workflows/orchestrator-integrity.yml

Repository: game-ci/unity-builder

Length of output: 585


🏁 Script executed:

# Verify the syntax of permissions: {} in GitHub Actions documentation context
# Check if there are any other cross-repo secret workflows to compare
grep -r "gh secret set" .github/workflows/

Repository: game-ci/unity-builder

Length of output: 178


Add explicit workflow permissions (least privilege).

The workflow lacks an explicit permissions block, leaving default GITHUB_TOKEN permissions implicit. While this workflow uses an explicit GH_TOKEN for gh secret set, the default token should still be restricted to follow least-privilege principle and align with the repository's existing security pattern (other workflows declare explicit permissions).

Suggested patch
 name: Sync Secrets to Repositories
 
 on:
   workflow_dispatch:
+    inputs:
       type: boolean
+
+permissions: {}
 
 jobs:
   sync-secrets:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/sync-secrets.yml around lines 20 - 24, Add an explicit
permissions block at the workflow root to restrict the default GITHUB_TOKEN
(follow least privilege). Insert a top-level permissions section (above jobs)
such as "permissions: contents: read" or "permissions: none" depending on
whether the workflow needs repo contents; this will limit GITHUB_TOKEN access
for the "sync-secrets" job while you continue to use the explicit GH_TOKEN for
gh secret set.

- name: Sync secrets
env:
GH_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
TARGET_REPO: ${{ inputs.target_repo }}
DRY_RUN: ${{ inputs.dry_run }}
# Secrets to sync — values come from repo + org secrets available here
SECRET_UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
SECRET_UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
SECRET_UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
SECRET_GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
SECRET_LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
SECRET_GOOGLE_SERVICE_ACCOUNT_EMAIL: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_EMAIL }}
SECRET_GOOGLE_SERVICE_ACCOUNT_KEY: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }}
SECRET_CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
Comment on lines +31 to +38
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd /tmp && git ls-files | grep -E "\.github/workflows/" | head -20

Repository: game-ci/unity-builder

Length of output: 133


🏁 Script executed:

cat -n .github/workflows/sync-secrets.yml | head -60

Repository: game-ci/unity-builder

Length of output: 2698


🏁 Script executed:

cat -n .github/workflows/build-tests-windows.yml | grep -i "unity_license" -A 2 -B 2

Repository: game-ci/unity-builder

Length of output: 826


🏁 Script executed:

cat .github/workflows/orchestrator-integrity.yml | grep -E "AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY" -A 2 -B 2

Repository: game-ci/unity-builder

Length of output: 4497


🏁 Script executed:

cat .github/workflows/orchestrator-integrity.yml | grep -E "secrets\." -i | head -20

Repository: game-ci/unity-builder

Length of output: 1172


🏁 Script executed:

rg "secrets\.AWS_" .github/workflows/ -A 1 -B 1

Repository: game-ci/unity-builder

Length of output: 436


🏁 Script executed:

cat .github/workflows/orchestrator-async-checks.yml | grep -A 10 -B 10 "AWS_ACCESS_KEY_ID.*secrets"

Repository: game-ci/unity-builder

Length of output: 830


🏁 Script executed:

cat -n .github/workflows/sync-secrets.yml | tail -30

Repository: game-ci/unity-builder

Length of output: 1239


Add UNITY_LICENSE to the secrets allowlist for sync.

The mapping omits UNITY_LICENSE, which is actively referenced in .github/workflows/build-tests-windows.yml (lines 109, 136, 161). This secret is necessary for downstream workflows and should be included in the sync.

Note: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are not referenced as actual secrets in the workflows—they are hardcoded test values (in orchestrator-integrity.yml) or commented out (in orchestrator-async-checks.yml), so they should not be added to the sync allowlist.

Suggested patch
          SECRET_UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }}
+         SECRET_UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          SECRET_GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}
            "UNITY_SERIAL:SECRET_UNITY_SERIAL"
+           "UNITY_LICENSE:SECRET_UNITY_LICENSE"
            "GIT_PRIVATE_TOKEN:SECRET_GIT_PRIVATE_TOKEN"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/sync-secrets.yml around lines 31 - 38, The sync secrets
allowlist is missing UNITY_LICENSE which is used by downstream workflows (e.g.,
build-tests-windows.yml); update the secret mappings in
.github/workflows/sync-secrets.yml by adding a mapping for UNITY_LICENSE (e.g.,
SECRET_UNITY_LICENSE -> ${{ secrets.UNITY_LICENSE }}) alongside the existing
SECRET_UNITY_* entries so the workflow can sync that secret for downstream use.

run: |
SECRETS=(
"UNITY_EMAIL:SECRET_UNITY_EMAIL"
"UNITY_PASSWORD:SECRET_UNITY_PASSWORD"
"UNITY_SERIAL:SECRET_UNITY_SERIAL"
"GIT_PRIVATE_TOKEN:SECRET_GIT_PRIVATE_TOKEN"
"LOCALSTACK_AUTH_TOKEN:SECRET_LOCALSTACK_AUTH_TOKEN"
"GOOGLE_SERVICE_ACCOUNT_EMAIL:SECRET_GOOGLE_SERVICE_ACCOUNT_EMAIL"
"GOOGLE_SERVICE_ACCOUNT_KEY:SECRET_GOOGLE_SERVICE_ACCOUNT_KEY"
"CODECOV_TOKEN:SECRET_CODECOV_TOKEN"
)

synced=0
skipped=0

for entry in "${SECRETS[@]}"; do
name="${entry%%:*}"
env_var="${entry##*:}"
value="${!env_var}"

if [ -z "$value" ]; then
echo "⏭ SKIP: $name (not available in this repo's context)"
skipped=$((skipped + 1))
continue
fi

if [ "$DRY_RUN" = "true" ]; then
echo "🔍 DRY RUN: would sync $name → $TARGET_REPO"
else
echo "$value" | gh secret set "$name" -R "$TARGET_REPO" --body -
echo "✅ SYNCED: $name → $TARGET_REPO"
fi
synced=$((synced + 1))
done

echo ""
echo "=== Summary ==="
echo "Synced: $synced"
echo "Skipped (not available): $skipped"
echo "Target: $TARGET_REPO"
if [ "$DRY_RUN" = "true" ]; then
echo "Mode: DRY RUN (no secrets were written)"
fi
Comment on lines +22 to +81

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI 5 days ago

In general, the fix is to add an explicit permissions block that limits the GITHUB_TOKEN to the least privileges required. This should be added either at the top level of the workflow (to apply to all jobs) or at the job level (for sync-secrets). Since this workflow only has a single job and uses a separate secret (GIT_PRIVATE_TOKEN) for writing secrets, GITHUB_TOKEN does not appear to need any write permissions. The safest minimal configuration is permissions: contents: read at the job or workflow level.

The single best way to fix this without affecting existing behavior is to add a permissions block under the sync-secrets job, right after runs-on: ubuntu-latest. Given the script only calls gh secret set using GH_TOKEN from a custom secret and does not interact with repository contents, issues, or pull requests via GITHUB_TOKEN, we can set permissions: contents: read. This keeps GITHUB_TOKEN usable for basic checkout or read-only operations if added later, while preventing unintended write access.

Concretely, in .github/workflows/sync-secrets.yml, modify the sync-secrets job so that:

  sync-secrets:
    name: Sync secrets to ${{ inputs.target_repo }}
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - name: Sync secrets
      ...

No new imports or libraries are needed, as this is purely a YAML configuration change.

Suggested changeset 1
.github/workflows/sync-secrets.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/sync-secrets.yml b/.github/workflows/sync-secrets.yml
--- a/.github/workflows/sync-secrets.yml
+++ b/.github/workflows/sync-secrets.yml
@@ -21,6 +21,8 @@
   sync-secrets:
     name: Sync secrets to ${{ inputs.target_repo }}
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     steps:
       - name: Sync secrets
         env:
EOF
@@ -21,6 +21,8 @@
sync-secrets:
name: Sync secrets to ${{ inputs.target_repo }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Sync secrets
env:
Copilot is powered by AI and may make mistakes. Always verify output.
Loading