Skip to content

fix: validate JSR token before publishing snapshots - #642

Open
jumski wants to merge 1 commit into
portable-worker-flows-templatefrom
portable-worker-jsr-auth
Open

fix: validate JSR token before publishing snapshots#642
jumski wants to merge 1 commit into
portable-worker-flows-templatefrom
portable-worker-jsr-auth

Conversation

@jumski

@jumski jumski commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Why

A snapshot run with a stale JSR_TOKEN gets past the script's auth pre-check
("✓ jsr: authenticated (via token)"), publishes the npm half successfully, and
then dies on the JSR half:

error: Failed to publish @pgflow/edge-worker@...
Caused by:
    1: The provided bearer token is invalid. (invalidBearerToken)

Root cause of the false positive: the pre-check ran
deno publish --dry-run, which never contacts the registry. Verified
locally — with a garbage token:

$ pnpm jsr publish --dry-run --allow-slow-types --allow-dirty --token jsrp_fakefakefake
Success Dry run complete
exit=0

The result is a half-published snapshot (npm version exists, JSR version
doesn't) and a worktree stuck on the versioned files.

Bonus leak: on publish failure the jsr npm wrapper console.logs the full
deno command line (dist/utils.js:272), including --token jsrp_…, so the
token ends up in terminal output, CI logs, and bug reports.

Second dead path: the no-token fallback ran deno login, a subcommand that
does not exist in deno 2.1.4 (nor in the jsr wrapper's bundled 2.3.7) — it
crashes with error: Module not found "…/login". And since dry-run never
reports auth problems, the fallback triggered "✓ authenticated (existing
session)" even with no session cached at all.

What

  • When JSR_TOKEN is set: validate it up front with a real API call
    (GET https://api.jsr.io/user, expects 200) and exit 1 with a clear
    "rotate the token" message before any versioning/build/publishing happens
  • No-token path: require the cached browser-session file
    ($DENO_DIR/auth.json, default ~/.cache/deno/auth.json) to exist. If
    missing, exit 1 with the one-time warm-up command
    (cd pkgs/edge-worker && pnpm jsr publish … — fails with "already
    published", but persists the login) instead of calling the nonexistent
    deno login
  • Redact jsrp_… tokens from the JSR publish output (stdout and stderr)

Verification

  • bash -n scripts/snapshot-release.sh
  • extracted auth block, run standalone:
    • JSR_TOKEN=jsrp_fake…Error: JSR_TOKEN is invalid or expired (api.jsr.io: 401) + exit 1
    • no token, no ~/.cache/deno/auth.json → guided error + exit 1
    • no token, auth.json present → ✓ jsr: using cached browser session + exit 0
  • redaction on the real leaked line from the failing run:
    --token jsrp_dI7…--token jsrp_[REDACTED]

@changeset-bot

changeset-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 4d0d87a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@nx-cloud

nx-cloud Bot commented Aug 20, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 4d0d87a

Command Status Duration Result
nx test:types:health dsl ✅ Succeeded 8s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-21 13:52:11 UTC

Comment on lines +368 to +370
if ( cd pkgs/edge-worker && $JSR_PUBLISH_CMD ) \
> >(sed -E 's/jsrp_[A-Za-z0-9]+/jsrp_[REDACTED]/g') \
2> >(sed -E 's/jsrp_[A-Za-z0-9]+/jsrp_[REDACTED]/g' >&2) ; then

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.

Process substitution race condition causing incomplete output

The process substitutions > >(sed...) and 2> >(sed...) spawn background processes. The if statement evaluates the exit code of the subshell immediately, but bash does not automatically wait for these background sed processes to complete. This creates a race condition where:

  1. The script continues execution before output is fully redacted/written
  2. Output may be truncated or appear out of order
  3. The script could exit before redaction completes, losing output entirely

Fix: Store output to variables first, then redact:

OUTPUT=$(cd pkgs/edge-worker && $JSR_PUBLISH_CMD 2>&1)
EXIT_CODE=$?
echo "$OUTPUT" | sed -E 's/jsrp_[A-Za-z0-9]+/jsrp_[REDACTED]/g'
if [[ $EXIT_CODE -eq 0 ]]; then

Or use a temporary file to capture output, then cat it through sed synchronously.

Suggested change
if ( cd pkgs/edge-worker && $JSR_PUBLISH_CMD ) \
> >(sed -E 's/jsrp_[A-Za-z0-9]+/jsrp_[REDACTED]/g') \
2> >(sed -E 's/jsrp_[A-Za-z0-9]+/jsrp_[REDACTED]/g' >&2) ; then
OUTPUT=$(cd pkgs/edge-worker && $JSR_PUBLISH_CMD 2>&1)
EXIT_CODE=$?
echo "$OUTPUT" | sed -E 's/jsrp_[A-Za-z0-9]+/jsrp_[REDACTED]/g'
if [[ $EXIT_CODE -eq 0 ]]; then

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@jumski
jumski force-pushed the portable-worker-jsr-auth branch from febc643 to 4d0d87a Compare August 21, 2026 13:27
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Preview Deployment: Website

Deployment successful!

🔗 Preview URL: https://pr-642.pgflow.pages.dev

📝 Details:

  • Branch: portable-worker-jsr-auth
  • Commit: 473cbbd1604ae26d8c21ffde532bd44b6c79a2fe
  • View Logs

_Last updated: _

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