Skip to content

fix(dev): prevent X-Forwarded-For spoofing on Unix socket VFS access#4114

Open
nyxsky404 wants to merge 2 commits intonitrojs:mainfrom
nyxsky404:fix/vfs-unix-socket-security
Open

fix(dev): prevent X-Forwarded-For spoofing on Unix socket VFS access#4114
nyxsky404 wants to merge 2 commits intonitrojs:mainfrom
nyxsky404:fix/vfs-unix-socket-security

Conversation

@nyxsky404
Copy link

🔗 Linked issue
#4103

❓ Type of change

  • 🐞 Bug fix (a non-breaking change that fixes a security issue)

📚 Description
This PR fixes a security vulnerability where the VFS handler trusted the X-Forwarded-For header when running on a Unix socket behind a reverse proxy.

The vulnerability:
When NITRO_UNIX_SOCKET is used, the code passed { xForwardedFor: isUnixSocket } to getRequestIP(). An attacker behind a reverse proxy could send X-Forwarded-For: 127.0.0.1 to satisfy the localhost check and access VFS content (application source code).

The fix:

  1. Never trust X-Forwarded-For for VFS access - it's attacker-controlled
  2. Deny access on Unix socket entirely since IP cannot be reliably determined

📝 Checklist

  • I have linked an issue or discussion.
  • I have added tests (4 new security tests)
  • I have run pnpm format and pnpm typecheck

Deny VFS access when running on Unix socket since IP cannot be reliably
determined. Never trust X-Forwarded-For header for this security-sensitive
endpoint.

Fixes nitrojs#4103
@nyxsky404 nyxsky404 requested a review from pi0 as a code owner March 16, 2026 06:38
@vercel
Copy link

vercel bot commented Mar 16, 2026

@nyxsky404 is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 542e85e7-ee91-4777-8781-7d9e5a294493

📥 Commits

Reviewing files that changed from the base of the PR and between b5339d1 and 4c31de4.

📒 Files selected for processing (2)
  • src/dev/vfs.ts
  • test/unit/vfs-security.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/unit/vfs-security.test.ts
  • src/dev/vfs.ts

📝 Walkthrough

Walkthrough

Disable X-Forwarded-For usage for VFS IP detection and add explicit 403 rejection for requests arriving via Unix sockets; add unit tests covering Unix-socket and network-socket VFS access denial scenarios.

Changes

Cohort / File(s) Summary
VFS Security Implementation
src/dev/vfs.ts
Always call request IP detection with xForwardedFor: false for VFS access and add early denial: throw HTTPError 403 "VFS access not available on Unix socket" when the request socket is a Unix socket.
VFS Security Tests
test/unit/vfs-security.test.ts
Add unit tests and mocks for Unix vs network sockets and mock Nitro/event factories to assert VFS handler rejects Unix-socket requests and rejects untrusted/non-local IPs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title follows conventional commits format with 'fix' prefix and clearly describes the security fix for VFS access on Unix sockets.
Description check ✅ Passed The description is directly related to the changeset, explaining the security vulnerability, the fix, and linking to issue #4103 with test coverage details.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

Migrating from UI to YAML configuration.

Use the @coderabbitai configuration command in a PR comment to get a dump of all your UI settings in YAML format. You can then edit this YAML file and upload it to the root of your repository to configure CodeRabbit programmatically.

Copy link

@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.

🧹 Nitpick comments (2)
src/dev/vfs.ts (1)

17-20: Remove explanatory inline comments in this block to match repo style.

These two comments describe the code action/rationale inline; this file pattern prefers self-explanatory code without such line comments.

💡 Minimal style-only diff
-    // Never trust X-Forwarded-For for VFS access - it's attacker-controlled
     const ip = getRequestIP(event, { xForwardedFor: false });

-    // Deny access on Unix socket since IP cannot be reliably determined
     if (isUnixSocket) {
       throw new HTTPError({
As per coding guidelines: `src/**/*.{ts,js}`: "Do not add comments explaining what the line does unless prompted".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/dev/vfs.ts` around lines 17 - 20, Remove the two explanatory inline
comments above the getRequestIP call so the code follows the repo style;
specifically delete the comment "Never trust X-Forwarded-For for VFS access -
it's attacker-controlled" and the comment "Deny access on Unix socket since IP
cannot be reliably determined" and leave the call to getRequestIP(event, {
xForwardedFor: false }) and the ip variable as-is (referencing getRequestIP,
event, xForwardedFor, and ip to locate the lines).
test/unit/vfs-security.test.ts (1)

56-61: Deduplicate repeated Nitro fixture setup across tests.

mockNitro is rebuilt four times with identical shape; extracting one helper will make the suite easier to evolve.

♻️ Suggested cleanup
+function createMockNitro() {
+  return {
+    options: { rootDir: "/test/root" },
+    vfs: new Map([["/test/root/test.js", { render: () => "test content" }]]),
+  } as unknown as Nitro;
+}
+
 describe("VFS Security - X-Forwarded-For spoofing on Unix socket", () => {
   it("should reject requests with spoofed X-Forwarded-For header on Unix socket", async () => {
-    const mockNitro = {
-      options: {
-        rootDir: "/test/root",
-      },
-      vfs: new Map([["/test/root/test.js", { render: () => "test content" }]]),
-    } as unknown as Nitro;
+    const mockNitro = createMockNitro();
@@
   it("should reject requests without X-Forwarded-For on Unix socket", async () => {
-    const mockNitro = {
-      options: {
-        rootDir: "/test/root",
-      },
-      vfs: new Map([["/test/root/test.js", { render: () => "test content" }]]),
-    } as unknown as Nitro;
+    const mockNitro = createMockNitro();
@@
   it("should reject requests from non-local IP on regular network socket", async () => {
-    const mockNitro = {
-      options: {
-        rootDir: "/test/root",
-      },
-      vfs: new Map([["/test/root/test.js", { render: () => "test content" }]]),
-    } as unknown as Nitro;
+    const mockNitro = createMockNitro();
@@
   it("should NOT trust X-Forwarded-For header on regular network socket", async () => {
-    const mockNitro = {
-      options: {
-        rootDir: "/test/root",
-      },
-      vfs: new Map([["/test/root/test.js", { render: () => "test content" }]]),
-    } as unknown as Nitro;
+    const mockNitro = createMockNitro();

Also applies to: 76-81, 94-99, 112-117

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/vfs-security.test.ts` around lines 56 - 61, Extract the repeated
mockNitro construction into a single test helper (e.g., makeMockNitro or
getMockNitro) that returns the typed Nitro fixture used in tests; replace each
inline const mockNitro = { options: { rootDir: "/test/root" }, vfs: new
Map([["/test/root/test.js", { render: () => "test content" }]]) } as unknown as
Nitro with calls to that helper in all test cases (the occurrences around lines
56, 76, 94, 112), ensuring the helper exports or is declared in the test file
scope and preserves the same shape and typing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/dev/vfs.ts`:
- Around line 17-20: Remove the two explanatory inline comments above the
getRequestIP call so the code follows the repo style; specifically delete the
comment "Never trust X-Forwarded-For for VFS access - it's attacker-controlled"
and the comment "Deny access on Unix socket since IP cannot be reliably
determined" and leave the call to getRequestIP(event, { xForwardedFor: false })
and the ip variable as-is (referencing getRequestIP, event, xForwardedFor, and
ip to locate the lines).

In `@test/unit/vfs-security.test.ts`:
- Around line 56-61: Extract the repeated mockNitro construction into a single
test helper (e.g., makeMockNitro or getMockNitro) that returns the typed Nitro
fixture used in tests; replace each inline const mockNitro = { options: {
rootDir: "/test/root" }, vfs: new Map([["/test/root/test.js", { render: () =>
"test content" }]]) } as unknown as Nitro with calls to that helper in all test
cases (the occurrences around lines 56, 76, 94, 112), ensuring the helper
exports or is declared in the test file scope and preserves the same shape and
typing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2d476b7b-a0b9-45e7-8950-d618c567a15d

📥 Commits

Reviewing files that changed from the base of the PR and between c31268c and b5339d1.

📒 Files selected for processing (2)
  • src/dev/vfs.ts
  • test/unit/vfs-security.test.ts

- Remove explanatory inline comments in vfs.ts per repo style
- Extract createMockNitro helper to deduplicate test fixtures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant