name: "Setup Copilot CLI" description: "Install the GitHub Copilot CLI for use in GitHub Actions workflows" branding: icon: "terminal" color: "blue" inputs: version: description: "Version of Copilot CLI to install (e.g. '1.0.0', 'latest', 'prerelease')" required: false default: "latest" github-token: description: "GitHub token to download Copilot CLI. Defaults to the workflow token." required: false default: ${{ github.token }} outputs: version: description: "The version of Copilot CLI that was installed" value: ${{ steps.version.outputs.version }} runs: using: "composite" steps: - name: Install Copilot CLI shell: bash env: VERSION: ${{ inputs.version }} PREFIX: ${{ runner.tool_cache }}/copilot GITHUB_TOKEN: ${{ inputs.github-token }} run: curl -fsSL https://gh.io/copilot-install | bash - name: Add to PATH shell: bash run: echo "${{ runner.tool_cache }}/copilot/bin" >> "$GITHUB_PATH" - name: Check for unnecessary write permissions shell: bash env: GH_TOKEN: ${{ inputs.github-token }} run: | API="$GITHUB_API_URL/repos/$GITHUB_REPOSITORY" writes_found=() # Probe write access by sending invalid requests to write endpoints. # 422/409 = token has write permission (passed auth, failed validation) # 403 = token does not have write permission probe_write() { local scope="$1" url="$2" method="${3:-POST}" body="${4:-\{\}}" code=$(curl -s -o /dev/null -w "%{http_code}" \ -X "$method" \ -H "Authorization: bearer $GH_TOKEN" \ -H "Accept: application/vnd.github+json" \ "$url" -d "$body") case "$code" in 2[0-9][0-9]|422|409) writes_found+=("$scope") ;; esac } probe_write "actions" "$API/actions/workflows/0/dispatches" POST '{"ref":"__probe__"}' probe_write "checks" "$API/check-runs" POST '{}' probe_write "contents" "$API/contents/__probe__" PUT '{"message":"probe"}' probe_write "deployments" "$API/deployments" POST '{}' probe_write "issues" "$API/issues" POST '{}' probe_write "packages" "$GITHUB_API_URL/user/packages/container/__nonexistent__/versions/0" DELETE '' probe_write "pages" "$API/pages" POST '{}' probe_write "pull-requests" "$API/pulls" POST '{}' probe_write "statuses" "$API/statuses/$GITHUB_SHA" POST '{}' if [ ${#writes_found[@]} -gt 0 ]; then echo "" echo "::warning::⚠️ The github-token passed to setup-copilot has write permissions: ${writes_found[*]}. Granting write permissions to the Copilot CLI in Actions workflows is a security risk. Recommend scoping your token with least-privilege permissions." { echo "### ⚠️ setup-copilot: Excessive Token Permissions" echo "" echo "The \`github-token\` input has **write** access to: \`${writes_found[*]}\`." echo "" echo "Giving write permissions to the Copilot CLI in Actions workflows is a security risk." echo "" echo "**Recommendation:** add a \`permissions\` block to your job:" echo '```yaml' echo "permissions:" echo " contents: read" echo '```' echo "and add a separate job with write permissions for steps that need it." } >> "$GITHUB_STEP_SUMMARY" fi - name: Verify installation id: version shell: bash run: | copilot --version echo "version=$(copilot --version | head -1)" >> "$GITHUB_OUTPUT"