XS⚠️ ◾ Adopt GitHub App Authentication - #879
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run write-dependent PR metrics in trusted pull_request_target context so fork PRs can mint a scoped installation token through Azure OIDC. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Harden privileged PR metrics ordering, restore required build scopes, and make token generation diagnostics and output handling explicit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run GitHub App token minting in the normal pull request workflow now that the branch is hosted directly in the upstream repository. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates Omex automation to stop relying on long-lived GitHub PATs and instead mint short-lived GitHub App installation tokens using Azure OIDC + Azure Key Vault, then use those tokens for GitHub operations in both GitHub Actions and Azure Pipelines.
Changes:
- Introduces a reusable composite action + PowerShell script to mint GitHub App installation tokens from a Key Vault–stored private key.
- Updates scheduled automation workflows (package update, PR metrics) to use minted installation tokens instead of PATs / default tokens.
- Updates the Azure Pipelines “GitHub forward” pipeline to fetch from GitHub using the minted installation token rather than a PAT.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/package-update.yml | Mints a GitHub App token via OIDC/Key Vault and uses it for checkout + PR creation instead of a PAT. |
| .github/workflows/build.yml | Mints a GitHub App token for PR Metrics, and adjusts workflow/job permissions. |
| .github/pipelines/github-forward.yml | Replaces PAT-based git fetch with GitHub App token–based auth in Azure Pipelines. |
| .github/dependabot.yml | Extends Dependabot scanning to include the new local action directory. |
| .github/actions/mint-github-app-token/New-GitHubAppToken.ps1 | Adds the shared token-minting script used by both Actions and Pipelines. |
| .github/actions/mint-github-app-token/action.yml | Adds the composite action wrapper (Azure login + token minting). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Use the checked-out local action in the direct same-repository pull request, matching the established PR Metrics workflow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
.github/workflows/build.yml:49
packages: writeis granted to the entirebuildjob even though publishing only happens on a gated release condition. This increases the blast radius if any step is compromised or if untrusted code runs in the job. Prefer splitting publishing into a separate job withpackages: writeand keeping the main build/test job at read-only permissions.
permissions:
contents: read
packages: write
Use the nonexportable Omex RSA key for remote RS256 signing, matching the established PR Metrics design. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Suppressed comments (2)
.github/workflows/build.yml:19
azure/login(and OIDC in general) does not issue anid-tokenforpull_requestworkflows coming from forks, so this job will fail for external contributors’ PRs once it starts depending on OIDC to mint the App token. If PR Metrics should only run for in-repo branches, add a guard to skip fork PRs.
if: github.event_name == 'pull_request'
.github/workflows/build.yml:49
- This job grants
packages: writefor all triggers (includingpull_request). Because workflows onpull_requestrun the workflow definition from the PR’s merge commit, this broad permission increases the blast radius if the workflow is modified in a PR (e.g., adding a package publish step). Consider splitting publishing into a release-only job/workflow that is the only one grantedpackages: write, and keep the PR build job at read-only permissions.
permissions:
contents: read
packages: write
Request only the pull request permission granted to the GitHub App installation, matching PR Metrics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR Metrics✔ Thanks for keeping your pull request small.
Metrics computed by PR Metrics. Add it to your Azure DevOps and GitHub PRs! |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Suppressed comments (1)
.github/pipelines/github-forward.yml:88
- Same concern here: the Base64-encoded header derived from the secret token may bypass Azure DevOps masking and leak in logs. If the remote URL embeds the token (or you set up a masked credential helper once), subsequent fetches can omit the derived Authorization header entirely.
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("x-access-token:$env:GITHUB_APP_TOKEN"))
git -c "http.extraheader=AUTHORIZATION: basic $auth" fetch omexgithubremote $env:GITHUBBRANCH
Isolate package publication, support fork metrics without executing PR code, and keep derived Git credentials masked and off command lines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Suppressed comments (1)
.github/pipelines/github-forward.yml:95
- Same issue here:
[Text.Encoding]may not resolve in PowerShell, andhttp.extraheadershould be scoped to github.com to reduce the chance of credential leakage to other remotes/hosts.
$auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("x-access-token:$env:GITHUB_APP_TOKEN"))
Write-Host "##vso[task.setsecret]$auth"
$env:GIT_CONFIG_COUNT = '1'
$env:GIT_CONFIG_KEY_0 = 'http.extraheader'
$env:GIT_CONFIG_VALUE_0 = "AUTHORIZATION: basic $auth"
Store the merge ref at the same local path exposed through GITHUB_REF for unambiguous resolution. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
.github/workflows/build.yml:50
- In
releaseruns, thebuildjob already runsdotnet packfor both matrix configurations, and then thepublishjob does a seconddotnet packbefore pushing. This redundantly rebuilds packages during releases and increases CI time/flakiness risk.
A minimal way to avoid duplicate work is to skip dotnet pack in the build job when the workflow is triggered by a release (the publish job will still produce the packages to publish).
- name: Create NuGet packages
run: dotnet pack --no-build --configuration ${{ matrix.configuration }} --no-restore
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
.github/workflows/build.yml:56
- The new
publishjob depends on the entirebuildmatrix (needs: build). Onreleaseevents this means the Debug matrix leg must also succeed before packages can publish, which can unnecessarily block a release on a Debug-only failure and slows the release pipeline.
Consider splitting out a Release-only build job for release publishing (e.g., build-release with configuration: Release and if: github.event_name == 'release') and have publish depend on that job, while keeping the Debug build for PR/push validation only.
publish:
if: github.event_name == 'release' && !github.event.release.prerelease && github.event.release.target_commitish == 'main'
name: Publish NuGet packages
needs: build
runs-on: windows-latest
Bind privileged jobs to protected environments, document explicit ownership, and rely on key-scoped Azure trust. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Warning
- Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.
Pull request overview
Copilot reviewed 5 out of 8 changed files in this pull request and generated 1 comment.
Files excluded by content exclusion policy (3)
- .github/workflows/build.yml
- .github/workflows/package-update.yml
- .github/workflows/pr-metrics.yml
Use the single main-only protected environment for all GitHub App token jobs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Warning
- Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.
Pull request overview
Copilot reviewed 5 out of 8 changed files in this pull request and generated no new comments.
Files excluded by content exclusion policy (3)
- .github/workflows/build.yml
- .github/workflows/package-update.yml
- .github/workflows/pr-metrics.yml
Require the Omex administrator team to review every file under .github/workflows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Warning
- Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.
Pull request overview
Copilot reviewed 5 out of 8 changed files in this pull request and generated no new comments.
Files excluded by content exclusion policy (3)
- .github/workflows/build.yml
- .github/workflows/package-update.yml
- .github/workflows/pr-metrics.yml
Suppressed comments (3)
Previously missed (3) — in code that hasn't changed since the last review.
CODEOWNERS:4
- The comment says privileged GitHub App automation should be under Omex administrator review, but the mint-token action directory is owned by
@microsoft/omex(not @microsoft/omex-admin). Either update the ownership to match the intent (admin review for the token-minting action), or adjust the comment to reflect that@microsoft/omexownership is expected.
# Keep privileged GitHub App automation under explicit Omex administrator review.
/.github/actions/mint-github-app-token/ @microsoft/omex
.github/actions/mint-github-app-token/New-GitHubAppToken.ps1:162
- In Azure Pipelines,
task.setvariable ...;issecret=truemakes the Key Vault access token available to subsequent tasks in the job. Since this token is only needed for the immediate signing call, prefer masking it without persisting it as a pipeline variable (usetask.setsecretinstead) to reduce the secret's exposure surface.
elseif (-not [string]::IsNullOrWhiteSpace($env:TF_BUILD))
{
Write-Output -InputObject "##vso[task.setvariable variable=KeyVaultAccessToken;issecret=true]$vaultAccessToken"
}
.github/actions/mint-github-app-token/action.yml:35
- The composite action references a third-party action via a mutable tag (
azure/login@v3). For supply-chain safety, consider pinning to a specific commit SHA (and optionally keeping a comment with the corresponding version tag) so future upstream tag moves cannot change what runs in CI.
- name: Azure – Sign-in
uses: azure/login@v3
with:
client-id: ${{ inputs.azure-client-id }}
tenant-id: ${{ inputs.azure-tenant-id }}
subscription-id: ${{ inputs.azure-subscription-id }}
There was a problem hiding this comment.
Warning
- Copilot's review of this pull request may be incomplete because some of the changed files are excluded by your Copilot content exclusion settings. See Excluding content from Copilot for details.
Pull request overview
Copilot reviewed 5 out of 8 changed files in this pull request and generated no new comments.
Files excluded by content exclusion policy (3)
- .github/workflows/build.yml
- .github/workflows/package-update.yml
- .github/workflows/pr-metrics.yml
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
.github/actions/mint-github-app-token/New-GitHubAppToken.ps1:162
- In Azure Pipelines (
TF_BUILD), the script persists the Key Vault access token into a pipeline variable (KeyVaultAccessToken). This increases the exposure surface of a highly-privileged token and is unnecessary here because the variable is not referenced anywhere else in the repo. Prefer only registering it as a secret for log masking (or omit entirely) rather than storing it as a variable.
elseif (-not [string]::IsNullOrWhiteSpace($env:TF_BUILD))
{
Write-Output -InputObject "##vso[task.setvariable variable=KeyVaultAccessToken;issecret=true]$vaultAccessToken"
}
Purpose
Replace long-lived GitHub PAT authentication with short-lived GitHub App installation tokens backed by Azure Key Vault.
Impact
GitHub automation now uses scoped, temporary credentials across GitHub Actions and Azure Pipelines, reducing credential exposure and aligning Omex with the established PR Metrics design.