Skip to content

OG_IMAGE_SECRET is a dual source of truth (build vs runtime) — make it single-source #103

Description

@hasparus

Problem

The OG image HMAC token has the secret in two places that must be kept in sync manually:

  • Build / signingsrc/lib/createOgImageLink.tsx reads OG_IMAGE_SECRET from astro:env/server, i.e. process.env at build time. In CI that's the GitHub Actions repo secret (passed via the workflow env:).
  • Runtime / verifyingapi/og.ts reads process.env.OG_IMAGE_SECRET, injected by Vercel from the project's env vars.

If the GitHub secret and the Vercel project env var differ (or the Vercel one was never set), every OG image returns 401 invalid-token. A missing Vercel var gives 500 ("missing"); a mismatched one gives 401. This is easy to get wrong on first setup ("set it in GitHub, forget to set it on Vercel") and on rotation (change one, forget the other). It bit a downstream fork.

Proposal

Make Vercel the single source of truth so build and runtime can't diverge:

  1. Set OG_IMAGE_SECRET once, on the Vercel project (Production/Preview), non-sensitive so the build can read it.
  2. Drop the OG_IMAGE_SECRET env: override on the deploy steps in ci.yml, so vercel build provides the value to the astro build from the pulled project env (vercel pull already runs first in deploy.mjs).
  3. Remove OG_IMAGE_SECRET from the required GitHub Actions secrets (keep placeholder for the non-deployed test build + astro sync).

Net: one value, set in one place, used for both signing and verifying.

Open question / risk

Need to verify that vercel build actually exposes the pulled .vercel/.env.<target>.local value to the astro build subprocess so astro:env/server (a required secret field) resolves it. If it doesn't, removing the GH override would fail the build (required env missing). Test on a preview deploy before adopting.

Alternative (smaller)

Keep the two-source setup but document it loudly (README already lists only the GH secret — add the Vercel-side requirement) and/or add a CI check that fails if the two don't match. Less robust than single-source.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions