From 95e57e088ee326c6995a66acff7f0603b4e7bb9a Mon Sep 17 00:00:00 2001 From: Theo Ephraim Date: Mon, 15 Jun 2026 17:44:03 -0700 Subject: [PATCH] ci: add Socket supply-chain scanning, tune dependency audit noise - Add nightly socket ci scan and weekly socket fix (remediation PRs, no auto-merge) - Add socket.yml to tune alert noise: scope PR scans to dep changes, mute low-signal reputational alerts, keep malware/install-script/network/env signals - Drop bun audit PR gate from moderate to critical-only; Socket is the primary gate - Remove nightly bun audit (redundant with socket ci on the known-CVE axis) --- .github/workflows/nightly-audit.yaml | 20 --------- .github/workflows/nightly-socket-scan.yaml | 28 +++++++++++++ .github/workflows/weekly-socket-fix.yaml | 36 +++++++++++++++++ package.json | 2 +- socket.yml | 47 ++++++++++++++++++++++ 5 files changed, 112 insertions(+), 21 deletions(-) delete mode 100644 .github/workflows/nightly-audit.yaml create mode 100644 .github/workflows/nightly-socket-scan.yaml create mode 100644 .github/workflows/weekly-socket-fix.yaml create mode 100644 socket.yml diff --git a/.github/workflows/nightly-audit.yaml b/.github/workflows/nightly-audit.yaml deleted file mode 100644 index 4c12558a..00000000 --- a/.github/workflows/nightly-audit.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: Nightly dependency audit -on: - schedule: - - cron: '15 7 * * *' - workflow_dispatch: - -permissions: - contents: read - -jobs: - audit: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - - name: Install js deps (w/ bun) - run: bun install - - name: Full dependency audit - run: bun run audit:full diff --git a/.github/workflows/nightly-socket-scan.yaml b/.github/workflows/nightly-socket-scan.yaml new file mode 100644 index 00000000..b634a2eb --- /dev/null +++ b/.github/workflows/nightly-socket-scan.yaml @@ -0,0 +1,28 @@ +name: Nightly Socket supply-chain scan +on: + schedule: + # 07:45 UTC — offset from the nightly dependency audit (07:15) + - cron: '45 7 * * *' + workflow_dispatch: + +permissions: + contents: read + +jobs: + socket-scan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + - name: Use Node.js 24.x + uses: actions/setup-node@v6 + with: + node-version: "24.x" + # Socket reads manifests + lockfiles directly and queries the Socket API, + # so no `bun install` is needed. Run the CLI via bunx to avoid pulling a + # third-party marketplace Action into our trusted set. + - name: Socket scan + run: bunx socket ci + env: + SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} diff --git a/.github/workflows/weekly-socket-fix.yaml b/.github/workflows/weekly-socket-fix.yaml new file mode 100644 index 00000000..80aec1b1 --- /dev/null +++ b/.github/workflows/weekly-socket-fix.yaml @@ -0,0 +1,36 @@ +name: Weekly Socket remediation PRs +on: + schedule: + # Mondays 08:00 UTC — weekly, offset from the nightly scans + - cron: '0 8 * * 1' + workflow_dispatch: + +# socket fix opens PRs, so it needs write scope. This is the ONLY Socket job +# that carries write permissions — detection (nightly-socket-scan) stays read-only. +permissions: + contents: write + pull-requests: write + +jobs: + socket-fix: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + - name: Use Node.js 24.x + uses: actions/setup-node@v6 + with: + node-version: "24.x" + - name: Install js deps (w/ bun) + run: bun install + # No --autopilot: Socket opens remediation PRs but never merges them. + # A human reviews the actual dep diff before it lands — deliberate, given + # we publish to npm. + - name: Socket fix + run: bunx socket fix --pr-limit 10 + env: + SOCKET_SECURITY_API_KEY: ${{ secrets.SOCKET_SECURITY_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SOCKET_CLI_GIT_USER_NAME: 'socket-fix[bot]' + SOCKET_CLI_GIT_USER_EMAIL: 'socket-fix@users.noreply.github.com' diff --git a/package.json b/package.json index 93a7f34c..aa9ebb99 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "dev": "turbo run dev --concurrency=40 --parallel --filter=\"!smoke-test-*\"", "lint": "eslint .", "lint:fix": "eslint . --fix", - "audit:changed": "bun run scripts/audit-changed-packages.ts --audit-level=moderate", + "audit:changed": "bun run scripts/audit-changed-packages.ts --audit-level=critical", "audit:full": "bun audit --audit-level=moderate", "bumpy:add": "bumpy add", "release:create-missing-tags": "node scripts/create-missing-release-tags.js", diff --git a/socket.yml b/socket.yml new file mode 100644 index 00000000..ab1d9a93 --- /dev/null +++ b/socket.yml @@ -0,0 +1,47 @@ +# Socket (socket.dev) configuration — read by the Socket GitHub App. +# Lives in-repo so our supply-chain policy is reviewable + version-controlled +# instead of buried in the dashboard. +# +# NOTE: issueRules here control *whether an alert is reported at all* (noise). +# Whether a reported alert *blocks* a PR vs. just comments is governed by the +# org Security Policy in the Socket dashboard — keep the high-signal ones below +# set to "block" there, and the rest to "monitor". +version: 2 + +# Only scan PRs that actually change dependencies. A PR that touches no manifest +# or lockfile has nothing for Socket to say — this alone kills most of the noise. +triggerPaths: + - "**/package.json" + - "bun.lock" + - "bun.lockb" + +githubApp: + enabled: true + # Keep real security alerts on PRs... + pullRequestAlertsEnabled: true + # ...but drop the big auto-generated dependency-overview / report comments that + # land on every PR and train people to scroll past Socket. + dependencyOverviewEnabled: false + projectReportsEnabled: false + +issueRules: + # --- High signal: the malicious-bump / credential-theft threat model --- + malware: true # known malware + installScripts: true # postinstall/preinstall hooks (the classic exfil vector) + shellScriptOverride: true # package overrides shell scripts + networkAccess: true # phones home + envVars: true # reads env vars — directly relevant to a secrets tool + gitDependency: true # non-registry source (git) + httpDependency: true # non-registry source (http url) + didYouMean: true # typosquat / lookalike name + troll: true # protestware / sabotage + obfuscatedRequire: true # obfuscated code paths + criticalCVE: true # critical known vulns + + # --- Low signal for us: reputational/heuristic noise we were ignoring anyway --- + newAuthor: false # new maintainer publishing — fires constantly + unstableOwnership: false + telemetry: false # covered by networkAccess for the cases we care about + minifiedFile: false # common in legit deps + hasNativeCode: false # we ship native binaries ourselves; not a useful signal here + deprecated: false # handled by our dependency hygiene, not a security gate