Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
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
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
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"
Comment on lines +77 to +80

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Socket action reference and Dependabot pattern ---'
rg -n -C 3 'SocketDev/action' \
  .github/dependabot.yml \
  src/security/socket-firewall/action.yml

printf '%s\n' '--- Candidate composite-action drift checks ---'
rg -n -i -C 3 \
  'SocketDev/action|dependency[ -]drift|action[ -]drift|composite.*update' \
  .

Repository: LerianStudio/github-actions-shared-workflows

Length of output: 8631


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Repository automation files ---'
git ls-files '.github' | sort

printf '%s\n' '--- All SocketDev/action references ---'
rg -n -i -C 4 'SocketDev/action' --glob '!CHANGELOG.md' .

printf '%s\n' '--- Drift and dependency automation ---'
rg -n -i -C 5 \
  'dependabot|dependency|drift|renovate|update.*action|action.*update|pin.*sha|sha.*pin' \
  .github Makefile package.json .pre-commit-config.yaml 2>/dev/null || true

printf '%s\n' '--- Dependabot configuration ---'
cat -n .github/dependabot.yml

Repository: LerianStudio/github-actions-shared-workflows

Length of output: 35084


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Repository files that could implement action pin updates ---'
git ls-files | rg -i \
  '(^|/)(dependabot|renovate|pinact|actionlint|update|drift|dependency|deps|renov).*(yml|yaml|sh|py|js|ts|go|mk|json)$|(^|/)(Makefile|Taskfile(\.ya?ml)?|package\.json)$' \
  || true

printf '%s\n' '--- Exact update-check tool references ---'
rg -n -i -C 3 \
  'pinact|renovate|dependabot.*(?:composite|src/)|(?:composite|src/).*dependabot|check[-_ ]actions|update[-_ ]actions|actions[-_ ]update|dependency[-_ ]drift|action[-_ ]drift' \
  --glob '!CHANGELOG.md' . \
  || true

printf '%s\n' '--- Workflow steps that execute repository-maintenance checks ---'
rg -n -i -C 4 \
  'run:|uses:|schedule:|workflow_dispatch:' \
  .github/workflows \
  | rg -i 'run:|uses:|schedule:|workflow_dispatch:|dependabot|renovate|pinact|drift|dependency|actionlint|update' \
  || true

Repository: LerianStudio/github-actions-shared-workflows

Length of output: 50400


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Pinned-actions validator ---'
git ls-files 'src/lint/pinned-actions' '.github/workflows/self-pr-validation.yml'
find src/lint/pinned-actions -maxdepth 2 -type f -print -exec sh -c 'echo "--- $1"; cat -n "$1"' _ {} \;

printf '%s\n' '--- Makefile maintenance targets ---'
rg -n -C 5 -i 'action|depend|pin|drift|update' Makefile

Repository: LerianStudio/github-actions-shared-workflows

Length of output: 9610


Add an active update path for SocketDev/action.

Dependabot does not scan composite actions under src/**/action.yml. The existing pinned-actions validator checks pin format but does not update action versions. Both src/security/socket-firewall/action.yml and src/setup/setup-node-guarded/action.yml reference SocketDev/action. Add a drift check that covers both files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/dependabot.yml around lines 77 - 80, Add an active Dependabot update
or drift-check configuration for SocketDev/action that explicitly covers both
src/security/socket-firewall/action.yml and
src/setup/setup-node-guarded/action.yml. Keep the existing pinned-actions
validation, but ensure this new path detects version changes for references in
both composite action files rather than relying on workflow scanning.

update-types:
- "minor"
- "patch"
Expand Down
118 changes: 118 additions & 0 deletions .github/workflows/js-pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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
Comment on lines +40 to +43

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Wire the paid Socket scan or remove the public claim.

The socket job has no socket-scan step. It runs Firewall, App Gate, API Report, and Reporter steps only. Therefore, run_socket does not run the promised Socket CLI report.

  • .github/workflows/js-pr-validation.yml#L30-L33: add the intended scan action and its caller contract, or describe the implemented App/API pipeline.
  • docs/js-pr-validation.md#L14-L14: remove the socket-scan and CLI-report claim unless the workflow invokes that composite.
📍 Affects 2 files
  • .github/workflows/js-pr-validation.yml#L30-L33 (this comment)
  • docs/js-pr-validation.md#L14-L14
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/js-pr-validation.yml around lines 30 - 33, Align the
documented Socket behavior with the implementation: in
.github/workflows/js-pr-validation.yml lines 30-33, either wire the intended
socket-scan composite action and its caller contract into the run_socket flow or
update the description to accurately identify the existing Firewall, App Gate,
API Report, and Reporter pipeline; in docs/js-pr-validation.md line 14, remove
the socket-scan and CLI-report claim unless that composite action is invoked.


# ----------------- Change gate -----------------
ignore_globs:
Expand Down Expand Up @@ -272,11 +276,63 @@ 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_enable_scan:
description: 'Run the Socket CLI scan (paid tier). Requires the SOCKET_SECURITY_API_KEY secret; without it the step skips with a notice.'
type: boolean
default: false
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_fail_on_findings:
description: 'Fail the Socket job when the Socket CLI scan reports blocking alerts. Default false keeps the scan advisory until a repository is clean.'
type: boolean
default: false
socket_sarif_file:
description: 'Path where the Socket CLI scan writes its SARIF report. Empty = no SARIF.'
type: string
default: ''
socket_ignore_commit_files:
description: 'Scan every manifest instead of only the ones touched by the commit (--ignore-commit-files)'
type: boolean
default: false
socket_python_version:
description: 'Python version used to run the Socket CLI'
type: string
default: '3.12'
socket_cli_version:
description: 'socketsecurity release installed from PyPI, pinned so the package executed with the API token cannot change between runs. Set to "latest" to track the newest release instead.'
type: string
default: '2.5.8'
secrets:
MANAGE_TOKEN:
required: false
SLACK_WEBHOOK_URL:
required: false
SOCKET_SECURITY_API_KEY:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
required: false

permissions:
actions: read
Expand Down Expand Up @@ -417,6 +473,68 @@ 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
issues: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with:
# socketcli diffs the commit to decide which manifests changed.
fetch-depth: 2
persist-credentials: false

- name: Socket Firewall
if: inputs.socket_enable_firewall
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 Scan
if: always() && inputs.socket_enable_scan
uses: LerianStudio/github-actions-shared-workflows/src/security/socket-scan@v1
with:
# Token presence is resolved inside the composite rather than in an
# `if:` — the secrets context is unavailable in step conditions.
socket-api-key: ${{ secrets.SOCKET_SECURITY_API_KEY }}
github-token: ${{ secrets.MANAGE_TOKEN || github.token }}
target-path: ${{ inputs.socket_working_dir }}
pr-number: ${{ github.event.pull_request.number || 0 }}
python-version: ${{ inputs.socket_python_version }}
cli-version: ${{ inputs.socket_cli_version }}
fail-on-findings: ${{ inputs.socket_fail_on_findings }}
sarif-file: ${{ inputs.socket_sarif_file }}
ignore-commit-files: ${{ inputs.socket_ignore_commit_files }}
dry-run: ${{ inputs.dry_run }}

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
69 changes: 67 additions & 2 deletions docs/js-pr-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ Umbrella reusable workflow for JavaScript/TypeScript repositories. A caller refe
2. **Change gate** — detects whether the PR touches anything beyond docs/meta (`src/config/non-doc-changes`); documentation-only PRs skip the heavy pipelines.
3. **Frontend analysis** — lint, typecheck, npm audit, tests, coverage and build (delegates to `frontend-pr-analysis.yml`), opt-in via `run_frontend_analysis`.
4. **Security scan** — Trivy, CodeQL, prerelease checks (delegates to `pr-security-scan.yml`), opt-in via `run_security`.
5. **Socket supply chain** — blocks malicious packages at install time and, optionally, runs the full Socket CLI report (`src/security/socket-firewall`, `src/security/socket-scan`). Enabled by default; disable with `run_socket: false`.

The `frontend-analysis` and `security` pipelines each have a `*-gate` aggregator job that exposes a single stable status-check name (`Frontend Analysis`, `Security`) for branch protection, regardless of the internal job names. Both are gated by the change detector, so documentation-only PRs skip them (and the aggregators still report success). If the change detector (`changes`) job itself fails, the aggregators propagate that failure instead of passing.
The `frontend-analysis`, `security` and `socket` pipelines each have a `*-gate` aggregator job that exposes a single stable status-check name (`Frontend Analysis`, `Security`, `Socket`) for branch protection, regardless of the internal job names. All are gated by the change detector, so documentation-only PRs skip them (and the aggregators still report success). If the change detector (`changes`) job itself fails, the aggregators propagate that failure instead of passing.

## Inputs

Expand All @@ -22,6 +23,7 @@ The `frontend-analysis` and `security` pipelines each have a `*-gate` aggregator
| `dry_run` | Preview metadata validations without posting comments/labels | boolean | `false` |
| `run_frontend_analysis` | Run the frontend analysis pipeline | boolean | `true` |
| `run_security` | Run the security scan pipeline | boolean | `true` |
| `run_socket` | Run the Socket supply-chain pipeline | boolean | `true` |
| `ignore_globs` | Space-separated globs treated as docs/meta for the change gate | string | `*.md docs/* .github/* LICENSE* .gitignore` |
| `pr_title_types` | Allowed commit types (pipe-separated) | string | `feat\|fix\|docs\|style\|refactor\|perf\|test\|chore\|ci\|build\|revert` |
| `pr_title_scopes` | Allowed scopes (pipe-separated, empty = any) | string | `''` |
Expand Down Expand Up @@ -78,6 +80,18 @@ The `frontend-analysis` and `security` pipelines each have a `*-gate` aggregator
| `codeql_languages` | CodeQL languages (comma-separated, e.g. `javascript-typescript`) | string | `''` |
| `ignore_file` | Path to Trivy ignore file (e.g. `.trivyignore.yaml`) | string | `''` |
| `trivy_skip_dirs` | Comma-separated directories to skip in every Trivy filesystem scan | string | `''` |
| `socket_enable_firewall` | Run Socket Firewall (free tier, no token) and install dependencies through it | boolean | `true` |
| `socket_enable_scan` | Run the Socket CLI scan (paid tier, needs `SOCKET_SECURITY_API_KEY`) | boolean | `false` |
| `socket_working_dir` | Directory holding the `package.json` and lockfile scanned by the Socket job | string | `.` |
| `socket_firewall_version` | Socket Firewall binary version | string | `latest` |
| `socket_job_summary` | Socket Firewall job summary verbosity (`all`, `errors`, `none`) | string | `all` |
| `socket_use_cache` | Cache the Socket Firewall binaries between runs (the `sfw` binary only) | boolean | `true` |
| `socket_fail_on_block` | Fail the Socket job when Socket Firewall blocks a package | boolean | `true` |
| `socket_fail_on_findings` | Fail the Socket job when the Socket CLI scan reports blocking alerts | boolean | `false` |
| `socket_sarif_file` | Path where the Socket CLI scan writes its SARIF report (empty = none) | string | `''` |
| `socket_ignore_commit_files` | Scan every manifest instead of only the ones touched by the commit | boolean | `false` |
| `socket_python_version` | Python version used to run the Socket CLI | string | `3.12` |
| `socket_cli_version` | `socketsecurity` release installed from PyPI (pinned; `latest` tracks the newest) | string | `2.5.8` |

> **Monorepo note:** `filter_paths`/`shared_paths`/`path_level`/`normalize_to_filter` scope the `frontend-analysis` job only. They are not passed to the `security` job because `frontend-pr-analysis.yml` and `pr-security-scan.yml` use different formats for that input (JSON array vs. newline-separated). For a path-scoped security scan too, call `pr-security-scan.yml` directly.

Expand All @@ -87,6 +101,7 @@ The `frontend-analysis` and `security` pipelines each have a `*-gate` aggregator
|--------|-------------|----------|
| `MANAGE_TOKEN` | Token for PR operations and private package access | No |
| `SLACK_WEBHOOK_URL` | Slack webhook for pipeline notifications | No |
| `SOCKET_SECURITY_API_KEY` | Socket API token for the Socket CLI scan (paid tier). Absent = the scan skips with a notice | No |

All other secrets required by the underlying primitives (e.g. `DOCKER_USERNAME`, `DOCKERHUB_IMAGE_PULL_TOKEN`, `NPMRC_TOKEN`) are forwarded automatically via `secrets: inherit`.

Expand Down Expand Up @@ -150,9 +165,59 @@ jobs:
secrets: inherit
```

## Socket supply chain

`npm audit`, Trivy and CodeQL find known CVEs and insecure code. None of them find a **supply-chain attack** — a package with a malicious install script, a typosquat, a dependency hijacked in a patch release. [Socket](https://socket.dev) covers that gap by analyzing package behavior, and it is wired here in two independent layers.

> Not to be confused with `socket.io`, the WebSocket library. Unrelated project, no scanning capability.

### Free tier — Socket Firewall (on by default)

[`src/security/socket-firewall`](../src/security/socket-firewall/README.md) installs Socket Firewall's free edition, which shims `npm`/`yarn`/`pnpm`, then runs the project's install through it. A malicious package makes the install exit non-zero and the `Socket` check goes red. No token, no account, no cost.

The shim only protects installs in the same job, so this runs a clean install of the same lockfile in the dedicated `socket` job. The 12 install steps inside `frontend-pr-analysis.yml` are not shimmed — the gate here is what blocks the PR.

**Monorepos:** the install needs a lockfile in `socket_working_dir` (default `.`). If none is found the layer skips with a warning instead of failing, so point it at the right directory:

```yaml
with:
socket_working_dir: 'ui'
```

Unlike `filter_paths`, this is a single directory — the Socket job is not matrixed per component. Repositories with several independently-locked apps should call the composite directly from their own matrixed job.

To report blocks as warnings instead of failing:

```yaml
with:
socket_fail_on_block: false
```

An install that fails for an ordinary reason (bad lockfile, unreachable registry) always fails the job — `socket_fail_on_block` only softens confirmed Socket blocks.

### Paid tier — Socket CLI scan (off by default)

[`src/security/socket-scan`](../src/security/socket-scan/README.md) runs `socketcli`, which posts the full alert report on the PR and enforces the organization's Socket policy. It needs the `SOCKET_SECURITY_API_KEY` secret; **without the secret it skips with a `::notice::` and the job stays green**, so enabling it early breaks nothing.

```yaml
with:
socket_enable_scan: true # opt-in
socket_fail_on_findings: false # default — advisory until the repo is clean
secrets: inherit # carries SOCKET_SECURITY_API_KEY
```

Socket API errors (`exit 3`) and unmet reachability prerequisites (`exit 5`) are always advisory — they say nothing about the dependencies under review.

### Turning the whole thing off

```yaml
with:
run_socket: false
```

## Branch protection

Require the aggregator checks `Frontend Analysis` and `Security` (plus the PR metadata checks from `pr-validation.yml`). These names are stable even when the underlying analysis steps change.
Require the aggregator checks `Frontend Analysis`, `Security` and `Socket` (plus the PR metadata checks from `pr-validation.yml`). These names are stable even when the underlying analysis steps change.

## Related

Expand Down
Loading
Loading