Releases are now Authenticode-signed (K22-REL-05) through the standards' shared workflow, which already carries the signing steps behind sign (azure/login v3.1.0 and azure/artifact-signing-action v2.0.0, both SHA-pinned and current; vpk pack --azureTrustedSignFile). ADR 0008.
release.yml: sign: true; new verify-signatures job after release downloads the published Setup.exe, portable zip and CLI zip and runs signtool verify /pa /all + Get-AuthenticodeSignature on every gclo executable, failing on an invalid, untimestamped or foreign-publisher signature (TRUSTED_SIGNING_SUBJECT).
Authentication is GitHub OIDC: an Entra application gclo-release-signing with a federated credential for repo:KofTwentyTwo/gclo:environment:release and only Artifact Signing Certificate Profile Signer on the certificate profile. No secret, key or PFX anywhere. The identity is release-environment variables: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_SUBSCRIPTION_ID, TRUSTED_SIGNING_ENDPOINT, TRUSTED_SIGNING_ACCOUNT, TRUSTED_SIGNING_PROFILE, TRUSTED_SIGNING_SUBJECT.
.github/scripts/Set-ReleaseSigning.ps1: idempotent Azure configuration (reads the existing account and Active profile through ARM, ensures app + service principal + federated credential + profile-scoped role, prints the gh variable set lines). Run interactively by the owner; never creates secrets or touches the account, validation or profile.
Docs: RELEASING.md ("Code signing", local signing with SignTool + the Microsoft.ArtifactSigning.Client dlib, the verify job), SECURITY.md, README verify step 4, threat-model revision row.
Closes#57 (part of #62). After the first signed release verifies, EX-0002 closes for gclo in the standards register.
Azure configuration status
Pending the owner's interactive sign-in; the script output and signtool verify results of the first signed prerelease will be posted here before merge.
How it was tested
actionlint clean; PSScriptAnalyzer 0 findings.
Verification of a real signed build: pending the Azure configuration (recorded here when done).
## What
Releases are now Authenticode-signed (K22-REL-05) through the standards' shared workflow, which already carries the signing steps behind `sign` (`azure/login` v3.1.0 and `azure/artifact-signing-action` v2.0.0, both SHA-pinned and current; `vpk pack --azureTrustedSignFile`). ADR 0008.
- `release.yml`: `sign: true`; new `verify-signatures` job after `release` downloads the published Setup.exe, portable zip and CLI zip and runs `signtool verify /pa /all` + `Get-AuthenticodeSignature` on every gclo executable, failing on an invalid, untimestamped or foreign-publisher signature (`TRUSTED_SIGNING_SUBJECT`).
- Authentication is GitHub OIDC: an Entra application `gclo-release-signing` with a federated credential for `repo:KofTwentyTwo/gclo:environment:release` and only *Artifact Signing Certificate Profile Signer* on the certificate profile. No secret, key or PFX anywhere. The identity is `release`-environment **variables**: `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_SUBSCRIPTION_ID`, `TRUSTED_SIGNING_ENDPOINT`, `TRUSTED_SIGNING_ACCOUNT`, `TRUSTED_SIGNING_PROFILE`, `TRUSTED_SIGNING_SUBJECT`.
- `.github/scripts/Set-ReleaseSigning.ps1`: idempotent Azure configuration (reads the existing account and Active profile through ARM, ensures app + service principal + federated credential + profile-scoped role, prints the `gh variable set` lines). Run interactively by the owner; never creates secrets or touches the account, validation or profile.
- Docs: RELEASING.md ("Code signing", local signing with SignTool + the `Microsoft.ArtifactSigning.Client` dlib, the verify job), SECURITY.md, README verify step 4, threat-model revision row.
Closes #57 (part of #62). After the first signed release verifies, EX-0002 closes for gclo in the standards register.
## Azure configuration status
Pending the owner's interactive sign-in; the script output and `signtool verify` results of the first signed prerelease will be posted here before merge.
## How it was tested
- `actionlint` clean; PSScriptAnalyzer 0 findings.
- Verification of a real signed build: pending the Azure configuration (recorded here when done).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Artifact Signing Certificate Profile Signer on …/certificateProfiles/releases only, for the service principal and (for local one-offs) the owner user. No subscription-level role for the application.
release environment variables set: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_SUBSCRIPTION_ID, TRUSTED_SIGNING_ENDPOINT, TRUSTED_SIGNING_ACCOUNT, TRUSTED_SIGNING_PROFILE, TRUSTED_SIGNING_SUBJECT=James Maes. No secret was created anywhere.
signtool verify /pa /all /v gclo.exe → exit 0; chain James Maes ← Microsoft ID Verified CS EOC CA 03 ← Microsoft ID Verified Code Signing PCA 2021 ← Microsoft Identity Verification Root CA 2020. Get-AuthenticodeSignature: Valid, subject CN=James Maes, O=James Maes, L=Chester, S=il, C=US, timestamper Microsoft Public RSA Time Stamping Authority.
The verify-signatures job expects the subject to contain "James Maes" (the validated publisher), which is what Windows will show.
Next: merge → v1.0.2-beta.2 (first CI-signed build, OIDC path exercised for real) → verify the published assets with signtool → v1.0.2 → close EX-0002 in the standards register.
## Azure configuration done (2026-10-10, run by the owner's interactive session)
Verified against the deployed resources, not the setup notes:
| Item | Value |
| --- | --- |
| Tenant | `4ebeb0ad-5782-487a-a1b4-5080255774cf` (`koftwentytwooutlook.onmicrosoft.com`) |
| Subscription | `8ef2479e-3346-4cba-93ad-101c6cd237a0` "Kof22 Signing Account" |
| Signing account | `kof22signing`, `rg-code-signing`, **eastus**, endpoint `https://eus.codesigning.azure.net` |
| Certificate profile | `releases`, PublicTrust, **Active**; certificate subject `CN=James Maes, O=James Maes, L=Chester, S=il, C=US` (thumbprint `BAAA6D7D…31D3`) |
| Entra application | `gclo-release-signing`, client id `5fc7f572-6ffa-4538-bcf4-65282dd0859a` (new; no existing identity existed in the tenant) |
| Federated credential | issuer `https://token.actions.githubusercontent.com`, subject `repo:KofTwentyTwo/gclo:environment:release`, audience `api://AzureADTokenExchange` |
| Role | *Artifact Signing Certificate Profile Signer* on `…/certificateProfiles/releases` only, for the service principal and (for local one-offs) the owner user. No subscription-level role for the application. |
`release` environment variables set: `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_SUBSCRIPTION_ID`, `TRUSTED_SIGNING_ENDPOINT`, `TRUSTED_SIGNING_ACCOUNT`, `TRUSTED_SIGNING_PROFILE`, `TRUSTED_SIGNING_SUBJECT=James Maes`. No secret was created anywhere.
## Signing test (local, same account and profile)
`signtool sign /fd SHA256 /tr http://timestamp.acs.microsoft.com /td SHA256 /dlib Azure.CodeSigning.Dlib.dll /dmdf metadata.json gclo.exe gclo.dll` → 2 signed, 0 warnings, 0 errors.
`signtool verify /pa /all /v gclo.exe` → exit 0; chain *James Maes* ← Microsoft ID Verified CS EOC CA 03 ← Microsoft ID Verified Code Signing PCA 2021 ← Microsoft Identity Verification Root CA 2020. `Get-AuthenticodeSignature`: `Valid`, subject `CN=James Maes, O=James Maes, L=Chester, S=il, C=US`, timestamper Microsoft Public RSA Time Stamping Authority.
The `verify-signatures` job expects the subject to contain **"James Maes"** (the validated publisher), which is what Windows will show.
Next: merge → `v1.0.2-beta.2` (first CI-signed build, OIDC path exercised for real) → verify the published assets with signtool → `v1.0.2` → close EX-0002 in the standards register.
Replaces #93 and #95 (rebuilt on main after #94; same commits, signed and signed-off; the threat-model revision table keeps both the #91 and the signing rows). The thumbprint quoted above is that day's certificate only: Azure Artifact Signing rotates certificates every few days, nothing pins it, and timestamped signatures stay valid.
Replaces #93 and #95 (rebuilt on main after #94; same commits, signed and signed-off; the threat-model revision table keeps both the #91 and the signing rows). The thumbprint quoted above is that day's certificate only: Azure Artifact Signing rotates certificates every few days, nothing pins it, and timestamped signatures stay valid.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
Releases are now Authenticode-signed (K22-REL-05) through the standards' shared workflow, which already carries the signing steps behind
sign(azure/loginv3.1.0 andazure/artifact-signing-actionv2.0.0, both SHA-pinned and current;vpk pack --azureTrustedSignFile). ADR 0008.release.yml:sign: true; newverify-signaturesjob afterreleasedownloads the published Setup.exe, portable zip and CLI zip and runssigntool verify /pa /all+Get-AuthenticodeSignatureon every gclo executable, failing on an invalid, untimestamped or foreign-publisher signature (TRUSTED_SIGNING_SUBJECT).gclo-release-signingwith a federated credential forrepo:KofTwentyTwo/gclo:environment:releaseand only Artifact Signing Certificate Profile Signer on the certificate profile. No secret, key or PFX anywhere. The identity isrelease-environment variables:AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_SUBSCRIPTION_ID,TRUSTED_SIGNING_ENDPOINT,TRUSTED_SIGNING_ACCOUNT,TRUSTED_SIGNING_PROFILE,TRUSTED_SIGNING_SUBJECT..github/scripts/Set-ReleaseSigning.ps1: idempotent Azure configuration (reads the existing account and Active profile through ARM, ensures app + service principal + federated credential + profile-scoped role, prints thegh variable setlines). Run interactively by the owner; never creates secrets or touches the account, validation or profile.Microsoft.ArtifactSigning.Clientdlib, the verify job), SECURITY.md, README verify step 4, threat-model revision row.Closes #57 (part of #62). After the first signed release verifies, EX-0002 closes for gclo in the standards register.
Azure configuration status
Pending the owner's interactive sign-in; the script output and
signtool verifyresults of the first signed prerelease will be posted here before merge.How it was tested
actionlintclean; PSScriptAnalyzer 0 findings.🤖 Generated with Claude Code
Azure configuration done (2026-10-10, run by the owner's interactive session)
Verified against the deployed resources, not the setup notes:
4ebeb0ad-5782-487a-a1b4-5080255774cf(koftwentytwooutlook.onmicrosoft.com)8ef2479e-3346-4cba-93ad-101c6cd237a0"Kof22 Signing Account"kof22signing,rg-code-signing, eastus, endpointhttps://eus.codesigning.azure.netreleases, PublicTrust, Active; certificate subjectCN=James Maes, O=James Maes, L=Chester, S=il, C=US(thumbprintBAAA6D7D…31D3)gclo-release-signing, client id5fc7f572-6ffa-4538-bcf4-65282dd0859a(new; no existing identity existed in the tenant)https://token.actions.githubusercontent.com, subjectrepo:KofTwentyTwo/gclo:environment:release, audienceapi://AzureADTokenExchange…/certificateProfiles/releasesonly, for the service principal and (for local one-offs) the owner user. No subscription-level role for the application.releaseenvironment variables set:AZURE_TENANT_ID,AZURE_CLIENT_ID,AZURE_SUBSCRIPTION_ID,TRUSTED_SIGNING_ENDPOINT,TRUSTED_SIGNING_ACCOUNT,TRUSTED_SIGNING_PROFILE,TRUSTED_SIGNING_SUBJECT=James Maes. No secret was created anywhere.Signing test (local, same account and profile)
signtool sign /fd SHA256 /tr http://timestamp.acs.microsoft.com /td SHA256 /dlib Azure.CodeSigning.Dlib.dll /dmdf metadata.json gclo.exe gclo.dll→ 2 signed, 0 warnings, 0 errors.signtool verify /pa /all /v gclo.exe→ exit 0; chain James Maes ← Microsoft ID Verified CS EOC CA 03 ← Microsoft ID Verified Code Signing PCA 2021 ← Microsoft Identity Verification Root CA 2020.Get-AuthenticodeSignature:Valid, subjectCN=James Maes, O=James Maes, L=Chester, S=il, C=US, timestamper Microsoft Public RSA Time Stamping Authority.The
verify-signaturesjob expects the subject to contain "James Maes" (the validated publisher), which is what Windows will show.Next: merge →
v1.0.2-beta.2(first CI-signed build, OIDC path exercised for real) → verify the published assets with signtool →v1.0.2→ close EX-0002 in the standards register.Replaces #93 and #95 (rebuilt on main after #94; same commits, signed and signed-off; the threat-model revision table keeps both the #91 and the signing rows). The thumbprint quoted above is that day's certificate only: Azure Artifact Signing rotates certificates every few days, nothing pins it, and timestamped signatures stay valid.