mirror of
https://github.com/unslothai/unsloth.git
synced 2026-10-19 08:54:21 +00:00
Harden npm and yarn installs against supply-chain attacks (#12660)
* Harden npm and yarn installs against supply-chain attacks - studio/frontend/.npmrc: allow-git=none. Git dependencies bypass the registry, the 7-day release-age gate and the integrity pin, and run prepare scripts on install. The lockfile has none. - oxc-validator/.npmrc (new): the installers run npm ci here on user machines, so mirror the frontend protections (min-release-age=7, registry pin, save-exact, allow-git=none). npm ci still installs the locked versions; UNSLOTH_NPM_REGISTRY keeps working via --registry. - Docker JupyterLab extension: commit yarn.lock (generated with the jlpm bundled in jupyterlab 4.6.0), install with jlpm install --immutable, set enableScripts: false, and include yarn.lock in the docker build context. Image builds no longer resolve caret ranges fresh or run dependency install scripts. * oxc-validator .npmrc: do not pin the registry A project registry= pin overrides a corporate mirror set in the user's ~/.npmrc, and this npm ci runs on every Studio install and update, so users behind a blocked npmjs.org would fail setup. Integrity hashes in the lockfile already reject tampered tarballs from any registry. * npm: harden the Tauri CLI install; run CI when an .npmrc changes studio/.npmrc applies the same settings as the frontend (7-day release age, exact saves, no git dependencies) plus ignore-scripts, to the npm ci --prefix studio the Desktop release runs to fetch the Tauri CLI. No locked package there has install scripts. No registry pin, as for the OXC validator. The workflows that already trigger on the OXC validator lockfile and the studio/ Tauri lockfile now also trigger on the .npmrc next to them. * Desktop clean-machine CI: also run on studio/.npmrc changes
This commit is contained in:
parent
5971d280d4
commit
4d16e94d5b
14 changed files with 4170 additions and 3 deletions
|
|
@ -89,6 +89,7 @@ on:
|
|||
- 'studio/frontend/.npmrc'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/.npmrc'
|
||||
- 'studio/nvidia_probe.py'
|
||||
- 'studio/backend/__init__.py'
|
||||
- 'studio/backend/utils/__init__.py'
|
||||
|
|
@ -133,6 +134,7 @@ on:
|
|||
- 'studio/frontend/.npmrc'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/.npmrc'
|
||||
- 'studio/nvidia_probe.py'
|
||||
- 'studio/backend/__init__.py'
|
||||
- 'studio/backend/utils/__init__.py'
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ on:
|
|||
- 'studio/package-lock.json'
|
||||
- 'studio/frontend/package.json'
|
||||
- 'studio/frontend/package-lock.json'
|
||||
- 'studio/.npmrc'
|
||||
- 'studio/frontend/.npmrc'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/.npmrc'
|
||||
- 'studio/src-tauri/Cargo.toml'
|
||||
- 'studio/src-tauri/Cargo.lock'
|
||||
- 'studio/src-tauri/build.rs'
|
||||
|
|
|
|||
1
.github/workflows/security-audit.yml
vendored
1
.github/workflows/security-audit.yml
vendored
|
|
@ -83,6 +83,7 @@ on:
|
|||
- 'scripts/lockfile_supply_chain_audit.py'
|
||||
- 'studio/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/.npmrc'
|
||||
- 'scripts/scan_npm_packages.py'
|
||||
- 'scripts/scan_npm_packages_baseline.json'
|
||||
- 'scripts/check_new_install_scripts.py'
|
||||
|
|
|
|||
2
.github/workflows/studio-tauri-smoke.yml
vendored
2
.github/workflows/studio-tauri-smoke.yml
vendored
|
|
@ -31,6 +31,7 @@ on:
|
|||
# manifests decide what it builds with.
|
||||
- 'studio/package.json'
|
||||
- 'studio/package-lock.json'
|
||||
- 'studio/.npmrc'
|
||||
# Run as a step of the Linux job.
|
||||
- 'scripts/lockfile_supply_chain_audit.py'
|
||||
# The Rust unit test every_shared_case_agrees_with_the_desktop_filter
|
||||
|
|
@ -59,6 +60,7 @@ on:
|
|||
# manifests decide what it builds with.
|
||||
- 'studio/package.json'
|
||||
- 'studio/package-lock.json'
|
||||
- 'studio/.npmrc'
|
||||
# Run as a step of the Linux job.
|
||||
- 'scripts/lockfile_supply_chain_audit.py'
|
||||
# The Rust unit test every_shared_case_agrees_with_the_desktop_filter
|
||||
|
|
|
|||
2
.github/workflows/studio-update-smoke.yml
vendored
2
.github/workflows/studio-update-smoke.yml
vendored
|
|
@ -40,6 +40,7 @@ on:
|
|||
- 'studio/frontend/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/.npmrc'
|
||||
# The harness below and the proxy it measures with.
|
||||
- 'tests/studio/install/test_update_idempotency.py'
|
||||
- 'tests/studio/install/idempotency_proxy.py'
|
||||
|
|
@ -113,6 +114,7 @@ on:
|
|||
- 'studio/frontend/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/package-lock.json'
|
||||
- 'studio/backend/core/data_recipe/oxc-validator/.npmrc'
|
||||
# The harness below and the proxy it measures with.
|
||||
- 'tests/studio/install/test_update_idempotency.py'
|
||||
- 'tests/studio/install/idempotency_proxy.py'
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
!jupyter/unsloth_labext/package.json
|
||||
!jupyter/unsloth_labext/tsconfig.json
|
||||
!jupyter/unsloth_labext/.yarnrc.yml
|
||||
!jupyter/unsloth_labext/yarn.lock
|
||||
!jupyter/unsloth_labext/src
|
||||
!jupyter/unsloth_labext/src/**
|
||||
!jupyter/unsloth_labext/style
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ RUN apt-get update \
|
|||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY jupyter/unsloth_labext /opt/labext-src
|
||||
RUN cd /opt/labext-src \
|
||||
&& /opt/unsloth-venv/bin/jlpm install \
|
||||
&& /opt/unsloth-venv/bin/jlpm install --immutable \
|
||||
&& /opt/unsloth-venv/bin/jlpm build:prod
|
||||
|
||||
FROM ${BASE_IMAGE}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ RUN apt-get update \
|
|||
RUN /opt/unsloth-venv/bin/uv pip install --python /opt/unsloth-venv/bin/python "jupyterlab==4.6.0"
|
||||
COPY jupyter/unsloth_labext /opt/labext-src
|
||||
RUN cd /opt/labext-src \
|
||||
&& /opt/unsloth-venv/bin/jlpm install \
|
||||
&& /opt/unsloth-venv/bin/jlpm install --immutable \
|
||||
&& /opt/unsloth-venv/bin/jlpm build:prod
|
||||
|
||||
FROM ${BASE_IMAGE}
|
||||
|
|
|
|||
1
docker/jupyter/unsloth_labext/.gitignore
vendored
1
docker/jupyter/unsloth_labext/.gitignore
vendored
|
|
@ -4,4 +4,3 @@ lib/
|
|||
unsloth-jupyterlab/
|
||||
.yarn/
|
||||
.pnp.*
|
||||
yarn.lock
|
||||
|
|
|
|||
|
|
@ -1 +1,5 @@
|
|||
nodeLinker: node-modules
|
||||
# Dependencies never run install scripts here: the build only needs tsc and
|
||||
# jupyter-builder, and yarn.lock is committed so the image build installs with
|
||||
# `jlpm install --immutable` (no fresh resolution of caret ranges).
|
||||
enableScripts: false
|
||||
|
|
|
|||
4117
docker/jupyter/unsloth_labext/yarn.lock
Normal file
4117
docker/jupyter/unsloth_labext/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
14
studio/.npmrc
Normal file
14
studio/.npmrc
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Unsloth Desktop release npm configuration. `npm ci --prefix studio` in
|
||||
# release-desktop.yml installs the pinned Tauri CLI from package-lock.json here,
|
||||
# and that CLI builds the app every Desktop user installs.
|
||||
#
|
||||
# Refuse tarballs published less than 7 days ago (npm >=11.10; bare integer
|
||||
# means DAYS). `npm ci` still installs the locked versions.
|
||||
min-release-age=7
|
||||
save-exact=true
|
||||
# No git/GitHub dependencies (they bypass the registry, the cooldown and the
|
||||
# integrity pin). No locked package has install scripts.
|
||||
allow-git=none
|
||||
ignore-scripts=true
|
||||
audit-level=high
|
||||
fund=false
|
||||
18
studio/backend/core/data_recipe/oxc-validator/.npmrc
Normal file
18
studio/backend/core/data_recipe/oxc-validator/.npmrc
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Unsloth OXC validator npm configuration. Same supply-chain defences as
|
||||
# studio/frontend/.npmrc; the installers run `npm ci` here on user machines.
|
||||
#
|
||||
# Refuse tarballs published less than 7 days ago (npm >=11.10; bare integer
|
||||
# means DAYS). `npm ci` still installs the locked versions, so this only
|
||||
# gates new resolutions.
|
||||
min-release-age=7
|
||||
# Keep exact pins when a maintainer runs `npm install <pkg>` here.
|
||||
save-exact=true
|
||||
# No registry= pin here: this install runs on every Studio setup and update,
|
||||
# and a project pin would override a corporate mirror in the user's ~/.npmrc.
|
||||
# Every lock entry carries an integrity hash, so `npm ci` rejects tampered
|
||||
# tarballs whichever registry serves them.
|
||||
# No git/GitHub dependencies: they bypass the registry, the cooldown and the
|
||||
# integrity pin, and run `prepare` on install. The lockfile has none.
|
||||
allow-git=none
|
||||
audit-level=high
|
||||
fund=false
|
||||
|
|
@ -14,6 +14,11 @@ min-release-age=7
|
|||
# `npm install <name>@<version> --save-exact` pass) but it stops new
|
||||
# carets from creeping into the manifest as patch-version footguns.
|
||||
save-exact=true
|
||||
# Refuse git/GitHub dependencies outright. A git dep is fetched outside the
|
||||
# registry (no min-release-age, no integrity pin) and runs its `prepare`
|
||||
# script during install. The lockfile has none; this keeps a tampered lock
|
||||
# or a hand-added `github:` spec from slipping one in. npm >=11.10.
|
||||
allow-git=none
|
||||
# Pin the default registry so a stale or hostile *lower-precedence* ~/.npmrc
|
||||
# can't silently redirect our installs to an attacker registry. Note this does
|
||||
# NOT block an ambient NPM_CONFIG_REGISTRY env var: npm and bun honor that at a
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue