Skip to content
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
e7fdc4b
chore(deps): bump fgrosse/go-coverage-report
dependabot[bot] Aug 3, 2026
4693ef8
feat(js-pr-validation): add socket.dev supply chain gate
bedatty Aug 5, 2026
cfe360f
fix(js-pr-validation): enforce sfw inspection and purge package cache
bedatty Aug 5, 2026
f75d2fd
fix(js-pr-validation): pin the socketsecurity CLI release
bedatty Aug 5, 2026
ee22bc5
test(js-pr-validation): point socket composites at this branch
bedatty Aug 5, 2026
77b3ad2
feat(js-pr-validation): guard every install and gate on the Socket App
bedatty Aug 5, 2026
5b9ecc6
fix(js-pr-validation): set result-encoding on the socket reporter
bedatty Aug 5, 2026
54f3c4d
fix(js-pr-validation): grant checks:read and stop swallowing API errors
bedatty Aug 5, 2026
bb8ca83
feat(js-pr-validation): declare SOCKET_SECURITY_API_KEY as optional
bedatty Aug 5, 2026
cde744a
test(js-pr-validation): add temporary socket token reachability probe
bedatty Aug 5, 2026
7a33a1e
test(js-pr-validation): drop the socket token reachability probe
bedatty Aug 5, 2026
ef1c887
feat(js-pr-validation): report per-package Socket Firewall findings
bedatty Aug 5, 2026
a778bc2
feat(js-pr-validation): report per-package vulnerabilities via the So…
bedatty Aug 5, 2026
13d8d48
fix(js-pr-validation): surface the Socket API error payload
bedatty Aug 6, 2026
4a53572
fix(js-pr-validation): tell a Cloudflare challenge apart from a scope…
bedatty Aug 6, 2026
4f08039
fix(js-pr-validation): fetch the Socket API with python, not curl
bedatty Aug 6, 2026
de9c860
test(js-pr-validation): widen the socket alert debug sample
bedatty Aug 6, 2026
43ac207
test(js-pr-validation): log the socket alert action distribution
bedatty Aug 6, 2026
b9f61ce
feat(js-pr-validation): filter socket findings by action and own the …
bedatty Aug 6, 2026
52c6a81
feat(js-pr-validation): expose the socket findings policy on the umbr…
bedatty Aug 6, 2026
651aa00
fix(js-pr-validation): render the socket fix object instead of [objec…
bedatty Aug 6, 2026
0f1afd5
feat(js-pr-validation): separate introduced findings from pre-existin…
bedatty Aug 6, 2026
e190d16
test(js-pr-validation): log the socket baseline scan identity
bedatty Aug 6, 2026
d5fa617
fix(js-pr-validation): reject incomplete socket baselines
bedatty Aug 6, 2026
eacae6a
test(js-pr-validation): log the head scan's own scan_state
bedatty Aug 6, 2026
a301f93
fix(js-pr-validation): select the socket baseline by package overlap
bedatty Aug 6, 2026
817e47d
fix(js-pr-validation): attribute findings via Socket's diff scan
bedatty Aug 6, 2026
3ce2df2
feat(js-pr-validation): green header with no new findings, and dashbo…
bedatty Aug 6, 2026
b6365a2
style(js-pr-validation): split the diff-scan lookup across lines
bedatty Aug 6, 2026
6137cc4
feat(js-pr-validation): give the pre-existing section shape
bedatty Aug 6, 2026
ce54891
fix(js-pr-validation): label the scan link as this PR's scan
bedatty Aug 6, 2026
b38f781
feat(js-pr-validation): show which direct dependency reaches a finding
bedatty Aug 6, 2026
cb28c98
chore(release): backmerge main into develop [skip ci]
lerian-studio Aug 7, 2026
87fffd0
fix(js-pr-validation): restore the suggested fixes block
bedatty Aug 7, 2026
b38a179
docs(js-pr-validation): correct the Socket documentation
bedatty Aug 7, 2026
c7ad918
fix(js-pr-validation): detect a stale diff scan instead of trusting it
bedatty Aug 7, 2026
f850c85
fix(js-pr-validation): build the diff scan instead of waiting for the…
bedatty Aug 7, 2026
7d39f39
test(js-pr-validation): diagnose a diff scan reporting added=0
bedatty Aug 7, 2026
10b45f7
fix(js-pr-validation): drop omit_unchanged from the diff scan read
bedatty Aug 7, 2026
95c6f70
fix(js-pr-validation): read the diff buckets from diff_scan.artifacts
bedatty Aug 7, 2026
aaf144c
fix(js-pr-validation): print dashboard URLs instead of bare scan ids
bedatty Aug 7, 2026
c807994
refactor(js-pr-validation): drop the resolved diagnostics
bedatty Aug 7, 2026
b1aa4f4
chore(js-pr-validation): pin the socket composites back to @v1
bedatty Aug 7, 2026
81cc6bf
Merge branch 'develop' into feat/js-pr-validation-socket
bedatty Aug 7, 2026
7b3255f
fix(js-pr-validation): address the CodeRabbit security and correctnes…
bedatty Aug 7, 2026
9f96d77
fix(js-pr-validation): rename anc so the spell check passes
bedatty Aug 7, 2026
cbaa29e
fix(js-pr-validation): close four more silent-pass paths from the review
bedatty Aug 7, 2026
471eb23
fix: remove the typos binary committed by accident
bedatty Aug 7, 2026
513193d
feat(js-pr-validation): add socket.dev supply chain gate (#645)
bedatty Aug 7, 2026
6908449
chore(deps): bump fgrosse/go-coverage-report from 1.3.0 to 1.3.1 in t…
bedatty Aug 7, 2026
b7e5915
fix(go-ci): pin external actions by sha and fix shellcheck warnings
bedatty Aug 7, 2026
c0cced3
fix(js-pr-validation): address socket layer review findings
bedatty Aug 7, 2026
a47239b
fix(js-pr-validation): stop reporting unmeasured socket state as clean
bedatty Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ updates:
- "trufflesecurity/trufflehog"
- "anchore/sbom-action"
- "sigstore/cosign-installer"
# Only reachable if SocketDev/action is ever referenced from a workflow;
# its current use is in src/security/socket-firewall, which the
# github-actions ecosystem does not scan (see note at the top).
- "SocketDev/action"
update-types:
- "minor"
- "patch"
Expand Down
352 changes: 99 additions & 253 deletions .github/workflows/frontend-pr-analysis.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@

steps:
- name: Checkout code
uses: actions/checkout@v7.0.1

Check failure on line 82 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/checkout@v7.0.1 (use full commit SHA with a # vX.Y.Z comment)

- name: Set up Go
uses: actions/setup-go@v7

Check failure on line 85 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/setup-go@v7 (use full commit SHA with a # vX.Y.Z comment)
with:
go-version: ${{ matrix.go }}
cache: true
Expand All @@ -101,7 +101,7 @@

- name: Upload coverage artifact
if: inputs.enable_coverage_comment && matrix.os == 'ubuntu-latest' && matrix.go == inputs.go_version_lint
uses: actions/upload-artifact@v7

Check failure on line 104 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/upload-artifact@v7 (use full commit SHA with a # vX.Y.Z comment)
with:
name: coverage-report
path: coverage.txt
Expand All @@ -118,15 +118,15 @@

steps:
- name: Checkout code
uses: actions/checkout@v7.0.1

Check failure on line 121 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/checkout@v7.0.1 (use full commit SHA with a # vX.Y.Z comment)

- name: Download coverage artifact
uses: actions/download-artifact@v8

Check failure on line 124 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/download-artifact@v8 (use full commit SHA with a # vX.Y.Z comment)
with:
name: coverage-report

- name: Go Coverage Comment
uses: fgrosse/go-coverage-report@v1.3.0
uses: fgrosse/go-coverage-report@v1.3.1

Check failure on line 129 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: fgrosse/go-coverage-report@v1.3.1 (use full commit SHA with a # vX.Y.Z comment)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
with:
coverage-artifact-name: coverage-report
coverage-file-name: coverage.txt
Expand All @@ -137,16 +137,16 @@

steps:
- name: Checkout code
uses: actions/checkout@v7.0.1

Check failure on line 140 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/checkout@v7.0.1 (use full commit SHA with a # vX.Y.Z comment)

- name: Set up Go
uses: actions/setup-go@v7

Check failure on line 143 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/setup-go@v7 (use full commit SHA with a # vX.Y.Z comment)
with:
go-version: ${{ inputs.go_version_lint }}
cache: true

- name: golangci-lint
uses: golangci/golangci-lint-action@v9

Check failure on line 149 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: golangci/golangci-lint-action@v9 (use full commit SHA with a # vX.Y.Z comment)
with:
version: ${{ inputs.golangci_lint_version }}
args: ${{ inputs.golangci_lint_args }}
Expand All @@ -159,7 +159,7 @@

steps:
- name: Checkout code
uses: actions/checkout@v7.0.1

Check failure on line 162 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

External action not pinned by SHA: uses: actions/checkout@v7.0.1 (use full commit SHA with a # vX.Y.Z comment)

- name: Set up Go
uses: actions/setup-go@v7
Expand All @@ -168,7 +168,7 @@
cache: true

- name: Build cross-platform binaries
run: |

Check failure on line 171 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2162:info:13:39: read without -r will mangle backslashes

Check failure on line 171 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:23:43: Double quote to prevent globbing and word splitting

Check failure on line 171 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:15:15: Double quote to prevent globbing and word splitting

Check failure on line 171 in .github/workflows/go-ci.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:14:13: Double quote to prevent globbing and word splitting
targets='${{ inputs.build_targets }}'
if [ "$targets" = "[]" ] || [ -z "$targets" ]; then
echo "No build targets specified, using defaults"
Expand Down
267 changes: 267 additions & 0 deletions .github/workflows/js-pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ on:
description: 'Run the security scan pipeline (Trivy, CodeQL, prerelease checks)'
type: boolean
default: true
run_socket:
description: 'Run the Socket supply-chain pipeline (Socket Firewall and, when enabled, the Socket CLI scan)'
type: boolean
default: true

# ----------------- Change gate -----------------
ignore_globs:
Expand Down Expand Up @@ -282,14 +286,111 @@ on:
description: 'Comma-separated directories to skip in every Trivy filesystem scan (appended to the built-in skip list).'
type: string
default: ''

# ----------------- Socket supply chain (src/security/socket-*) -----------------
socket_enable_firewall:
description: 'Run Socket Firewall (free tier, no token) and install dependencies through it, blocking malicious packages at install time.'
type: boolean
default: true
socket_working_dir:
description: 'Directory holding the package.json and lockfile scanned by the Socket jobs'
type: string
default: '.'
socket_firewall_version:
description: 'Socket Firewall binary version. Empty or "latest" tracks the newest release.'
type: string
default: 'latest'
socket_job_summary:
description: 'Socket Firewall job summary verbosity (all, errors, none)'
type: string
default: 'all'
socket_use_cache:
description: 'Cache the sfw binary between runs. Unrelated to the package-manager cache, which is always purged before the guarded install.'
type: boolean
default: true
socket_fail_on_block:
description: 'Fail the Socket job when Socket Firewall blocks a package. Set to false to report the block as a warning instead.'
type: boolean
default: true
socket_enable_app_gate:
description: >-
Turn the Socket GitHub App checks into an enforceable gate. The App analyses the dependency graph and
posts advisory checks; this makes an adverse verdict block the pull request. Needs no token.
type: boolean
default: true
socket_app_slug:
description: 'GitHub App slug whose checks the gate reads'
type: string
default: 'socket-security'
socket_app_timeout:
description: 'Seconds to wait for the Socket App checks to complete before treating the result as inconclusive'
type: number
default: 300
socket_app_fail_on_findings:
description: 'Fail the Socket job when the App reports adverse checks'
type: boolean
default: true
socket_app_on_inconclusive:
description: >-
What to do when the App ran but reached no verdict (neutral/skipped/timeout): "block" (default) or "warn".
A conflicted pull request is the common cause, and it must not read as clean.
type: string
default: 'block'
socket_enable_api_report:
description: >-
Read the full scan the Socket App already computed and report per-package alerts, vulnerabilities and
scores in the pull request comment. Requires SOCKET_SECURITY_API_KEY with the full-scans:list scope.
Advisory only — it never gates the merge.
type: boolean
default: true
socket_api_max_rows:
description: 'Maximum package rows kept in the dependency findings table'
type: number
default: 25
socket_api_include_actions:
description: >-
Comma-separated Socket alert actions reported as findings. Socket marks roughly 99% of alerts as "ignore"
(capability observations such as envVars), so reporting unfiltered buries a handful of findings in
thousands of lines.
type: string
default: 'error,warn,monitor'
socket_comment_when:
description: >-
"findings" (the default) posts the Socket comment only when there is something to act on. "always" posts
every run. Operational state — whether the scan ran, which checks passed — is never in the comment; it
lives in the job log and the Socket status check.
type: string
default: 'findings'
socket_api_fail_on_actions:
description: >-
Comma-separated Socket alert actions that block the pull request. Empty (the default) reports without
blocking. Set to e.g. "error" to own the merge decision in this workflow rather than deferring it to the
Socket App's verdict.
type: string
default: ''
socket_app_on_missing:
description: >-
What to do when the App published no checks, which is what a repository without it installed looks like:
"warn" (default) keeps those repositories green, "block" requires the App.
type: string
default: 'warn'
secrets:
MANAGE_TOKEN:
required: false
SLACK_WEBHOOK_URL:
required: false
# Declared but not consumed by any job today: the Socket layers here run
# token-free (the firewall inspects traffic locally, the App gate reads the
# GitHub checks API). It is declared so an organization secret reaches this
# workflow through `secrets: inherit` without a release, which a reusable
# workflow cannot do for an undeclared secret. Do not delete as dead —
# Socket Firewall enterprise is the intended consumer.
SOCKET_SECURITY_API_KEY:
required: false
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

permissions:
actions: read
checks: read
contents: read
id-token: write
issues: write
Expand Down Expand Up @@ -351,6 +452,9 @@ jobs:
path_level: ${{ inputs.path_level }}
normalize_to_filter: ${{ inputs.normalize_to_filter }}
app_name_prefix: ${{ inputs.app_name_prefix }}
enable_socket_firewall: ${{ inputs.socket_enable_firewall }}
socket_firewall_version: ${{ inputs.socket_firewall_version }}
socket_fail_on_block: ${{ inputs.socket_fail_on_block }}
enable_lint: ${{ inputs.enable_lint }}
enable_typecheck: ${{ inputs.enable_typecheck }}
enable_security: ${{ inputs.enable_security }}
Expand Down Expand Up @@ -427,6 +531,169 @@ jobs:
result: ${{ needs.changes.result != 'success' && needs.changes.result || needs.security.result }}
label: Security

# ----------------- Socket Supply Chain -----------------
socket:
name: Socket (checks)
needs: changes
if: inputs.run_socket && needs.changes.outputs.code == 'true'
runs-on: ${{ vars.GENERAL_RUNNERS || inputs.runner_type }}
permissions:
contents: read
checks: read
issues: write
pull-requests: write
env:
SOCKET_APP_NAME: ${{ inputs.app_name_prefix != '' && inputs.app_name_prefix || github.event.repository.name }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with:
persist-credentials: false

# This install is the reporting source of truth for the Socket Firewall
# row below. Enforcement itself is broader: every install in
# frontend-pr-analysis.yml also runs through the firewall, so a malicious
# package cannot execute install scripts in any analysis job either.
- name: Socket Firewall
id: firewall
if: inputs.socket_enable_firewall
continue-on-error: true
uses: LerianStudio/github-actions-shared-workflows/src/security/socket-firewall@v1
with:
package-manager: ${{ inputs.package_manager }}
node-version: ${{ inputs.node_version }}
working-dir: ${{ inputs.socket_working_dir }}
firewall-version: ${{ inputs.socket_firewall_version }}
job-summary: ${{ inputs.socket_job_summary }}
use-cache: ${{ inputs.socket_use_cache }}
fail-on-block: ${{ inputs.socket_fail_on_block }}
dry-run: ${{ inputs.dry_run }}

- name: Socket App Gate
id: app-gate
if: inputs.socket_enable_app_gate && github.event_name == 'pull_request'
continue-on-error: true
uses: LerianStudio/github-actions-shared-workflows/src/security/socket-app-gate@v1
with:
github-token: ${{ secrets.MANAGE_TOKEN || github.token }}
# The App reports against the pull request head, not the merge commit.
commit-sha: ${{ github.event.pull_request.head.sha }}
app-slug: ${{ inputs.socket_app_slug }}
timeout-seconds: ${{ inputs.socket_app_timeout }}
fail-on-findings: ${{ inputs.socket_app_fail_on_findings }}
on-inconclusive: ${{ inputs.socket_app_on_inconclusive }}
on-missing-app: ${{ inputs.socket_app_on_missing }}

# Reads the scan the App already produced, addressed by the dashboard URL the
# gate captured — no new scan, one quota unit, no duplicate analysis.
# The App publishes the diff scan id in its own comment. Looking it up by
# after_full_scan_id does not work: the App diffs against a different full
# scan than the one its Project Report check links to.
- name: Resolve Socket diff scan id
id: diff-scan
if: always() && inputs.socket_enable_api_report && github.event_name == 'pull_request'
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.MANAGE_TOKEN || github.token }}
PR: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
JQ='[.[] | select(.user.login == "socket-security[bot]") | .body] | last // ""'
BODY=$(gh api "repos/$REPO/issues/$PR/comments" --paginate --jq "$JQ")
ID=$(printf '%s' "$BODY" \
| grep -oE 'diff-scan/[0-9a-fA-F-]{36}' | head -1 | cut -d/ -f2 || true)
if [ -n "$ID" ]; then
echo "Resolved diff scan $ID from the Socket App comment."
else
echo "No diff scan id in the Socket App comment — it only posts one when dependencies change."
fi
echo "id=$ID" >> "$GITHUB_OUTPUT"

- name: Socket API Report
id: api-report
if: always() && inputs.socket_enable_api_report && github.event_name == 'pull_request'
continue-on-error: true
uses: LerianStudio/github-actions-shared-workflows/src/security/socket-api-report@v1
with:
socket-api-key: ${{ secrets.SOCKET_SECURITY_API_KEY }}
report-url: ${{ steps.app-gate.outputs.report-url }}
max-rows: ${{ inputs.socket_api_max_rows }}
include-actions: ${{ inputs.socket_api_include_actions }}
fail-on-actions: ${{ inputs.socket_api_fail_on_actions }}
# The baseline: findings already on the target branch are reported as
# pre-existing and never block, so a repository carrying debt does not
# fail every pull request for something none of them caused.
base-branch: ${{ github.base_ref }}
head-sha: ${{ github.event.pull_request.head.sha }}
diff-scan-id: ${{ steps.diff-scan.outputs.id }}

- name: Post Socket report to PR
if: always() && github.event_name == 'pull_request' && !inputs.dry_run
uses: LerianStudio/github-actions-shared-workflows/src/security/socket-reporter@v1
with:
github-token: ${{ secrets.MANAGE_TOKEN || github.token }}
app-name: ${{ env.SOCKET_APP_NAME }}
comment-when: ${{ inputs.socket_comment_when }}
firewall-blocked: ${{ steps.firewall.outputs.blocked || 'false' }}
firewall-fail-on-block: ${{ inputs.socket_fail_on_block }}
firewall-findings-file: ${{ steps.firewall.outputs.findings-file }}
api-findings-file: ${{ steps.api-report.outputs.findings-file }}
api-blocking-count: ${{ steps.api-report.outputs.blocking-count || '0' }}
# yamllint disable-line rule:line-length
run-url: ${{ format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }}

# continue-on-error above keeps the report reachable even when a layer
# fails, so the verdict is re-applied here.
# dry_run is a preview across the whole umbrella, so the gate reports the
# verdict it would have applied instead of applying it.
- name: Gate - Fail on Socket findings
if: always() && !inputs.dry_run
env:
FIREWALL_OUTCOME: ${{ steps.firewall.outcome }}
APP_GATE_OUTCOME: ${{ steps.app-gate.outcome }}
API_BLOCKING: ${{ steps.api-report.outputs.blocking-count }}
run: |
FAILED=""
[ "$FIREWALL_OUTCOME" = "failure" ] && FAILED="$FAILED Socket-Firewall"
[ "$APP_GATE_OUTCOME" = "failure" ] && FAILED="$FAILED Socket-App-Gate"
# Only real findings from the API layer block. Its API-failure paths
# report zero here by construction, so an unreachable Socket cannot
# fail a pull request.
if [ "${API_BLOCKING:-0}" -gt 0 ] 2>/dev/null; then
FAILED="$FAILED Socket-Dependency-Findings"
fi
if [ -n "$FAILED" ]; then
echo "::error::Socket supply chain gate failed:$FAILED. See the Socket comment on the pull request."
exit 1
fi
echo "Socket supply chain gate passed."

- name: Gate - Socket findings (dry run)
if: always() && inputs.dry_run
env:
FIREWALL_OUTCOME: ${{ steps.firewall.outcome }}
APP_GATE_OUTCOME: ${{ steps.app-gate.outcome }}
API_BLOCKING: ${{ steps.api-report.outputs.blocking-count }}
run: |
echo "::notice::DRY RUN — Socket gate not enforced"
echo " Socket Firewall : $FIREWALL_OUTCOME"
echo " Socket App gate : $APP_GATE_OUTCOME"
echo " Blocking findings: ${API_BLOCKING:-0}"

socket-gate:
name: Socket
needs: [changes, socket]
if: always()
runs-on: ${{ vars.GENERAL_RUNNERS || inputs.runner_type }}
permissions:
contents: read
steps:
- name: Aggregate Socket result
uses: LerianStudio/github-actions-shared-workflows/src/validate/result-gate@v1
with:
result: ${{ needs.changes.result != 'success' && needs.changes.result || needs.socket.result }}
label: Socket

# ----------------- Org ruleset compatibility stubs -----------------
# Go Analysis and Lib Version are required status checks in the Lerian org
# branch-protection ruleset (designed for Go repos). These stubs are
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ go.list
# ── Temporary files ────────────────────────────────────────────────────────────
tmp/
temp/

# Linter binaries fetched ad hoc for local verification
/typos
11 changes: 11 additions & 0 deletions docs/frontend-pr-analysis-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ jobs:
secrets: inherit
```

## Guarded dependency installs

Every job that installs dependencies does so through [`setup-node-guarded`](../src/setup/setup-node-guarded/README.md), which runs `sfw npm ci` (or the `yarn`/`pnpm` equivalent) under [Socket Firewall](https://github.com/SocketDev/sfw-free) instead of a bare install. A malicious package is refused mid-fetch, so it never reaches disk and its install scripts never execute — in **any** of these jobs, not just one.

Guarded installs deliberately run **without a package-manager cache**: Socket Firewall only inspects what crosses the network, and a cached tarball produces no request. The cache is also purged before each install, since runner images can arrive pre-warmed. Measured cost is roughly 20s for a cold install of ~2000 packages.

Set `enable_socket_firewall: false` to restore the previous behaviour (cached, unguarded) — necessary for repositories that install from a private registry, which the free edition does not support.

## Inputs

| Input | Description | Required | Default |
Expand All @@ -152,6 +160,9 @@ jobs:
| `app_name_prefix` | Prefix for app names in matrix output | No | `''` |
| `node_version` | Node.js version to use | No | `22` |
| `package_manager` | Package manager (npm, yarn, pnpm) | No | `npm` |
| `enable_socket_firewall` | Route every dependency install through Socket Firewall (free tier, no token) so a malicious package is refused before any install script runs. `false` restores the previous behaviour, package-manager cache included | No | `true` |
| `socket_firewall_version` | Socket Firewall binary version | No | `latest` |
| `socket_fail_on_block` | Fail the job when Socket Firewall blocks a package | No | `true` |
| `eslint_args` | Additional ESLint arguments | No | `''` |
| `audit_level` | npm audit severity level (low, moderate, high, critical) | No | `high` |
| `coverage_threshold` | Minimum coverage percentage (0-100) | No | `80` |
Expand Down
Loading
Loading