Skip to content

feat: build using tarball#5882

Open
wayfarer3130 wants to merge 9 commits intomasterfrom
feat/build-using-tarball
Open

feat: build using tarball#5882
wayfarer3130 wants to merge 9 commits intomasterfrom
feat/build-using-tarball

Conversation

@wayfarer3130
Copy link
Contributor

@wayfarer3130 wayfarer3130 commented Mar 6, 2026

This PR changes the build scripts to allow pushing the results of a CS3D build into an OHIF build.

It currently links with:
cornerstonejs/cornerstone3D#2648
to demonstrate this capability, but will need to be pushed/created to finalize this work.

There is no functional change, with only a single logging change in StackViewport used to test the deploy preview.

See the README.md files for details in this and in the CS3D PR.

Context

Changes & Results

Testing

Checklist

PR

  • [] My Pull Request title is descriptive, accurate and follows the
    semantic-release format and guidelines.

Code

  • [] My code has been well-documented (function documentation, inline comments,
    etc.)

Public Documentation Updates

  • [] The documentation page has been updated as necessary for any public API
    additions or removals.

Tested Environment

  • [] OS:
  • [] Node version:
  • [] Browser:

Greptile Summary

This PR introduces an automated OHIF ↔ CS3D integration pipeline that consumes tarball release assets from CS3D GitHub releases and rewrites @cornerstonejs/* dependency references across the monorepo to point at those tarballs. It also adds local development tooling (worktree setup, lib linking, Netlify checkout) and a GitHub Actions workflow that creates/updates integration branches and PRs from incoming repository_dispatch events.

Key changes and concerns:

  • Integration workflow (.github/workflows/ohif-cs3d-integration.yml): The CS3D_TRUSTED_REPO environment variable passed to the security-verification step is sourced directly from github.event.client_payload.source_repository — the same untrusted value used to populate the dependency URLs. This makes the trust check circular and bypassable by anyone who can send a repository_dispatch event.
  • TSV parsing bug (.github/scripts/update-cs3d-deps-from-assets.mjs): The TSV asset-list input path has two problems: a dead-code ternary that always produces 0, and an inverted header-detection condition that either silently drops the first asset or adds the header row text as an asset name, causing all rewriting to be skipped in the --assets <tsv-file> usage path.
  • PR-scoped state committed to the branch (.github/cs3d-integration.json, libs/externals.json, all modified package.json files, and lockfiles): These files record integration state for CS3D PR feat: Add headers to prevent preflight requests #2648, pin all @cornerstonejs/* packages to non-published tarball URLs, and reference an in-progress feature branch in externals.json. The PR description notes this is intentional for demonstration purposes and must not be merged to master in its current form.
  • New developer scripts (scripts/worktree-cs3d.mjs, scripts/link-cornerstone-libs.mjs, etc.) are well-structured; link-cornerstone-libs.mjs covers only a hardcoded set of node_modules roots and may miss extension-level hoisted installs.

Confidence Score: 1/5

  • Not safe to merge to master: the branch carries PR-scoped integration state (tarball URLs and CS3D metadata) that would permanently pin master to a pre-release build, and the new workflow has a security bypass in its trust-verification step.
  • Two critical blockers: (1) merging would leave all @cornerstonejs/* deps pointing at tarballs from an unreleased CS3D PR instead of stable npm versions, breaking future upgrades and CI; (2) the CI_TRUSTED_REPO bypass allows any repository_dispatch sender to redirect all @cornerstonejs dependencies to an attacker-controlled repo. Additionally, a logic bug in the TSV parsing path of the update script would silently skip all asset rewrites when using file-based input.
  • .github/workflows/ohif-cs3d-integration.yml (security issue), .github/scripts/update-cs3d-deps-from-assets.mjs (logic bug), .github/cs3d-integration.json and libs/externals.json (should not be merged to master), all modified package.json and lockfiles (tarball URLs must be reverted to semver before merging).

Important Files Changed

Filename Overview
.github/workflows/ohif-cs3d-integration.yml New GitHub Actions workflow that automates CS3D dependency integration via repository_dispatch; contains a critical security issue where CS3D_TRUSTED_REPO is derived from the untrusted client_payload.source_repository field.
.github/scripts/update-cs3d-deps-from-assets.mjs Script that rewrites @cornerstonejs/* dependencies to tarball URLs; contains a dead-code ternary and a logic bug in TSV asset-list parsing that either drops the first asset or adds a header row value as an asset name.
.github/scripts/verify-cs3d-integration-diff.mjs Verification script checking that only allowed files changed and that @cornerstonejs URLs point to trusted repos; logic is sound but only as trusted as the CS3D_TRUSTED_REPO env value it receives.
.github/scripts/update-open-cs3d-integration-prs.mjs Small utility script that resolves the bot/cs3d-merged branch name and writes it to GITHUB_OUTPUT; logic is straightforward and correct.
scripts/install-cs3d-from-pr.mjs Developer convenience script to install CS3D tarballs from a specific PR; fetches up to 100 releases and picks the latest matching one, which works for typical PR counts but could miss releases on very active repos.
scripts/link-cornerstone-libs.mjs Creates symlinks in hardcoded node_modules roots (root, platform/app, platform/ui, platform/core); extensions with their own hoisted node_modules are not covered, which could cause version resolution issues.
scripts/worktree-cs3d.mjs Creates a git worktree of cornerstone3D and sets file: resolutions in the root package.json; straightforward implementation for local dev workflow.
scripts/checkout-libs-for-netlify.mjs Clones external repos for Netlify/CI builds using a shallow clone; log message says "exports empty" instead of "entries empty" (misleading wording), and no URL validation before passing to git clone.
scripts/build-libs.mjs Detects and builds the @cornerstonejs worktree if present, then links it into node_modules; clean and correctly guarded with directory existence check.
libs/externals.json New config file mapping the cornerstone3D external repo; currently hardcodes a feature branch ("feat/publish-tarballs") that will need to be updated or removed before merging to main.
.github/cs3d-integration.json Integration metadata snapshot from a specific CS3D PR (#2648) that should not be merged into master; this file is expected to be transient and should be reset or removed before merging.
scripts/install-libs.mjs Iterates externals and runs bun install + bun build in each lib directory; clean and straightforward, correctly skips missing libs.

Sequence Diagram

sequenceDiagram
    participant CS3D as CS3D Repo
    participant GHA as GitHub Actions<br/>(ohif-cs3d-integration.yml)
    participant Script1 as update-cs3d-deps-<br/>from-assets.mjs
    participant Script2 as verify-cs3d-<br/>integration-diff.mjs
    participant OHIF as OHIF Repo<br/>(bot/cs3d-pr-N branch)

    CS3D->>GHA: repository_dispatch<br/>{event: cs3d_integration_requested,<br/>payload: {release_tag, source_repository,<br/>cs3d_pr_number, mode}}
    GHA->>GHA: checkout default branch<br/>create/reuse bot/cs3d-pr-N
    GHA->>Script1: node update-cs3d-deps-from-assets.mjs<br/>--release-tag --repo (from payload)
    Script1->>CS3D: GET /releases/tags/{release_tag}<br/>(GitHub API, Bearer token)
    CS3D-->>Script1: Release asset list (tgz filenames)
    Script1->>Script1: Map asset names → @cornerstonejs/* packages<br/>Rewrite package.json deps to tarball URLs<br/>Write .github/cs3d-integration.json
    Script1-->>GHA: Updated package.json files
    GHA->>GHA: yarn install (regenerate lockfile)
    GHA->>Script2: node verify-cs3d-integration-diff.mjs<br/>CS3D_TRUSTED_REPO=payload.source_repository ⚠️
    Script2->>Script2: Check only allowed files changed<br/>Check @cornerstonejs URLs point to trusted repo
    Script2-->>GHA: Pass / Fail
    GHA->>OHIF: git commit + push bot/cs3d-pr-N
    GHA->>OHIF: gh pr create/update PR
Loading

Comments Outside Diff (3)

  1. .github/workflows/ohif-cs3d-integration.yml, line 612-613 (link)

    Circular trust: CS3D_TRUSTED_REPO sourced from the untrusted payload

    Both the dependency-update step and the verification step receive source_repository from github.event.client_payload. The update script writes tarball URLs using that repo, then the verify script trusts URLs from that same repo (CS3D_TRUSTED_REPO: ${{ github.event.client_payload.source_repository }}).

    A malicious actor who can send a repository_dispatch event to this repo (anyone with write access) could set source_repository: "attacker/evil-packages" and the workflow would:

    1. Rewrite all @cornerstonejs/* deps to point at https://github.com/attacker/evil-packages/releases/...
    2. Pass verification, because the verification trusts that exact same repo

    The fix is to hard-code the trusted repository or source it from a repository variable/secret, not from the payload:

          - name: Verify diff (allowed: package manifests, lockfile, metadata only in integration-only)
            env:
              CS3D_TRUSTED_REPO: cornerstonejs/cornerstone3D
            run: node .github/scripts/verify-cs3d-integration-diff.mjs --mode "${{ github.event.client_payload.mode || 'integration-only' }}"

    The same fix applies to the merged-update job (line ~700).

  2. .github/scripts/update-cs3d-deps-from-assets.mjs, line 219-224 (link)

    Inverted TSV header condition drops first asset or adds header text as asset name

    There are two bugs in the TSV-input parsing path:

    1. idx is always 0 – the ternary first.includes('\t') ? 0 : 0 evaluates to 0 in both branches; the condition has no effect.

    2. Inverted header guardlines.slice(1) already skips the first line (treating it as a header). The subsequent check tries to add lines[0] back if it doesn't start with cornerstonejs-. The logic is backwards:

      • When lines[0] IS a header (e.g. "name"): condition is true, so the header text "name" is pushed into names as an asset → no matching package is ever found, all assets are silently ignored.
      • When lines[0] IS the first asset (no header, e.g. "cornerstonejs-core-4.18.2.tgz"): condition is false, so that first asset is silently dropped.

    The condition should be inverted:

  3. scripts/install-cs3d-from-pr.mjs, line 1813-1828 (link)

    Pagination cap of 100 releases may miss the target release on active repos

    fetchLatestReleaseForPr fetches only ?per_page=100 releases without any pagination. On a busy repo, if more than 100 releases exist and the target PR's release is older than the 100 most recent ones, the script will silently report "No release found" even though the release exists.

    Consider adding a note in the error message, or implement pagination using a Link: <...>; rel="next" header approach if this is expected to be used on repos with many releases.

Last reviewed commit: 3e39ee5

Greptile also left 2 inline comments on this PR.

@wayfarer3130 wayfarer3130 requested review from jbocce and sedghi March 6, 2026 21:04
@netlify
Copy link

netlify bot commented Mar 6, 2026

Deploy Preview for ohif-dev canceled.

Name Link
🔨 Latest commit 1d1f56a
🔍 Latest deploy log https://app.netlify.com/projects/ohif-dev/deploys/69ab47ed5984630008e5aa7d

@cypress
Copy link

cypress bot commented Mar 6, 2026

Viewers    Run #6072

Run Properties:  status check passed Passed #6072  •  git commit 1d1f56a0c9: Add blocker to prevent merging when tarballs present
Project Viewers
Branch Review feat/build-using-tarball
Run status status check passed Passed #6072
Run duration 02m 18s
Commit git commit 1d1f56a0c9: Add blocker to prevent merging when tarballs present
Committer Bill Wallace
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 37
View all changes introduced in this branch ↗︎

Comment on lines +1 to +8
{
"cornerstonejs": {
"path": "@cornerstonejs",
"url": "https://github.com/cornerstonejs/cornerstone3D.git",
"branch": "feat/publish-tarballs",
"directory": "cornerstone3D"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feature branch hardcoded in externals.json shipped to master

libs/externals.json is committed with a specific, in-progress feature branch (feat/publish-tarballs) from the CS3D repo. This file is read by scripts/checkout-libs-for-netlify.mjs to clone the CS3D repo into libs/@cornerstonejs on every CI/Netlify build.

Once this PR is merged to master, every standard build of OHIF will clone that feature branch. If the branch is later deleted or rebased, all master builds will break with a git clone failure.

If externals.json is intended to be a transient per-integration-branch artifact (like cs3d-integration.json), it should either be reset to an empty object {} before merge, or checkout-libs-for-netlify.mjs should treat a missing/empty file as a no-op (which it already does) and the committed file should reflect that state.

Comment on lines +1 to +6
{
"mode": "integration-only",
"cs3dPr": 2648,
"releaseTag": "cs3d-pr-2648-d5bfc4c",
"cs3dRepo": "cornerstonejs/cornerstone3D"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration metadata for a specific CS3D PR is checked in to the base branch

This file records integration state for CS3D PR #2648 with a specific release tag (cs3d-pr-2648-d5bfc4c). Per the CS3D_INTEGRATION.md documentation, this file is written by the automation and is expected to be a per-integration-branch artifact.

If this file is merged to master, verify-cs3d-integration-diff.mjs will fail on the next automation run because the metadata will describe a stale integration. More critically, all the @cornerstonejs/* deps in package.json and the lockfiles still point to tarballs from that CS3D PR, meaning master would depend on a non-published pre-release build of cornerstone3D permanently.

This file (along with the tarball URL changes in all package.json files) should be reverted to the stable semver versions before merging to master.

Comment on lines +14 to +21
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Block merge if package.json has CS3D tarball refs
run: node .github/scripts/check-no-cs3d-tarball-deps.mjs

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 14 days ago

In general, the fix is to explicitly add a permissions block to the workflow or job so that the GITHUB_TOKEN has only the minimal required rights. For this job, it only needs to read repository contents to run the Node script on checked-out code, so contents: read is sufficient.

The best minimal change without altering existing behavior is to add a job-level permissions section under jobs.check (indented to align with runs-on), setting contents: read. actions/checkout works with read-only contents permissions for typical use cases, and no other steps require broader scopes. No imports or additional methods are needed; this is a pure YAML configuration change within .github/workflows/block-merge-cs3d-tarball-deps.yml.

Concretely: in .github/workflows/block-merge-cs3d-tarball-deps.yml, under jobs:, inside the check: job, insert:

permissions:
  contents: read

at the same indentation depth as runs-on, just before or after runs-on.

Suggested changeset 1
.github/workflows/block-merge-cs3d-tarball-deps.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/block-merge-cs3d-tarball-deps.yml b/.github/workflows/block-merge-cs3d-tarball-deps.yml
--- a/.github/workflows/block-merge-cs3d-tarball-deps.yml
+++ b/.github/workflows/block-merge-cs3d-tarball-deps.yml
@@ -12,6 +12,8 @@
 jobs:
   check:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-node@v4
EOF
@@ -12,6 +12,8 @@
jobs:
check:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Copilot is powered by AI and may make mistakes. Always verify output.
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