github-advanced-security[bot] commented on code in PR #13525:
URL: https://github.com/apache/cloudstack/pull/13525#discussion_r3511063086


##########
.github/workflows/copilot-token-health.yml:
##########
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Manual health check for the pool of volunteer Copilot tokens (see 
.github/COPILOT_TOKENS.md).
+# Trigger it from the Actions tab to find dead tokens in 
GH_AW_COPILOT_TOKEN_NAMES so they can be
+# pruned. Only HTTP status codes are printed, never account logins. A 200 just 
means the token is
+# live; there is no endpoint to check whether its monthly Copilot requests are 
used up.
+name: Copilot token health
+
+on:
+  workflow_dispatch: {}
+
+permissions: {}
+
+jobs:
+  resolve:
+    runs-on: ubuntu-latest
+    outputs:
+      names: ${{ steps.list.outputs.names }}
+    steps:
+      - id: list
+        env:
+          NAMES: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES || '[]' }}
+        run: echo "names=$NAMES" >> "$GITHUB_OUTPUT"
+
+  check:
+    needs: resolve
+    if: ${{ needs.resolve.outputs.names != '[]' && needs.resolve.outputs.names 
!= '' }}
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        name: ${{ fromJson(needs.resolve.outputs.names) }}
+    steps:
+      - name: Check token liveness
+        env:
+          TOKEN: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', matrix.name)] 
}}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', matrix.name)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/161)



##########
.github/workflows/daily-issue-triage.lock.yml:
##########
@@ -1299,6 +1302,79 @@
               }
             }
 
+  pick_copilot_token:
+    needs: activation
+    runs-on: ubuntu-latest
+    outputs:
+      name: ${{ steps.pick.outputs.name }}
+    steps:
+      - name: Configure GH_HOST for enterprise compatibility
+        id: ghes-host-config
+        shell: bash
+        run: |
+          # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the 
correct
+          # GitHub instance (GHES/GHEC). On github.com this is a harmless 
no-op.
+          GH_HOST="${GITHUB_SERVER_URL#https://}";
+          GH_HOST="${GH_HOST#http://}";
+          echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+      - name: Compute candidate names by date
+        id: names
+        run: |
+          set -euo pipefail
+          NAMES=()
+          if [ -n "${NAMES_JSON:-}" ]; then
+            mapfile -t NAMES < <(printf '%s' "$NAMES_JSON" | jq -r '.[]')
+          fi
+          N=${#NAMES[@]}
+          K=3   # today's pick plus 2 fallbacks in case it's dead
+          if [ "$N" -eq 0 ]; then
+            for o in $(seq 0 $((K-1))); do echo "name_$o=" >> 
"$GITHUB_OUTPUT"; done
+            echo "GH_AW_COPILOT_TOKEN_NAMES is empty -> agent will use base 
COPILOT_GITHUB_TOKEN"
+            exit 0
+          fi
+          DOY=$(date -u +%-j)
+          # slot 1 starts half the pool away from slot 0 so the two workflows
+          # pick different tokens whenever the pool has at least 2
+          START=$(( (DOY - 1 + ROTATION_SLOT * ((N + 1) / 2)) % N ))
+          for o in $(seq 0 $((K-1))); do
+            i=$(( (START + o) % N ))
+            echo "name_$o=${NAMES[$i]}" >> "$GITHUB_OUTPUT"
+          done
+        env:
+          NAMES_JSON: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES }}
+          ROTATION_SLOT: "1"
+      - name: Pick first live token name
+        id: pick
+        run: |
+          set -euo pipefail
+          live() {
+            [ -n "$1" ] && [ "$(curl -s -o /dev/null -w '%{http_code}' \
+              -H "Authorization: Bearer $1" https://api.github.com/user || 
echo 000)" = "200" ]
+          }
+          for pair in "$NAME_0|$CAND_0" "$NAME_1|$CAND_1" "$NAME_2|$CAND_2"; do
+            nm="${pair%%|*}"; tok="${pair#*|}"
+            if [ -z "$tok" ]; then continue; fi
+            echo "::add-mask::$tok"
+            if live "$tok"; then
+              echo "name=$nm" >> "$GITHUB_OUTPUT"
+              echo "Selected rotated token '$nm'"
+              exit 0
+            fi
+          done
+          # empty name makes the agent job fall back to the base 
COPILOT_GITHUB_TOKEN secret
+          [ -n "$BASE" ] && echo "::add-mask::$BASE"
+          echo "name=" >> "$GITHUB_OUTPUT"
+          if live "$BASE"; then echo "Falling back to base 
COPILOT_GITHUB_TOKEN"; else
+            echo "WARNING: no live Copilot token (rotated or base)" >&2; fi
+        env:
+          BASE: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+          CAND_0: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_0)] }}
+          CAND_1: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_1)] }}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', steps.names.outputs.name_1)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/165)



##########
.github/workflows/daily-issue-triage.lock.yml:
##########
@@ -1299,6 +1302,79 @@
               }
             }
 
+  pick_copilot_token:
+    needs: activation
+    runs-on: ubuntu-latest
+    outputs:
+      name: ${{ steps.pick.outputs.name }}
+    steps:
+      - name: Configure GH_HOST for enterprise compatibility
+        id: ghes-host-config
+        shell: bash
+        run: |
+          # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the 
correct
+          # GitHub instance (GHES/GHEC). On github.com this is a harmless 
no-op.
+          GH_HOST="${GITHUB_SERVER_URL#https://}";
+          GH_HOST="${GH_HOST#http://}";
+          echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+      - name: Compute candidate names by date
+        id: names
+        run: |
+          set -euo pipefail
+          NAMES=()
+          if [ -n "${NAMES_JSON:-}" ]; then
+            mapfile -t NAMES < <(printf '%s' "$NAMES_JSON" | jq -r '.[]')
+          fi
+          N=${#NAMES[@]}
+          K=3   # today's pick plus 2 fallbacks in case it's dead
+          if [ "$N" -eq 0 ]; then
+            for o in $(seq 0 $((K-1))); do echo "name_$o=" >> 
"$GITHUB_OUTPUT"; done
+            echo "GH_AW_COPILOT_TOKEN_NAMES is empty -> agent will use base 
COPILOT_GITHUB_TOKEN"
+            exit 0
+          fi
+          DOY=$(date -u +%-j)
+          # slot 1 starts half the pool away from slot 0 so the two workflows
+          # pick different tokens whenever the pool has at least 2
+          START=$(( (DOY - 1 + ROTATION_SLOT * ((N + 1) / 2)) % N ))
+          for o in $(seq 0 $((K-1))); do
+            i=$(( (START + o) % N ))
+            echo "name_$o=${NAMES[$i]}" >> "$GITHUB_OUTPUT"
+          done
+        env:
+          NAMES_JSON: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES }}
+          ROTATION_SLOT: "1"
+      - name: Pick first live token name
+        id: pick
+        run: |
+          set -euo pipefail
+          live() {
+            [ -n "$1" ] && [ "$(curl -s -o /dev/null -w '%{http_code}' \
+              -H "Authorization: Bearer $1" https://api.github.com/user || 
echo 000)" = "200" ]
+          }
+          for pair in "$NAME_0|$CAND_0" "$NAME_1|$CAND_1" "$NAME_2|$CAND_2"; do
+            nm="${pair%%|*}"; tok="${pair#*|}"
+            if [ -z "$tok" ]; then continue; fi
+            echo "::add-mask::$tok"
+            if live "$tok"; then
+              echo "name=$nm" >> "$GITHUB_OUTPUT"
+              echo "Selected rotated token '$nm'"
+              exit 0
+            fi
+          done
+          # empty name makes the agent job fall back to the base 
COPILOT_GITHUB_TOKEN secret
+          [ -n "$BASE" ] && echo "::add-mask::$BASE"
+          echo "name=" >> "$GITHUB_OUTPUT"
+          if live "$BASE"; then echo "Falling back to base 
COPILOT_GITHUB_TOKEN"; else
+            echo "WARNING: no live Copilot token (rotated or base)" >&2; fi
+        env:
+          BASE: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+          CAND_0: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_0)] }}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', steps.names.outputs.name_0)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/163)



##########
.github/workflows/daily-repo-status.lock.yml:
##########
@@ -1295,6 +1298,79 @@
               }
             }
 
+  pick_copilot_token:
+    needs: activation
+    runs-on: ubuntu-latest
+    outputs:
+      name: ${{ steps.pick.outputs.name }}
+    steps:
+      - name: Configure GH_HOST for enterprise compatibility
+        id: ghes-host-config
+        shell: bash
+        run: |
+          # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the 
correct
+          # GitHub instance (GHES/GHEC). On github.com this is a harmless 
no-op.
+          GH_HOST="${GITHUB_SERVER_URL#https://}";
+          GH_HOST="${GH_HOST#http://}";
+          echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+      - name: Compute candidate names by date
+        id: names
+        run: |
+          set -euo pipefail
+          NAMES=()
+          if [ -n "${NAMES_JSON:-}" ]; then
+            mapfile -t NAMES < <(printf '%s' "$NAMES_JSON" | jq -r '.[]')
+          fi
+          N=${#NAMES[@]}
+          K=3   # today's pick plus 2 fallbacks in case it's dead
+          if [ "$N" -eq 0 ]; then
+            for o in $(seq 0 $((K-1))); do echo "name_$o=" >> 
"$GITHUB_OUTPUT"; done
+            echo "GH_AW_COPILOT_TOKEN_NAMES is empty -> agent will use base 
COPILOT_GITHUB_TOKEN"
+            exit 0
+          fi
+          DOY=$(date -u +%-j)
+          # slot 1 starts half the pool away from slot 0 so the two workflows
+          # pick different tokens whenever the pool has at least 2
+          START=$(( (DOY - 1 + ROTATION_SLOT * ((N + 1) / 2)) % N ))
+          for o in $(seq 0 $((K-1))); do
+            i=$(( (START + o) % N ))
+            echo "name_$o=${NAMES[$i]}" >> "$GITHUB_OUTPUT"
+          done
+        env:
+          NAMES_JSON: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES }}
+          ROTATION_SLOT: "0"
+      - name: Pick first live token name
+        id: pick
+        run: |
+          set -euo pipefail
+          live() {
+            [ -n "$1" ] && [ "$(curl -s -o /dev/null -w '%{http_code}' \
+              -H "Authorization: Bearer $1" https://api.github.com/user || 
echo 000)" = "200" ]
+          }
+          for pair in "$NAME_0|$CAND_0" "$NAME_1|$CAND_1" "$NAME_2|$CAND_2"; do
+            nm="${pair%%|*}"; tok="${pair#*|}"
+            if [ -z "$tok" ]; then continue; fi
+            echo "::add-mask::$tok"
+            if live "$tok"; then
+              echo "name=$nm" >> "$GITHUB_OUTPUT"
+              echo "Selected rotated token '$nm'"
+              exit 0
+            fi
+          done
+          # empty name makes the agent job fall back to the base 
COPILOT_GITHUB_TOKEN secret
+          [ -n "$BASE" ] && echo "::add-mask::$BASE"
+          echo "name=" >> "$GITHUB_OUTPUT"
+          if live "$BASE"; then echo "Falling back to base 
COPILOT_GITHUB_TOKEN"; else
+            echo "WARNING: no live Copilot token (rotated or base)" >&2; fi
+        env:
+          BASE: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+          CAND_0: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_0)] }}
+          CAND_1: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_1)] }}
+          CAND_2: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_2)] }}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', steps.names.outputs.name_2)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/167)



##########
.github/workflows/daily-issue-triage.lock.yml:
##########
@@ -1299,6 +1302,79 @@
               }
             }
 
+  pick_copilot_token:
+    needs: activation
+    runs-on: ubuntu-latest
+    outputs:
+      name: ${{ steps.pick.outputs.name }}
+    steps:
+      - name: Configure GH_HOST for enterprise compatibility
+        id: ghes-host-config
+        shell: bash
+        run: |
+          # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the 
correct
+          # GitHub instance (GHES/GHEC). On github.com this is a harmless 
no-op.
+          GH_HOST="${GITHUB_SERVER_URL#https://}";
+          GH_HOST="${GH_HOST#http://}";
+          echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+      - name: Compute candidate names by date
+        id: names
+        run: |
+          set -euo pipefail
+          NAMES=()
+          if [ -n "${NAMES_JSON:-}" ]; then
+            mapfile -t NAMES < <(printf '%s' "$NAMES_JSON" | jq -r '.[]')
+          fi
+          N=${#NAMES[@]}
+          K=3   # today's pick plus 2 fallbacks in case it's dead
+          if [ "$N" -eq 0 ]; then
+            for o in $(seq 0 $((K-1))); do echo "name_$o=" >> 
"$GITHUB_OUTPUT"; done
+            echo "GH_AW_COPILOT_TOKEN_NAMES is empty -> agent will use base 
COPILOT_GITHUB_TOKEN"
+            exit 0
+          fi
+          DOY=$(date -u +%-j)
+          # slot 1 starts half the pool away from slot 0 so the two workflows
+          # pick different tokens whenever the pool has at least 2
+          START=$(( (DOY - 1 + ROTATION_SLOT * ((N + 1) / 2)) % N ))
+          for o in $(seq 0 $((K-1))); do
+            i=$(( (START + o) % N ))
+            echo "name_$o=${NAMES[$i]}" >> "$GITHUB_OUTPUT"
+          done
+        env:
+          NAMES_JSON: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES }}
+          ROTATION_SLOT: "1"
+      - name: Pick first live token name
+        id: pick
+        run: |
+          set -euo pipefail
+          live() {
+            [ -n "$1" ] && [ "$(curl -s -o /dev/null -w '%{http_code}' \
+              -H "Authorization: Bearer $1" https://api.github.com/user || 
echo 000)" = "200" ]
+          }
+          for pair in "$NAME_0|$CAND_0" "$NAME_1|$CAND_1" "$NAME_2|$CAND_2"; do
+            nm="${pair%%|*}"; tok="${pair#*|}"
+            if [ -z "$tok" ]; then continue; fi
+            echo "::add-mask::$tok"
+            if live "$tok"; then
+              echo "name=$nm" >> "$GITHUB_OUTPUT"
+              echo "Selected rotated token '$nm'"
+              exit 0
+            fi
+          done
+          # empty name makes the agent job fall back to the base 
COPILOT_GITHUB_TOKEN secret
+          [ -n "$BASE" ] && echo "::add-mask::$BASE"
+          echo "name=" >> "$GITHUB_OUTPUT"
+          if live "$BASE"; then echo "Falling back to base 
COPILOT_GITHUB_TOKEN"; else
+            echo "WARNING: no live Copilot token (rotated or base)" >&2; fi
+        env:
+          BASE: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+          CAND_0: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_0)] }}
+          CAND_1: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_1)] }}
+          CAND_2: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_2)] }}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', steps.names.outputs.name_2)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/166)



##########
.github/workflows/daily-repo-status.lock.yml:
##########
@@ -1295,6 +1298,79 @@
               }
             }
 
+  pick_copilot_token:
+    needs: activation
+    runs-on: ubuntu-latest
+    outputs:
+      name: ${{ steps.pick.outputs.name }}
+    steps:
+      - name: Configure GH_HOST for enterprise compatibility
+        id: ghes-host-config
+        shell: bash
+        run: |
+          # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the 
correct
+          # GitHub instance (GHES/GHEC). On github.com this is a harmless 
no-op.
+          GH_HOST="${GITHUB_SERVER_URL#https://}";
+          GH_HOST="${GH_HOST#http://}";
+          echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+      - name: Compute candidate names by date
+        id: names
+        run: |
+          set -euo pipefail
+          NAMES=()
+          if [ -n "${NAMES_JSON:-}" ]; then
+            mapfile -t NAMES < <(printf '%s' "$NAMES_JSON" | jq -r '.[]')
+          fi
+          N=${#NAMES[@]}
+          K=3   # today's pick plus 2 fallbacks in case it's dead
+          if [ "$N" -eq 0 ]; then
+            for o in $(seq 0 $((K-1))); do echo "name_$o=" >> 
"$GITHUB_OUTPUT"; done
+            echo "GH_AW_COPILOT_TOKEN_NAMES is empty -> agent will use base 
COPILOT_GITHUB_TOKEN"
+            exit 0
+          fi
+          DOY=$(date -u +%-j)
+          # slot 1 starts half the pool away from slot 0 so the two workflows
+          # pick different tokens whenever the pool has at least 2
+          START=$(( (DOY - 1 + ROTATION_SLOT * ((N + 1) / 2)) % N ))
+          for o in $(seq 0 $((K-1))); do
+            i=$(( (START + o) % N ))
+            echo "name_$o=${NAMES[$i]}" >> "$GITHUB_OUTPUT"
+          done
+        env:
+          NAMES_JSON: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES }}
+          ROTATION_SLOT: "0"
+      - name: Pick first live token name
+        id: pick
+        run: |
+          set -euo pipefail
+          live() {
+            [ -n "$1" ] && [ "$(curl -s -o /dev/null -w '%{http_code}' \
+              -H "Authorization: Bearer $1" https://api.github.com/user || 
echo 000)" = "200" ]
+          }
+          for pair in "$NAME_0|$CAND_0" "$NAME_1|$CAND_1" "$NAME_2|$CAND_2"; do
+            nm="${pair%%|*}"; tok="${pair#*|}"
+            if [ -z "$tok" ]; then continue; fi
+            echo "::add-mask::$tok"
+            if live "$tok"; then
+              echo "name=$nm" >> "$GITHUB_OUTPUT"
+              echo "Selected rotated token '$nm'"
+              exit 0
+            fi
+          done
+          # empty name makes the agent job fall back to the base 
COPILOT_GITHUB_TOKEN secret
+          [ -n "$BASE" ] && echo "::add-mask::$BASE"
+          echo "name=" >> "$GITHUB_OUTPUT"
+          if live "$BASE"; then echo "Falling back to base 
COPILOT_GITHUB_TOKEN"; else
+            echo "WARNING: no live Copilot token (rotated or base)" >&2; fi
+        env:
+          BASE: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+          CAND_0: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_0)] }}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', steps.names.outputs.name_0)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/162)



##########
.github/workflows/daily-repo-status.lock.yml:
##########
@@ -1295,6 +1298,79 @@
               }
             }
 
+  pick_copilot_token:
+    needs: activation
+    runs-on: ubuntu-latest
+    outputs:
+      name: ${{ steps.pick.outputs.name }}
+    steps:
+      - name: Configure GH_HOST for enterprise compatibility
+        id: ghes-host-config
+        shell: bash
+        run: |
+          # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the 
correct
+          # GitHub instance (GHES/GHEC). On github.com this is a harmless 
no-op.
+          GH_HOST="${GITHUB_SERVER_URL#https://}";
+          GH_HOST="${GH_HOST#http://}";
+          echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+      - name: Compute candidate names by date
+        id: names
+        run: |
+          set -euo pipefail
+          NAMES=()
+          if [ -n "${NAMES_JSON:-}" ]; then
+            mapfile -t NAMES < <(printf '%s' "$NAMES_JSON" | jq -r '.[]')
+          fi
+          N=${#NAMES[@]}
+          K=3   # today's pick plus 2 fallbacks in case it's dead
+          if [ "$N" -eq 0 ]; then
+            for o in $(seq 0 $((K-1))); do echo "name_$o=" >> 
"$GITHUB_OUTPUT"; done
+            echo "GH_AW_COPILOT_TOKEN_NAMES is empty -> agent will use base 
COPILOT_GITHUB_TOKEN"
+            exit 0
+          fi
+          DOY=$(date -u +%-j)
+          # slot 1 starts half the pool away from slot 0 so the two workflows
+          # pick different tokens whenever the pool has at least 2
+          START=$(( (DOY - 1 + ROTATION_SLOT * ((N + 1) / 2)) % N ))
+          for o in $(seq 0 $((K-1))); do
+            i=$(( (START + o) % N ))
+            echo "name_$o=${NAMES[$i]}" >> "$GITHUB_OUTPUT"
+          done
+        env:
+          NAMES_JSON: ${{ vars.GH_AW_COPILOT_TOKEN_NAMES }}
+          ROTATION_SLOT: "0"
+      - name: Pick first live token name
+        id: pick
+        run: |
+          set -euo pipefail
+          live() {
+            [ -n "$1" ] && [ "$(curl -s -o /dev/null -w '%{http_code}' \
+              -H "Authorization: Bearer $1" https://api.github.com/user || 
echo 000)" = "200" ]
+          }
+          for pair in "$NAME_0|$CAND_0" "$NAME_1|$CAND_1" "$NAME_2|$CAND_2"; do
+            nm="${pair%%|*}"; tok="${pair#*|}"
+            if [ -z "$tok" ]; then continue; fi
+            echo "::add-mask::$tok"
+            if live "$tok"; then
+              echo "name=$nm" >> "$GITHUB_OUTPUT"
+              echo "Selected rotated token '$nm'"
+              exit 0
+            fi
+          done
+          # empty name makes the agent job fall back to the base 
COPILOT_GITHUB_TOKEN secret
+          [ -n "$BASE" ] && echo "::add-mask::$BASE"
+          echo "name=" >> "$GITHUB_OUTPUT"
+          if live "$BASE"; then echo "Falling back to base 
COPILOT_GITHUB_TOKEN"; else
+            echo "WARNING: no live Copilot token (rotated or base)" >&2; fi
+        env:
+          BASE: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+          CAND_0: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_0)] }}
+          CAND_1: ${{ secrets[format('COPILOT_GITHUB_TOKEN_{0}', 
steps.names.outputs.name_1)] }}

Review Comment:
   ## CodeQL / Excessive Secrets Exposure
   
   All organization and repository secrets are passed to the workflow runner in 
[secrets\[format('COPILOT_GITHUB_TOKEN_{0}', steps.names.outputs.name_1)\]](1)
   
   [Show more 
details](https://github.com/apache/cloudstack/security/code-scanning/164)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to