Repository navigation
Commits via git are unverified; switch to GraphQL for commits #18565
Description
Activity
- locked and limited conversation to collaborators
on Feb 26, 2026 - unlocked this conversation
on Feb 26, 2026 /scout collect info
Reacted by github-actions/scout collect info
Reacted by github-actionsgithub-actions commented
on Feb 27, 2026 on Feb 27, 2026 – with GitHub ActionsContributorMore actions🔍 Scout Research Report
Triggered by
@pelikhanExecutive Summary
The issue is well-understood and has a clean solution. Commits made via
git commit+git pushusingGITHUB_TOKENare unverified because GitHub does not automatically GPG-sign commits made through the standard Git protocol. ThecreateCommitOnBranchGraphQL mutation (released by GitHub in Sep 2021) automatically signs commits using GitHub's own GPG key, making them appear as Verified in the UI — no GPG key management required.This repo currently uses
git commit+git pushin at least two places:format-and-commit.ymlandscripts/changeset.js, plus many.lock.ymlworkflows that instruct AI agents to usegit commit.Research Findings
Why
gitcommits via GITHUB_TOKEN are unverifiedGitHub Actions'
GITHUB_TOKENis a bot token. When you use it to authenticategit pushover HTTPS, the commits are created locally without a cryptographic signature. GitHub has no way to verify those commits because there is no GPG/SSH key attached.From GitHub Docs on commit signature verification:
GitHub will automatically use GPG to sign commits you make using the web interface. Commits signed by GitHub will have a verified status.
The key: only commits made through GitHub's API (web, GraphQL, REST blob+tree) are auto-signed.
The
createCommitOnBranchGraphQL MutationReleased September 2021 ([GitHub Changelog]((github.blog/redacted)
Commits authored using the new API are automatically GPG signed and are marked as verified in the GitHub UI. GitHub Apps can use the mutation to author commits directly or on behalf of users.
Key advantages over the older REST blob/tree approach:
- Single API call for multiple files (no separate blob + tree + commit + ref steps)
- Auto-signed/verified by default
- Works with
GITHUB_TOKEN, GitHub App tokens, and PATs
Implementation Approaches
Option 1:
gh api graphqlin shell (as described in the issue)Requires a
.github/api/createCommitOnBranch.gqlfile and collecting changed files viagit diff --name-only. Files are base64-encoded and passed as form fields. Works well for small-to-medium file sets.Known caveat: shell argument list length limit (
/usr/bin/gh: Argument list too long) when many files change — workaround is to write the query body to a temp file.Option 2:
actions/github-scriptwith GraphQLUsing
@octokit/graphqlin a workflow step handles both additions and deletions cleanly in JavaScript. No shell escaping issues, easier to handle dynamic file lists. Example from [StackOverflow discussion]((stackoverflow.com/redacted)Option 3: Third-party reusable Actions
Action Approach Notes IAreKyleW00t/verified-bot-commitREST API (blob+tree+commit+ref) Linux/macOS/Windows; uses GITHUB_TOKENor GitHub App tokenstep-security/github-api-commit-actionGraphQL createCommitOnBranchFetches latest OID just before committing; works on checked-out branch Asana/push-signed-commitsGraphQL createCommitOnBranchPython-based composite action; local commits → re-signs via API; uses git reset --hardto sync localImportant Caveats
-
Commit hash changes: When using the GraphQL API, GitHub signs and re-creates the commit server-side. The resulting SHA will differ from any locally created commit. Workflows must update their local branch ref after committing via API (e.g.,
git fetch && git reset --hard origin/branch). -
File size limit: API blob uploads are limited to ~40 MiB per file.
-
"Web Commit Signing" org setting: Some reports indicate that for GitHub App tokens (not
GITHUB_TOKEN), the org-level "Web Commit Signing" setting may need to be enabled. For standardGITHUB_TOKENin GitHub Actions, this is not an issue. -
Deletions:
createCommitOnBranchsupports bothadditionsanddeletionsinfileChanges. Thegh api graphqlshell approach requires extra work to handle deleted files (not just modified/added ones).
Current State in This Repo
The following places currently use unverified
git commit:.github/workflows/format-and-commit.yml— usesgit add -A && git commit+git pushscripts/changeset.js— usesgit commit -m "Release ..."+git push- Multiple
.lock.ymlagent workflows — instruct the AI agent via# --allow-tool shell(git commit:*)/# - Bash(git commit:*)comments
Recommendations
-
Replace
git commit+git pushinformat-and-commit.ymlwith agh api graphqlstep using thecreateCommitOnBranchmutation. This is the highest-impact, most straightforward change. -
Update
scripts/changeset.jsto use the GraphQL API for the release commit, or use a reusable action likestep-security/github-api-commit-action. -
For AI agent lock workflows (
.lock.ymlfiles), consider adding a post-commit step that re-creates the commit via GraphQL, or instruct the agent to use the GraphQL API directly instead ofgit commit. TheAsana/push-signed-commitscomposite action pattern (local commit → API re-sign → local reset) may be a good fit here. -
Consider a shared reusable workflow for the GraphQL commit step to avoid duplicating the mutation across many workflows.
Key Sources
- [GitHub Changelog: A simpler API for authoring commits (2021)]((github.blog/redacted)
- [dev.to: GitHub: signing commit in a workflow]((dev.to/redacted)
- GitHub Gist: Verified commits made easy with GitHub Actions (REST API approach)
- step-security/github-api-commit-action
- Asana/push-signed-commits
- IAreKyleW00t/verified-bot-commit
References: §22472950127
🔭 Intelligence gathered by Scout
- added a parent issue
on Mar 18, 2026
When using the GITHUB_TOKEN via git the resulting commits show up as unverified.
If the same commits are made with the GITHUB_TOKEN through the graphql api (as discussed here https://gist.github.com/swinton/03e84635b45c78353b1f71e41007fc7c?permalink_comment_id=5401086#gistcomment-5401086 ):
The resulting commits appear as signed/verified.