molecule-ci/.github/workflows
Hongming Wang d420b4a24f ci: lock down validate-workspace-template against fork-PR untrusted code (P135)
Splits the reusable validator into two jobs to keep external fork
PRs from running arbitrary template code on the runner.

Background

The reusable workflow runs three primitives that execute
template-supplied code:
  - pip install -r requirements.txt  (setup.py + post-install hooks)
  - importlib.exec_module(adapter)   (top-level Python in adapter.py)
  - docker build                     (RUN steps in Dockerfile)

Token scope is already minimal (contents: read), GitHub forced
fork-PR tokens read-only in 2021, and the workflow_call interface
doesn't accept secrets. So the actual exploit surface is "what can
a malicious actor do with arbitrary code execution on a GitHub-
hosted runner that has no useful credentials?" — answer: crypto-
mine, DNS-exfiltrate runner metadata, attempt lateral movement
within the runner's network. Annoying, not catastrophic, but a
real attack surface that this PR closes.

The fix

Two-job split:

  validate-static    Always runs, including external fork PRs.
                     File-content checks (secret scan, YAML parse,
                     AST inspection of adapter.py without import),
                     pip install only the validator's pyyaml dep
                     (not the template's requirements.txt). NO
                     third-party code execution.

  validate-runtime   Skipped when github.event.pull_request.head.
                     repo.fork == true. pip install requirements.txt
                     + adapter import + docker build. Internal PRs
                     and push events to internal branches still get
                     the full coverage.

The validator script gains a --static-only flag that skips
check_adapter_runtime_load() (the function that calls
exec_module). The validate-static job uses it; validate-runtime
uses the existing full mode.

Trade-off

External contributors get static feedback only on their PR. If
their template metadata passes static checks but breaks runtime
loading, branch protection on staging/main blocks the merge once
runtime validation runs (post-merge or after an internal
contributor reposts). Fewer false-positive CI failures for honest
external contributors; same coverage at the merge-protected
boundary.

What this does NOT close

- Maintainer-approved external PRs that consciously execute
  third-party code. The maintainer must approve a workflow run
  via GitHub's first-time-contributor gate; that's a human
  decision, not a workflow-level gate.
- requirements.txt that pulls a malicious transitive dep from
  PyPI even on internal PRs. Mitigated by branch-protection +
  human review of PRs that touch requirements.txt.

Closes task #135.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 01:07:58 -07:00
..
auto-promote-branch.yml docs: recommend @v1 over @main in reusable-workflow adoption snippets (#16) 2026-04-28 11:14:12 -07:00
auto-promote-staging-pr.yml docs: pin reusable-workflow examples from @main to @v1 (P133) 2026-04-30 01:04:06 -07:00
auto-promote-staging.yml docs: recommend @v1 over @main in reusable-workflow adoption snippets (#16) 2026-04-28 11:14:12 -07:00
disable-auto-merge-on-push.yml docs: recommend @v1 over @main in reusable-workflow adoption snippets (#16) 2026-04-28 11:14:12 -07:00
publish-template-image.yml docs: recommend @v1 over @main in reusable-workflow adoption snippets (#16) 2026-04-28 11:14:12 -07:00
validate-org-template.yml fix(validate): fetch validator scripts from molecule-ci instead of expecting them in caller 2026-04-29 01:56:25 -07:00
validate-plugin.yml fix(validate): fetch validator scripts from molecule-ci instead of expecting them in caller 2026-04-29 01:56:25 -07:00
validate-workspace-template.yml ci: lock down validate-workspace-template against fork-PR untrusted code (P135) 2026-04-30 01:07:58 -07:00