Notes about github cli credential leak 2026-06-16
- GitHub notifications for ~4AM Eastern indicated access from a location while the jsoref account user was asleep
- Event log showed a number of OAuth actions including creating repositories that attempted to steal additional credentials
- 2026-06-16 jsoref removed jsoref from check-spelling and a number of other orgnizations to isolate the account
- 2026-06-16 jsoref the check-spelling dns fail safe was enabled for v0.0.26 with a generic message (
Sorry) - 2026-06-16 jsoref removed all github/oauth applications and rotated github password
- 2026-06-16 jsoref reported the account compromise to github (this is harder than one might imagine as there's no fast path through support for this)
- All GitHub OAuth + GitHub Apps were deleted
- SSH keys were rotated
- Account passwords were changed (including for GitHub)
- All Docker Hub account PATs were revoked (Docker Hub credentials were only used to enable higher pull access)
- Secrets were all dummies
- Credential was a dummy -- the value was gibberish. It was probably set up so that a workflow would run past a certain point
- Credentials were dummies -- the username was test-test-test and the password was gibberish. They were probably set up so that a workflow would run past a certain point
- CHECK_SPELLING (there is no corresponding deploy key)
- KEY (would have related to an obsolete repository that was archived 2025-Dec -- by which point there were no deploy keys for the repository)
- Potentially Docker credentials for use to publish pixelfed -- there is no such docker repository (in fact, there are no repositories)
The GitHub cli oauth token was stolen from jsoref's primary computer. It's unclear how.
In general, each gh instance gets its own token (we determined this through testing). It is generally stored in a system key store (e.g. macOS). But it returned any time you run gh auth token, so anything that can run commands as the user on a system can get it.
-
The attacker performed
artifact.destroyandworkflows.delete_workflow_runto hide action runs (future runs would show counting discontinuities, but as these repositories were abandoned and had no real secrets, that would never happen). -
The attacker named the workflows with a
.prefix to try to hide the file (.github-actions-lint.yml) with lots of verbiage relating tolint(this doesn't actually fit with jsoref's patterns, but it's likely a generic attack of sorts). Each workflow includes the same template ("common secrets") as well as any secrets that are listed in the repository'ssecretslist. -
The attacker pushed a second commit to delete their commits:
- https://github.com/check-spelling-sandbox/realopinsight/commit/69df9b593c12947b2b369b774a65c13a0796c05f.patch
- https://github.com/check-spelling-sandbox/stack/commit/eae4c24a1f5b68b8b47f89f02c546302050f492b.patch
- https://github.com/check-spelling-sandbox/pixelfed/commit/46a0443347f17765f3d39ffcdca1727cfa6f0208.patch
- https://github.com/check-spelling-sandbox/test-5/commit/27c84565506a22ce077887a385ad4fdf0531ec70.patch (this is a private repository, but the contents of each workflow are approximately equivalent)
- https://github.com/GarnerBuild/dummy/commit/8360e9d0407b35055c4e744ee58acde25ae3ba8e.patch