Skip to content

fix(publish-runtime): use PyPI Trusted Publisher (OIDC) instead of PYPI_TOKEN - #2113

Merged
HongmingWang-Rabbit merged 1 commit into
stagingfrom
fix/publish-runtime-oidc
Apr 26, 2026
Merged

fix(publish-runtime): use PyPI Trusted Publisher (OIDC) instead of PYPI_TOKEN#2113
HongmingWang-Rabbit merged 1 commit into
stagingfrom
fix/publish-runtime-oidc

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

  • Migrates publish-runtime.yml from twine + PYPI_TOKEN to PyPI Trusted Publisher (OIDC)
  • Adds id-token: write permission on the publish job (least-privilege; cascade job unchanged)
  • Updates the workflow's header comment to reflect the new auth model

Why

A leaked PYPI_TOKEN would let any holder publish arbitrary versions of molecule-ai-workspace-runtime to PyPI from anywhere — bypassing the monorepo's review and CI gates entirely. The 8 workspace template repos pull this package, so a malicious publish poisons all of them.

Trusted Publisher (OIDC) eliminates that exfil path: no long-lived credential exists to leak. Only this exact workflow, on this repo, in the pypi-publish environment, can upload.

This is the belt-and-suspenders companion to the sibling-repo lockdown PR (PR #56 in molecule-ai-workspace-runtime) — without OIDC, the sibling lockdown alone doesn't prevent a local `python -m build && twine upload` from a laptop with a personal PyPI maintainer credential.

PyPI side (already done)

Trusted Publisher is configured at https://pypi.org/manage/project/molecule-ai-workspace-runtime/settings/publishing/ pointing at:

  • Repository: Molecule-AI/molecule-core
  • Workflow: publish-runtime.yml
  • Environment: pypi-publish

After this merges

  1. Run a workflow_dispatch of publish-runtime with a dev version (e.g. `0.1.6.dev1`) to confirm OIDC end-to-end
  2. Once a real publish succeeds, delete the `PYPI_TOKEN` repo secret (it becomes dead weight + a leak surface with no purpose)
  3. Audit PyPI maintainers for the package and prune to the minimum (ideally zero human accounts; OIDC handles all publishes)

Test plan

  • CI green
  • Manual workflow_dispatch with version: 0.1.6.dev1 (or similar) succeeds and the version appears on PyPI
  • Confirm PYPI_TOKEN secret is no longer referenced anywhere in the repo (`gh secret list` + `grep -r PYPI_TOKEN .github/`)

Notes

🤖 Generated with Claude Code

HongmingWang-Rabbit pushed a commit that referenced this pull request Apr 26, 2026
Reflects PR #2113 (PyPI Trusted Publisher / OIDC migration). No static
PyPI token exists in the repo anymore, so the docs shouldn't claim one
does. Replaces the PYPI_TOKEN row in the Required Secrets table with an
"Auth" section pointing at the OIDC config; TEMPLATE_DISPATCH_TOKEN is
still the only repo secret the cascade needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…PI_TOKEN

Drops the static PYPI_TOKEN secret in favor of OIDC trusted publishing.
PyPI now mints a short-lived upload credential after verifying the
workflow's OIDC claim against the trusted-publisher config registered
for molecule-ai-workspace-runtime (Molecule-AI/molecule-core,
publish-runtime.yml, environment pypi-publish).

Why:
- A leaked PYPI_TOKEN would let any holder publish arbitrary versions of
  molecule-ai-workspace-runtime to PyPI from anywhere — bypassing the
  monorepo's review and CI gates entirely. The 8 template repos pull
  this package; a malicious publish poisons all of them.
- Trusted Publisher (OIDC) makes that exfil path moot: no long-lived
  credential exists to leak. Only this exact workflow, on this repo,
  in the pypi-publish environment, can upload.

After this lands and the first OIDC publish succeeds, the PYPI_TOKEN
repo secret should be deleted (it becomes dead weight + a leak surface
with no purpose).

Belt-and-suspenders companion to PR #56 in molecule-ai-workspace-runtime
(sibling repo lockdown). Without OIDC, the sibling lockdown alone
doesn't prevent local `python -m build && twine upload` from a laptop
with a personal PyPI maintainer credential.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HongmingWang-Rabbit
HongmingWang-Rabbit merged commit f3a2043 into staging Apr 26, 2026
14 checks passed
HongmingWang-Rabbit pushed a commit that referenced this pull request Apr 26, 2026
Reflects PR #2113 (PyPI Trusted Publisher / OIDC migration). No static
PyPI token exists in the repo anymore, so the docs shouldn't claim one
does. Replaces the PYPI_TOKEN row in the Required Secrets table with an
"Auth" section pointing at the OIDC config; TEMPLATE_DISPATCH_TOKEN is
still the only repo secret the cascade needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HongmingWang-Rabbit added a commit that referenced this pull request Apr 26, 2026
)

* docs: point new-runtime-template flow at the GitHub template repo

The 'Writing a new adapter' section was a 6-step manual checklist that
re-derived the canonical shape every time. Now that
Molecule-AI/molecule-ai-workspace-template-starter exists as a GitHub
template, the flow collapses to:

  gh repo create ... --template Molecule-AI/molecule-ai-workspace-template-starter

Plus a fill-in-the-TODO-markers table.

Why this matters: the starter ships with the
'repository_dispatch: [runtime-published]' cascade receiver pre-wired,
which means new templates pick up runtime PyPI publishes automatically
without the one-time setup PR each existing template needed (PRs #6-#22
across the 8 template repos that we just opened to retrofit). At
'hundreds of runtimes' scale this is the difference between linear PR-
toil and zero PR-toil per template addition.

Also adds: 'When the starter itself needs to evolve' — explicit pattern
for keeping the canonical shape in one place when it changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* docs(workspace-runtime): drop PYPI_TOKEN refs — OIDC is the new auth

Reflects PR #2113 (PyPI Trusted Publisher / OIDC migration). No static
PyPI token exists in the repo anymore, so the docs shouldn't claim one
does. Replaces the PYPI_TOKEN row in the Required Secrets table with an
"Auth" section pointing at the OIDC config; TEMPLATE_DISPATCH_TOKEN is
still the only repo secret the cascade needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Hongming Wang <hongmingwangalt@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@molecule-ai
molecule-ai Bot deleted the fix/publish-runtime-oidc branch May 20, 2026 06:22
HongmingWang-Rabbit pushed a commit that referenced this pull request Jun 12, 2026
These 5 workflows have been stable since the 2026-05-11 Gitea port:
- block-internal-paths
- check-migration-collisions
- lint-bp-context-emit-match
- lint-curl-status-capture
- lint-required-context-exists-in-bp

All are well past the 7-clean-run/7-clean-day Phase 3 threshold.
Phase 4 flip per RFC internal#219 §1.

Fixes #2113 (partial — remaining ~27 masks still in flight).
HongmingWang-Rabbit pushed a commit that referenced this pull request Jun 12, 2026
…alse (#2113)' (#2126) from fix/continue-on-error-triage-2113 into main
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