Skip to content

feat(ceremony)!: github reveals its token request whole - #44

Open
SupremaLex wants to merge 1 commit into
mainfrom
feat/github-reveals-the-whole-exchange
Open

SupremaLex wants to merge 1 commit into
mainfrom
feat/github-reveals-the-whole-exchange

Conversation

@SupremaLex

@SupremaLex SupremaLex commented Sep 17, 2026

Copy link
Copy Markdown
Member

What

GitHub's token request is revealed whole, the shape X already has: one revealed run from offset zero to the signed length, no commitment in that direction, every field a verifier reads in the open. The github/v1 exchange used to commit client_secret as a suffix and reveal the body up to it.

The change is one value — secretField: null in profiles.json. regen-ceremony-profiles.py takes GITHUB_TOKEN_SENT_COMMITMENTS to 0, secret_field to None and secretField to null from it. No verifier logic moves; the Solidity diff outside the generated file and the tests is comment-only (checked by diffing with comment lines excluded).

Specified by libid-org/libID#35 (docs/github-public-client, on #31). Deliberately not in this PR: #35's REQ-PLAT-61 five-field canonical form validation. On today's main ASM-PROV-07 covers both platforms and TEST-PLAT-19 probes both endpoints, so GitHub keeps the same decoded-form assumption X uses. That is the scope the CTO set: reveal the range, nothing more.

What it publishes

An attestation of this exchange carries the application credential in plaintext — to the notary that observed the session and to every reader of the chain that verifies it. GitHub documents a public client as one that "will have to ship the client secret in the application's code". The real fixture below therefore contains a working client_secret for App Iv23lioEM9NAR9vO8CmT; it was registered for fixtures and its secret is rotated before this branch is pushed, so the published bytes are dead on arrival.

Fixtures — regenerated, not edited

  • github-ceremony-session.json: from libid-rs ceremony_fixtures against this branch's rust/profiles crate (a local path dependency; the crates.io 0.10 still carries the old layout). It decodes to one revealed range [0..383) and zero sent commitments.
  • github-ceremony-real.json: a real MPC-TLS session captured 2026-09-17 with capture_ceremony, consenting as testyakly (id 293919812). Token direction: [0..406) revealed, zero commitments.
  • The X records are byte-identical to main's, which is what says the change reaches only this profile.

Version

This changes what a github/v1 verifier accepts: _tokenBody demands the profile's exact commitment count, so a record carrying the old committed suffix no longer verifies and one carrying the new layout did not verify before. profiles.json and REQ-COMMON-01B both say that is a new ceremonyVersion. It is an edit to v1 on this evidence: chain-configurations registers no ceremony Platform Verifier on any network, so no github/v1 record has been accepted anywhere for the change to invalidate. If one is registered before this lands, this decision has to be revisited.

Tests

  • GitHubPlatformVerifier.t.sol: the hand-built exchange reveals the request whole via _exchangeBody / _wholeSent; the three bespoke exchange-head tests follow; the two fixture tests read the regenerated records.
  • New: test_rejectsAnExchangeThatCommitsABodySuffix — the layout asserted against the verifier rather than against the generated constant, so it fails if the value ever flips back.
  • test_rejectsAnExchangeWhoseRequestLineIsHidden is unchanged in substance: coverage and the origin rule are checked before the commitment count, which its comment now says.

Verification

forge test 483/483; forge fmt --check, forge lint -D notes, regen-ceremony-profiles.py --check; rust/: 37 tests, fmt --check, clippy -D warnings; ts/: build, 24 tests, lint, fmt — all clean. forge coverage --ir-minimum on the GitHub suite: the touched verifier files at 94–98% lines.

Order across the repos

libid-rs takes libid-profiles from crates.io, and that crate is generated here and published only by a GitHub Release, whose publish-crates job needs forge test green. So the fixture in this PR was generated from this branch's rust/profiles as a local path dependency, and the sequence is forced:

  1. This PR merges. It is green on its own — the fixture travels as a file, not as a dependency edge.
  2. refactor(ceremony): the token request commits nothing, as a rule #45, stacked here — _tokenSentCommitments and the secretField profile field removed, the count a fixed rule; no acceptance change. Merges after this PR and before the release, so the crate ships both.
  3. release/v0.13.0 — its own PR from scripts/bump-version.sh, then gh release create v0.13.0, which publishes libid-profiles 0.13.0.
  4. libid-org/libID-rs chore/github-whole-range-fixtures (draft until step 3 lands): already carries the capture tool's generic redirect URI; then takes the 0.13 pin together with the layout tests that assert the new shape, and re-runs ceremony_fixtures against the published crate to diff against the record carried here — they must be identical.

Follows

  • libid-server-rs tests/ceremony/github.rs overrides secret_field: None locally; it becomes a no-op and can go.

GitHub's exchange hid `client_secret` behind a range commitment and revealed
the body up to it. It now reveals the request whole, the shape X already had:
one revealed run from offset zero to the signed length, no commitment in that
direction, every field a verifier reads in the open.

`secretField: null` in profiles.json is the whole change; the generator takes
GITHUB_TOKEN_SENT_COMMITMENTS to 0, `secret_field` to None and `secretField`
to null from that one value. No verifier logic moves.

An attestation of the exchange therefore publishes the application credential,
to the notary that observed the session and to every reader of the chain. That
is a property of the layout, and GitHub documents a public client as one that
ships its secret.

The fixtures are regenerated rather than edited: the deterministic record from
libid-rs `ceremony_fixtures`, and a real MPC-TLS session captured against
github.com. The X records are byte-identical, which is what says the change
reaches only this profile.

This changes what a `github/v1` verifier accepts: a record carrying the old
committed suffix no longer verifies, and one carrying the new layout did not
verify before. It is an edit to v1 rather than a new ceremony version on this
evidence: chain-configurations registers no ceremony Platform Verifier on any
network, so no github/v1 record has been accepted anywhere for the change to
invalidate.

Assisted-by: Claude Opus 5
Assisted-by: Claude Fable 5.1
Signed-off-by: SupremaLex <georglutsenko@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant