ci: extend lockfile-strict surface to Tauri smoke + audit jobs
Brings the parallel CI paths into line with the lockfile-pinned
release path and tightens the supply-chain audit surface:
studio-tauri-smoke.yml: run lockfile_supply_chain_audit.py before
the Tauri CLI install, and install via `npm ci --prefix studio`
against the committed studio/package-lock.json (was a mutable
`npm install --save-dev` post-audit). This relocates the existing
pre-install lockfile supply-chain audit step; the step's name and
command are preserved verbatim so its purpose is unchanged, only
its position relative to the install. The earlier security
rationale about lifecycle scripts and the postinstall-dropper
class is preserved on the Frontend build step where it actually
applies (vite/esbuild lifecycle scripts run on the frontend
install); the Tauri CLI install step gets a new rationale tied to
`npm ci` semantics.
security-audit.yml:
* add studio/package.json and studio/package-lock.json to the PR
path filter so a Tauri CLI lockfile change cannot bypass the
workflow,
* extend OSV-Scanner, scan_npm_packages.py (with LOG3 and exit-
code propagation), and the install-script diff to cover
studio/package-lock.json,
* add an npm audit step for the Tauri CLI holder project,
* extend the npm-provenance-and-install-scripts job with
--ignore-scripts installs + npm audit signatures for the
oxc-validator and Tauri CLI holder projects; the existing
frontend audit-signatures step is renamed to "(Studio
frontend, informational)" purely for disambiguation against
the two new sibling steps, with its log path rerouted through
$GITHUB_WORKSPACE so a single artifact upload can collect all
three logs,
* update the lockfile-audit step summary to list the Tauri CLI
holder lockfile,
* fix the stale "Initially non-blocking" comment on the now-
blocking npm scan-packages step.
build.sh and studio/setup.ps1 (oxc): pass --no-fund --no-audit to
npm ci for parity with the other call sites.
studio/setup.sh and studio/setup.ps1: restore the bun.lock
exclusion in the frontend staleness check so a leftover local
bun.lock from the migration does not trigger a spurious rebuild.
scripts/lockfile_supply_chain_audit.py: emit a HIGH-severity
missing-lockfile Finding when a requested lockfile does not
exist, so a deleted default cannot silently pass the audit. Uses
the script's own Finding accumulator pattern (sibling
scripts/scan_npm_packages.py implements the same intent via an
rc=2 hard-fail, its single-lockfile-per-invocation idiom; this
script aggregates multiple lockfiles so Finding is the natural
channel).
scripts/check_frontend_dep_removal.py: add studio/package.json
and studio/package-lock.json to EXPECTED_NOISE_FILES; the new
Tauri CLI holder manifests must not count as frontend dep usage.
This commit is contained in:
parent
d43b0e3029
commit
b743e1b4ff
7 changed files with 147 additions and 30 deletions
109
.github/workflows/security-audit.yml
vendored
109
.github/workflows/security-audit.yml
vendored
|
|
@ -55,6 +55,8 @@ 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/package.json'
|
||||
- 'studio/package-lock.json'
|
||||
- 'studio/src-tauri/Cargo.toml'
|
||||
- 'studio/src-tauri/Cargo.lock'
|
||||
- 'pyproject.toml'
|
||||
|
|
@ -280,7 +282,7 @@ jobs:
|
|||
{
|
||||
echo "## Lockfile supply-chain audit"
|
||||
echo
|
||||
echo "Scanned: studio/frontend/package-lock.json + studio/backend/core/data_recipe/oxc-validator/package-lock.json + studio/src-tauri/Cargo.lock"
|
||||
echo "Scanned: studio/frontend/package-lock.json + studio/backend/core/data_recipe/oxc-validator/package-lock.json + studio/package-lock.json + studio/src-tauri/Cargo.lock"
|
||||
echo
|
||||
echo "No structural anomalies or known IOC strings."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
|
@ -325,6 +327,23 @@ jobs:
|
|||
echo '```'
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: npm audit (Studio Tauri CLI holder)
|
||||
# Same audit surface, third npm project (@tauri-apps/cli for the
|
||||
# signed desktop release; lockfile lives at studio/package-lock.json).
|
||||
continue-on-error: true
|
||||
working-directory: studio
|
||||
run: |
|
||||
set +e
|
||||
npm audit --audit-level=high | tee "$GITHUB_WORKSPACE/logs-npm-audit-studio.txt"
|
||||
npm audit --json > "$GITHUB_WORKSPACE/logs-npm-audit-studio.json" || true
|
||||
{
|
||||
echo "## npm audit (Studio Tauri CLI holder)"
|
||||
echo
|
||||
echo '```'
|
||||
tail -200 "$GITHUB_WORKSPACE/logs-npm-audit-studio.txt"
|
||||
echo '```'
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# cargo: Studio Tauri shell
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
|
|
@ -367,6 +386,7 @@ jobs:
|
|||
/tmp/osv-scanner scan source \
|
||||
--lockfile=studio/frontend/package-lock.json \
|
||||
--lockfile=studio/backend/core/data_recipe/oxc-validator/package-lock.json \
|
||||
--lockfile=studio/package-lock.json \
|
||||
--lockfile=studio/src-tauri/Cargo.lock \
|
||||
--lockfile=requirements.txt:audit-reqs/unsloth-deps.txt \
|
||||
--lockfile=requirements.txt:audit-reqs/studio.txt \
|
||||
|
|
@ -930,16 +950,15 @@ jobs:
|
|||
# full log and surface it in the step summary either way. It
|
||||
# never runs `npm install`, never executes anything from a
|
||||
# downloaded tarball, and only fetches from registry.npmjs.org.
|
||||
# Initially non-blocking so the baseline can settle; drop
|
||||
# continue-on-error once the baseline is clean for a week.
|
||||
# This step is blocking: the final exit code is the worst rc
|
||||
# across all three npm projects (no continue-on-error).
|
||||
#
|
||||
# Two separate npm projects share this scan surface; scan each.
|
||||
# Capture exit codes via PIPESTATUS so a HIGH/CRITICAL on the
|
||||
# frontend lockfile does not skip the OXC scan (both reports
|
||||
# are most useful exactly when one already failed).
|
||||
# Three separate npm projects share this scan surface; scan each.
|
||||
# Capture exit codes via PIPESTATUS so a HIGH/CRITICAL on one
|
||||
# lockfile does not skip the next scan (all reports are most
|
||||
# useful exactly when one already failed).
|
||||
run: |
|
||||
set +e
|
||||
set -o pipefail
|
||||
|
||||
LOG=logs-scan-npm.txt
|
||||
python3 scripts/scan_npm_packages.py 2>&1 | tee "$LOG"
|
||||
|
|
@ -951,6 +970,12 @@ jobs:
|
|||
2>&1 | tee "$LOG2"
|
||||
oxc_rc=${PIPESTATUS[0]}
|
||||
|
||||
LOG3=logs-scan-npm-studio.txt
|
||||
python3 scripts/scan_npm_packages.py \
|
||||
--lockfile studio/package-lock.json \
|
||||
2>&1 | tee "$LOG3"
|
||||
studio_rc=${PIPESTATUS[0]}
|
||||
|
||||
{
|
||||
echo "## scan_npm_packages (Studio frontend)"
|
||||
echo
|
||||
|
|
@ -965,12 +990,22 @@ jobs:
|
|||
echo '```'
|
||||
tail -300 "$LOG2"
|
||||
echo '```'
|
||||
echo
|
||||
echo "## scan_npm_packages (Studio Tauri CLI holder)"
|
||||
echo
|
||||
echo '### Findings (tail)'
|
||||
echo '```'
|
||||
tail -300 "$LOG3"
|
||||
echo '```'
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
if [ "$frontend_rc" -ne 0 ]; then
|
||||
exit "$frontend_rc"
|
||||
fi
|
||||
exit "$oxc_rc"
|
||||
if [ "$oxc_rc" -ne 0 ]; then
|
||||
exit "$oxc_rc"
|
||||
fi
|
||||
exit "$studio_rc"
|
||||
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: always()
|
||||
|
|
@ -979,6 +1014,7 @@ jobs:
|
|||
path: |
|
||||
logs-scan-npm.txt
|
||||
logs-scan-npm-oxc.txt
|
||||
logs-scan-npm-studio.txt
|
||||
retention-days: 30
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
|
|
@ -1125,7 +1161,7 @@ jobs:
|
|||
working-directory: studio/frontend
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: npm audit signatures (informational)
|
||||
- name: npm audit signatures (Studio frontend, informational)
|
||||
# Surfaces unsigned / mis-signed packages from the npm
|
||||
# transparency log. continue-on-error during baseline-build
|
||||
# phase; promote to hard gate once the lockfile is fully
|
||||
|
|
@ -1134,10 +1170,48 @@ jobs:
|
|||
continue-on-error: true
|
||||
run: |
|
||||
set -o pipefail
|
||||
LOG=logs-audit-signatures.txt
|
||||
LOG="$GITHUB_WORKSPACE/logs-audit-signatures.txt"
|
||||
npm audit signatures 2>&1 | tee "$LOG"
|
||||
{
|
||||
echo "## npm audit signatures"
|
||||
echo "## npm audit signatures (Studio frontend)"
|
||||
echo
|
||||
echo '```'
|
||||
tail -200 "$LOG"
|
||||
echo '```'
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Install oxc-validator deps (--ignore-scripts)
|
||||
working-directory: studio/backend/core/data_recipe/oxc-validator
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: npm audit signatures (oxc-validator, informational)
|
||||
working-directory: studio/backend/core/data_recipe/oxc-validator
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -o pipefail
|
||||
LOG="$GITHUB_WORKSPACE/logs-audit-signatures-oxc.txt"
|
||||
npm audit signatures 2>&1 | tee "$LOG"
|
||||
{
|
||||
echo "## npm audit signatures (oxc-validator)"
|
||||
echo
|
||||
echo '```'
|
||||
tail -200 "$LOG"
|
||||
echo '```'
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Install Studio Tauri CLI holder deps (--ignore-scripts)
|
||||
working-directory: studio
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: npm audit signatures (Studio Tauri CLI holder, informational)
|
||||
working-directory: studio
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set -o pipefail
|
||||
LOG="$GITHUB_WORKSPACE/logs-audit-signatures-studio.txt"
|
||||
npm audit signatures 2>&1 | tee "$LOG"
|
||||
{
|
||||
echo "## npm audit signatures (Studio Tauri CLI holder)"
|
||||
echo
|
||||
echo '```'
|
||||
tail -200 "$LOG"
|
||||
|
|
@ -1154,6 +1228,9 @@ jobs:
|
|||
# OXC lockfile may not exist on the base ref (newly added).
|
||||
git show "$BASE_SHA:studio/backend/core/data_recipe/oxc-validator/package-lock.json" \
|
||||
> /tmp/base-oxc-package-lock.json 2>/dev/null || echo '{}' > /tmp/base-oxc-package-lock.json
|
||||
# Tauri CLI holder lockfile may not exist on the base ref (newly added).
|
||||
git show "$BASE_SHA:studio/package-lock.json" \
|
||||
> /tmp/base-studio-package-lock.json 2>/dev/null || echo '{}' > /tmp/base-studio-package-lock.json
|
||||
|
||||
- name: Diff for newly-added install-script deps
|
||||
if: github.event_name == 'pull_request'
|
||||
|
|
@ -1164,6 +1241,9 @@ jobs:
|
|||
python3 scripts/check_new_install_scripts.py \
|
||||
--base /tmp/base-oxc-package-lock.json \
|
||||
--head studio/backend/core/data_recipe/oxc-validator/package-lock.json
|
||||
python3 scripts/check_new_install_scripts.py \
|
||||
--base /tmp/base-studio-package-lock.json \
|
||||
--head studio/package-lock.json
|
||||
|
||||
- name: Skip install-script diff (non-PR trigger)
|
||||
if: github.event_name != 'pull_request'
|
||||
|
|
@ -1175,6 +1255,9 @@ jobs:
|
|||
if: always()
|
||||
with:
|
||||
name: npm-audit-signatures-log
|
||||
path: studio/frontend/logs-audit-signatures.txt
|
||||
path: |
|
||||
logs-audit-signatures.txt
|
||||
logs-audit-signatures-oxc.txt
|
||||
logs-audit-signatures-studio.txt
|
||||
if-no-files-found: ignore
|
||||
retention-days: 30
|
||||
|
|
|
|||
29
.github/workflows/studio-tauri-smoke.yml
vendored
29
.github/workflows/studio-tauri-smoke.yml
vendored
|
|
@ -60,14 +60,18 @@ jobs:
|
|||
with:
|
||||
workspaces: studio/src-tauri -> target
|
||||
|
||||
# Pre-install lockfile structural audit. Has to fire BEFORE
|
||||
# any `npm ci` so a tarball's `prepare` / `postinstall` cannot
|
||||
# run ahead of the scan. Pure-Python read-only; safe everywhere.
|
||||
- name: Lockfile supply-chain audit (pre-install scan)
|
||||
run: python3 scripts/lockfile_supply_chain_audit.py
|
||||
|
||||
- name: Install pinned Tauri CLI (matches release-desktop.yml)
|
||||
# Lifecycle scripts (esbuild native-binary postinstall, etc.) are
|
||||
# required for `vite build`. The pre-install lockfile structural
|
||||
# audit (lockfile_supply_chain_audit.py) is the practical defence
|
||||
# against the npm postinstall-dropper class -- it fires BEFORE any
|
||||
# tarball runs, on the injection pattern itself rather than an
|
||||
# advisory-DB lookup.
|
||||
run: npm install --save-dev --prefix studio @tauri-apps/cli@2.10.1 --no-fund --no-audit
|
||||
# `npm ci` resolves @tauri-apps/cli and its platform-specific
|
||||
# optional native binaries from studio/package-lock.json --
|
||||
# transitive versions are fully pinned, integrity hashes are
|
||||
# verified, and the install is reproducible across re-runs.
|
||||
run: npm ci --prefix studio --no-fund --no-audit
|
||||
|
||||
- name: Verify pinned Tauri CLI version
|
||||
run: |
|
||||
|
|
@ -75,17 +79,14 @@ jobs:
|
|||
echo "$out"
|
||||
[ "$out" = "tauri-cli 2.10.1" ] || { echo "::error::expected tauri-cli 2.10.1, got $out"; exit 1; }
|
||||
|
||||
- name: Lockfile supply-chain audit (pre-install scan)
|
||||
run: python3 scripts/lockfile_supply_chain_audit.py
|
||||
|
||||
- name: Frontend build (npm ci, vite)
|
||||
working-directory: studio/frontend
|
||||
# Lifecycle scripts (esbuild native-binary postinstall, etc.) are
|
||||
# required for `vite build`. The pre-install lockfile structural
|
||||
# audit (lockfile_supply_chain_audit.py) is the practical defence
|
||||
# against the npm postinstall-dropper class -- it fires BEFORE any
|
||||
# tarball runs, on the injection pattern itself rather than an
|
||||
# advisory-DB lookup.
|
||||
# audit (lockfile_supply_chain_audit.py) above is the practical
|
||||
# defence against the npm postinstall-dropper class -- it fires
|
||||
# BEFORE any tarball runs, on the injection pattern itself rather
|
||||
# than an advisory-DB lookup.
|
||||
run: |
|
||||
npm ci --no-fund --no-audit
|
||||
npm run build
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue