Skip to content

feat: add registry artifact integrity check - #1091

Draft
DevelopmentCats wants to merge 2 commits into
mainfrom
devcats/registry-integrity-canary
Draft

feat: add registry artifact integrity check#1091
DevelopmentCats wants to merge 2 commits into
mainfrom
devcats/registry-integrity-canary

Conversation

@DevelopmentCats

@DevelopmentCats DevelopmentCats commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a scheduled check that verifies responses for module tarballs from registry.coder.com originate from the registry application itself.

Draft — design is still being discussed internally. See notes below.

How

Every response from the registry application sets a Server-Version header. The check probes a rotating sample of module tarball URLs and asserts the header is present.

Implementation notes:

  • Probes /download/, not the frontend pages the health check covers.
  • Sends Accept-Encoding: gzip, which the download handler requires.
  • Failures are reported in two buckets: request failures (likely availability, cross-reference the health check) and header failures.

Why this is separate from check-registry-site-health

The two answer different questions. Health asks whether the registry is reachable and reports availability to the public status page. This asks whether responses are coming from the registry application, which warrants engineering triage rather than an automatic public status update.

This workflow has no Instatus credentials in scope and cannot open a public incident.

Known limitations

  • This is a tripwire, not an integrity guarantee. A header check verifies who answered, not what was served. It does not verify tarball contents.
  • Cache coverage is incomplete. Requests are currently cache-busted so they reach the origin, which means the check does not observe what a cached client request would receive. Both paths need covering.
  • Content verification against the source of truth is not addressed here; that requires comparing served artifacts to their release tags.

Status

Draft pending internal design review. Not ready for merge.

Test plan

Validated locally against production and against local origins with and without the header. bun fmt:ci and shellcheck (at CI severity) pass.

Copilot AI lite review requested due to automatic review settings September 1, 2026 18:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new GitHub Actions “integrity canary” to detect cases where registry.coder.com might be serving tarballs from a non-registry origin by asserting the presence of the Server-Version header on sampled /download/ responses.

Changes:

  • Introduces a scheduled workflow (check-registry-integrity) that runs every 15 minutes (offset from the existing health check) and executes a new integrity-check script.
  • Adds a bash script that discovers modules via the registry API, samples a rotating window, and verifies the Server-Version header on tarball HEAD responses (with cache-busting + Accept-Encoding: gzip).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
.github/workflows/check_registry_integrity.yaml Adds scheduled workflow to run the integrity canary script.
.github/scripts/check_registry_integrity.sh Implements module discovery + sampled tarball header verification and triage-oriented failure output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/scripts/check_registry_integrity.sh
Comment thread .github/workflows/check_registry_integrity.yaml
Comment thread .github/workflows/check_registry_integrity.yaml Outdated
@phorcys420

Copy link
Copy Markdown
Member

@DevelopmentCats this is kind of easy to bypass if they just decide to mimick it, or if they serve the same thing as us except the binaries, can we also make this check if the served module corresponds to its GH counterpart?

e.g for Mux, GET https://registry.coder.com/terraform_protocol/coder/mux/coder/1.5.0/download, X-Terraform-Get is set to /download/coder/1.5.0-mux.tar.gz.

So you'd check that /download/coder/1.5.0-mux.tar.gz is the same as the tarball you'd get from the release/coder/mux/v1.5.0 tag. Another solution would be that we also release the modules on GitHub at the same time and then we'd just have to compare the GH release with the registry.coder.com asset.

@phorcys420

Copy link
Copy Markdown
Member

^ feel free to say no and we'll do it later too

@DevelopmentCats

Copy link
Copy Markdown
Collaborator Author

^ feel free to say no and we'll do it later too

No I think you are actually right on this @phorcys420 I was mostly just getting us to a starting point this so that if there was any byte difference in the modules it would be caught, but you have a valid point

@DevelopmentCats DevelopmentCats changed the title feat: add registry integrity canary feat: add registry artifact integrity check Sep 2, 2026
@DevelopmentCats
DevelopmentCats marked this pull request as draft September 2, 2026 13:16
Adds a scheduled check that verifies module tarball responses from
registry.coder.com originate from the registry application.

Every response from the registry application sets a Server-Version header
via serverVersionMiddleware, so a response without one did not come from
the registry application. The check probes a rotating sample of tarball
URLs and asserts the header is present.

Kept separate from check-registry-site-health: that workflow reports
availability to the public status page, whereas a failure here warrants
engineering triage rather than an automatic public status update. This
workflow has no Instatus credentials in scope.

Scope is limited to verifying who answered the request, not what was
served; content verification against release tags is not covered here.
@DevelopmentCats
DevelopmentCats force-pushed the devcats/registry-integrity-canary branch from a0c8d1b to e2fa4b5 Compare September 2, 2026 13:18
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.

3 participants