-
Notifications
You must be signed in to change notification settings - Fork 0
feat(js-pr-validation): add socket.dev supply chain gate #645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
4693ef8
cfe360f
f75d2fd
ee22bc5
77b3ad2
5b9ecc6
54f3c4d
bb8ca83
cde744a
7a33a1e
ef1c887
a778bc2
13d8d48
4a53572
4f08039
de9c860
43ac207
b9f61ce
52c6a81
651aa00
0f1afd5
e190d16
d5fa617
eacae6a
a301f93
817e47d
3ce2df2
b6365a2
6137cc4
ce54891
b38f781
87fffd0
b38a179
c7ad918
f850c85
7d39f39
10b45f7
95c6f70
aaf144c
c807994
b1aa4f4
81cc6bf
7b3255f
9f96d77
cbaa29e
471eb23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
|
|
||
| # ----------------- Change gate ----------------- | ||
| ignore_globs: | ||
|
|
@@ -272,6 +276,62 @@ 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 | ||
|
bedatty marked this conversation as resolved.
|
||
| 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_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 | ||
|
|
@@ -341,6 +401,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 }} | ||
|
|
@@ -417,6 +480,110 @@ jobs: | |
| result: ${{ needs.changes.result != 'success' && needs.changes.result || needs.security.result }} | ||
| label: Security | ||
|
|
||
| # ----------------- Socket Supply Chain ----------------- | ||
| # TEMPORARY: the two composite refs below point at this feature branch so the | ||
| # new actions resolve during end-to-end validation. Revert to @v1 before merge | ||
| # — the tag does not carry them yet, and the internal pinning policy requires | ||
| # a floating major tag for composites. | ||
| 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@feat/js-pr-validation-socket | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| 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@feat/js-pr-validation-socket | ||
| 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 }} | ||
|
|
||
| - name: Post Socket report to PR | ||
| if: always() && github.event_name == 'pull_request' && !inputs.dry_run | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| uses: LerianStudio/github-actions-shared-workflows/src/security/socket-reporter@feat/js-pr-validation-socket | ||
| with: | ||
| github-token: ${{ secrets.MANAGE_TOKEN || github.token }} | ||
| app-name: ${{ env.SOCKET_APP_NAME }} | ||
| firewall-enabled: ${{ inputs.socket_enable_firewall }} | ||
| firewall-blocked: ${{ steps.firewall.outputs.blocked || 'false' }} | ||
| firewall-exit-code: ${{ steps.firewall.outputs.install-exit-code || '0' }} | ||
| firewall-fail-on-block: ${{ inputs.socket_fail_on_block }} | ||
| app-gate-enabled: ${{ inputs.socket_enable_app_gate }} | ||
| app-findings-file: ${{ steps.app-gate.outputs.findings-file }} | ||
| app-fail-on-findings: ${{ inputs.socket_app_fail_on_findings }} | ||
| # 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. | ||
| - name: Gate - Fail on Socket findings | ||
| if: always() | ||
| env: | ||
| FIREWALL_OUTCOME: ${{ steps.firewall.outcome }} | ||
| APP_GATE_OUTCOME: ${{ steps.app-gate.outcome }} | ||
| run: | | ||
| FAILED="" | ||
| [ "$FIREWALL_OUTCOME" = "failure" ] && FAILED="$FAILED Socket-Firewall" | ||
| [ "$APP_GATE_OUTCOME" = "failure" ] && FAILED="$FAILED Socket-App-Gate" | ||
| 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." | ||
|
|
||
| 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 | ||
|
|
||
There was a problem hiding this comment.
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:
Repository: LerianStudio/github-actions-shared-workflows
Length of output: 8631
🏁 Script executed:
Repository: LerianStudio/github-actions-shared-workflows
Length of output: 35084
🏁 Script executed:
Repository: LerianStudio/github-actions-shared-workflows
Length of output: 50400
🏁 Script executed:
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 existingpinned-actionsvalidator checks pin format but does not update action versions. Bothsrc/security/socket-firewall/action.ymlandsrc/setup/setup-node-guarded/action.ymlreferenceSocketDev/action. Add a drift check that covers both files.🤖 Prompt for AI Agents