diff --git a/.github/workflows/cut-release.yml b/.github/workflows/cut-release.yml index 878cc9d33..5635de49e 100644 --- a/.github/workflows/cut-release.yml +++ b/.github/workflows/cut-release.yml @@ -127,18 +127,38 @@ jobs: with: ref: ${{ inputs.source_branch }} fetch-depth: 0 + # Defense in depth: don't leave a usable git credential on disk + # for any code that runs against the checked-out branch. + persist-credentials: false - name: Verify version files at source HEAD env: EXPECTED: ${{ steps.names.outputs.version }} run: | set -euo pipefail + # pyproject.toml is parsed with tomllib (safe — pure data, no code). PYPROJECT_VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])") if [ "$PYPROJECT_VERSION" != "$EXPECTED" ]; then echo "::error::pyproject.toml version is '$PYPROJECT_VERSION' but expected '$EXPECTED'." exit 1 fi - MODULE_VERSION=$(python3 -c "v={}; exec(open('comfyui_version.py').read(),v); print(v['__version__'])") + # comfyui_version.py contains Python — never `exec()` it. A + # malicious candidate branch could replace it with arbitrary code + # that would then run in CI with RELEASE_BOT_TOKEN in scope. + # Statically parse the AST to extract __version__ instead. + MODULE_VERSION=$(python3 - <<'PY' + import ast, pathlib, sys + tree = ast.parse(pathlib.Path("comfyui_version.py").read_text(encoding="utf-8")) + for node in tree.body: + if isinstance(node, ast.Assign): + for target in node.targets: + if isinstance(target, ast.Name) and target.id == "__version__": + if isinstance(node.value, ast.Constant) and isinstance(node.value.value, str): + print(node.value.value) + sys.exit(0) + sys.exit("Could not statically read __version__ from comfyui_version.py") + PY + ) if [ "$MODULE_VERSION" != "$EXPECTED" ]; then echo "::error::comfyui_version.py __version__ is '$MODULE_VERSION' but expected '$EXPECTED'." exit 1 @@ -225,12 +245,15 @@ jobs: env: REL_BRANCH: ${{ steps.names.outputs.release_branch }} TAG_NAME: ${{ steps.names.outputs.tag_name }} + JOB_STATUS: ${{ job.status }} run: | set -euo pipefail { echo "" echo "### Result" - if [ "$INPUT_DRY_RUN" = "true" ]; then + if [ "$JOB_STATUS" != "success" ]; then + echo "❌ Workflow did not complete successfully (job status: \`$JOB_STATUS\`). See the run logs for details. No branch or tag should be assumed to have been created." + elif [ "$INPUT_DRY_RUN" = "true" ]; then echo "🔍 **Dry run** — no branch or tag was created." else echo "✅ Created \`$REL_BRANCH\` and tagged \`$TAG_NAME\` from \`$INPUT_SOURCE_BRANCH\`."