Skip to content

fix(sf-core-installer): remove axios and harden dependencies against supply chain attacks#13450

Merged
czubocha merged 6 commits intomainfrom
remove-axios-from-installer
Mar 31, 2026
Merged

fix(sf-core-installer): remove axios and harden dependencies against supply chain attacks#13450
czubocha merged 6 commits intomainfrom
remove-axios-from-installer

Conversation

@czubocha
Copy link
Copy Markdown
Contributor

@czubocha czubocha commented Mar 31, 2026

Summary

Reduces the serverless npm package (sf-core-installer) supply chain attack surface by removing unnecessary dependencies, pinning versions, and adding min-release-age protection.

Changes

1. Replace axios with fetch + undici (binary.js, package.json)

  • axios was used for a single HTTP GET to download the binary installer. Replace with Node built-in fetch() and undici.ProxyAgent for proxy support.
  • Proxy env var detection (HTTPS_PROXY, HTTP_PROXY, NO_PROXY with hostname/suffix/port matching) inlined from axios-proxy-builder logic.
  • Eliminates 3 third-party packages (axios, axios-proxy-builder, tunnel) from the published dependency tree.
  • res.ok check added — fetch() doesn't throw on non-2xx responses unlike axios, so without this a 404 would silently write an error page as the binary.
  • Proxy detection moved inside Binary.install() — previously the run() code path never applied proxy config. Proxy now works for both postInstall and run entry points.

2. Remove unused xml2js (package.json)

  • xml2js was listed as a dependency but never imported or required anywhere in the installer.

3. Pin dependency versions and add min-release-age (package.json, .npmrc)

  • Pin rimraf and undici to exact versions (5.0.10, 6.24.1) to prevent npm from resolving to a potentially compromised newer version.
  • Add min-release-age=3 to .npmrc — aligns local npm install with the existing Dependabot cooldown policy (3 days for patches). Prevents npm from resolving to package versions published less than 3 days ago.

Summary by CodeRabbit

  • Bug Fixes

    • Improved HTTP error detection and reporting during binary downloads for more reliable failure handling
  • Chores

    • Streamlined installer networking and proxy handling, reducing external dependency surface
    • Switched downloads to a simpler fetch-and-write approach for more robust installation behavior
    • Bumped minimum Node.js engine requirement
  • Configuration

    • Added an npm config entry introducing a minimum package release age constraint
  • Documentation

    • Minor whitespace cleanup in provider documentation

Note

Medium Risk
Changes the sf-core-installer binary download and proxy handling path, which could affect installs in proxied or restricted environments. Dependency removals/pinning reduce supply-chain exposure but may surface compatibility issues if the new proxy/HTTP behavior differs.

Overview
Reduces the sf-core-installer published dependency surface by removing axios, axios-proxy-builder, tunnel, and unused xml2js, and by pinning remaining deps (rimraf, undici) plus aligning the lockfile (also pins @aws-sdk/client-sso-oidc).

Reworks binary download in binary.js to use Node fetch() with undici’s ProxyAgent, adds explicit non-2xx handling, and inlines HTTP(S)_PROXY/NO_PROXY parsing so proxy behavior is applied during installation. Adds .npmrc min-release-age=3 to avoid resolving very recently published versions, and makes a small docs formatting tweak.

Written by Cursor Bugbot for commit cda53ec. This will update automatically on new commits. Configure here.

czubocha and others added 3 commits March 31, 2026 18:33
…upply chain risk

axios and axios-proxy-builder were used for a single HTTP GET to
download the binary installer. Replace with built-in fetch() and
undici.ProxyAgent for proxy support. This eliminates 3 third-party
dependencies (axios, axios-proxy-builder, tunnel) from the published
npm package, reducing exposure to supply chain attacks like the
compromised axios@1.14.1.

Proxy behavior (HTTPS_PROXY, HTTP_PROXY, NO_PROXY) verified equivalent
across 13 e2e test cases against a real local proxy server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
xml2js was never imported or required anywhere in the installer code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pin rimraf and undici to exact versions in sf-core-installer to prevent
npm from resolving to a potentially compromised newer version.

Add min-release-age=3 to .npmrc to align local npm install with the
existing Dependabot cooldown policy (3 days for patches). This prevents
npm from resolving to package versions published less than 3 days ago.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mmarzex
Copy link
Copy Markdown
Contributor

Mmarzex commented Mar 31, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f37fb65-c170-430a-afc9-0120379299ab

📥 Commits

Reviewing files that changed from the base of the PR and between cda53ec and 9c4831b.

📒 Files selected for processing (1)
  • packages/sf-core-installer/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/sf-core-installer/package.json

📝 Walkthrough

Walkthrough

Replaced Axios-based downloads and external proxy config with undici's ProxyAgent and internal NO_PROXY/HTTP_PROXY handling in the core installer. Binary API signatures simplified (removed fetchOptions); downloads now use fetch(...).arrayBuffer() and synchronous write to disk. Added .npmrc min-release-age = 3.

Changes

Cohort / File(s) Summary
NPM Configuration
\.npmrc
Added min-release-age = 3 setting.
Core Installer - runtime & deps
packages/sf-core-installer/package.json
Removed axios, axios-proxy-builder, xml2js; added undici@6.24.1; pinned rimraf to 5.0.10; raised engines.node minimum to >=18.17.0.
Core Installer - implementation
packages/sf-core-installer/binary.js
Replaced Axios streaming with undici fetch + ProxyAgent; added local NO_PROXY/HTTP_PROXY selection and bypass logic (hostname/port/wildcard); simplified Binary.install/Binary.run signatures (removed fetchOptions); switched to fetch(...).arrayBuffer() and writeFileSync with explicit HTTP status checks; removed top-level proxy configure call.
Docs minor
docs/sf/providers/aws/guide/services.md
Removed a trailing blank line (minor whitespace change).

Sequence Diagram(s)

sequenceDiagram
  rect rgba(200,200,255,0.5)
  participant CLI as Installer (Binary)
  end
  rect rgba(200,255,200,0.5)
  participant ProxySel as ProxySelector (env NO_PROXY / HTTP(S)_PROXY)
  end
  rect rgba(255,200,200,0.5)
  participant Remote as Remote Server
  end
  rect rgba(255,255,200,0.5)
  participant FS as Filesystem
  end

  CLI->>ProxySel: determine proxy for download URL
  ProxySel-->>CLI: return ProxyAgent or direct
  CLI->>Remote: fetch(url) using undici + ProxyAgent
  Remote-->>CLI: HTTP response (status, body)
  CLI->>CLI: if !res.ok -> throw error
  CLI->>FS: writeFileSync(arrayBuffer, mode=0o755)
  FS-->>CLI: file persisted
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I sniff the env, I hop and pry,
I choose a proxy, or bid it goodbye,
I fetch the bytes and set them free,
I write with a hop — executable, happy me! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changes: removing axios and hardening dependencies against supply chain attacks, which aligns with the core objectives of dependency reduction and security improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch remove-axios-from-installer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 06752b8923

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/sf-core-installer/binary.js (1)

158-166: ⚠️ Potential issue | 🟠 Major

Unreachable cleanup: removeBinary() never executes after error().

The error() function calls process.exit(1), so the subsequent this.removeBinary() calls on lines 160 and 165 are unreachable. The same issue exists in the .catch() block at line 190.

🐛 Proposed fix to ensure cleanup runs before exit
     process.on('SIGINT', () => {
-      error('Could not download Serverless')
       this.removeBinary()
+      error('Could not download Serverless')
     })

     process.on('SIGTERM', () => {
-      error('Could not download Serverless')
       this.removeBinary()
+      error('Could not download Serverless')
     })

And in the catch block:

       .catch((e) => {
-        error(`Error fetching release: ${e.message}`)
         this.removeBinary()
+        error(`Error fetching release: ${e.message}`)
       })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sf-core-installer/binary.js` around lines 158 - 166, The error
handler calls error(...) which calls process.exit(1) before this.removeBinary(),
making cleanup unreachable; move the cleanup to run before exiting by invoking
this.removeBinary() (and await it if removeBinary returns a Promise) inside the
process.on('SIGINT') and process.on('SIGTERM') handlers, then call error(...)
only after cleanup completes; apply the same change in the .catch(...) block
where error(...) is called so that removeBinary() runs (and is awaited if async)
prior to exiting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/sf-core-installer/package.json`:
- Around line 23-26: Package.json currently pins "rimraf":"5.0.10" which pulls
in vulnerable glob@10.4.5 (CVE-2025-64756); update the dependency or add an
override to ensure glob >= 10.5.0. Fix by either bumping rimraf to a release
that depends on glob 10.5.0+ (update the "rimraf" version in package.json) or
add an npm/yarn/pnpm override entry that pins "glob" to ">=10.5.0" (or a
specific safe version) so the transitive dependency is forced to the
non-vulnerable release; reference the "rimraf" entry in package.json and the
project’s package manager override configuration to implement the change.

---

Outside diff comments:
In `@packages/sf-core-installer/binary.js`:
- Around line 158-166: The error handler calls error(...) which calls
process.exit(1) before this.removeBinary(), making cleanup unreachable; move the
cleanup to run before exiting by invoking this.removeBinary() (and await it if
removeBinary returns a Promise) inside the process.on('SIGINT') and
process.on('SIGTERM') handlers, then call error(...) only after cleanup
completes; apply the same change in the .catch(...) block where error(...) is
called so that removeBinary() runs (and is awaited if async) prior to exiting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2ac95a30-7e31-42c6-bfa6-16940133f48c

📥 Commits

Reviewing files that changed from the base of the PR and between 9f6d4a0 and 06752b8.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • .npmrc
  • packages/sf-core-installer/binary.js
  • packages/sf-core-installer/package.json

@serverless serverless deleted a comment from coderabbitai bot Mar 31, 2026
@czubocha
Copy link
Copy Markdown
Contributor Author

@cursor review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cda53ece04

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Align with undici@6.24.1 which requires node >=18.17.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@czubocha czubocha merged commit b16cf3e into main Mar 31, 2026
12 checks passed
@czubocha czubocha deleted the remove-axios-from-installer branch March 31, 2026 18:03
@github-actions github-actions bot locked and limited conversation to collaborators Mar 31, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants