Skip to content
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

Unrestricted directory traversal with @fs #2820

Closed
GrygrFlzr opened this issue Apr 2, 2021 · 14 comments · Fixed by #2850 or #3784
Closed

Unrestricted directory traversal with @fs #2820

GrygrFlzr opened this issue Apr 2, 2021 · 14 comments · Fixed by #2850 or #3784
Labels
p5-urgent Fix build-breaking bugs affecting most users, should be released ASAP (priority)

Comments

@GrygrFlzr
Copy link
Member

Describe the bug

The entire filesystem is indiscriminately exposed while the Vite dev server is running. Combined with the fact that the server is exposed to 0.0.0.0 by default, you're effectively opening your machine to the world during development.

This is technically a Vite feature as currently documented, but probably not actually intended.

Reproduction

Any Vite project will do.

npm init @vitejs/app app
cd app
npm install
npm run dev

Combined with the fact that any "out of root" directories already reveal the username of the current user, you can also easily do http://localhost:3000/@fs/home/username/.ssh/id_rsa

System Info

  System:
    OS: Windows 10 10.0.19042
    CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
    Memory: 19.47 GB / 31.95 GB
  Binaries:
    Node: 14.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 7.7.5 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 89.0.4389.114
    Edge: Spartan (44.19041.423.0), Chromium (89.0.774.63)
    Internet Explorer: 11.0.19041.1
  npmPackages:
    vite: ^2.1.5 => 2.1.5

Used package manager: npm

@GrygrFlzr GrygrFlzr added bug p5-urgent Fix build-breaking bugs affecting most users, should be released ASAP (priority) labels Apr 2, 2021
@haoqunjiang
Copy link
Member

This feature is used to solve problems in monorepos.
So I think we can expose an option to specify a workspace root (defaults to the project root) and restrict fs access beyond that directory.

@pngwn
Copy link

pngwn commented Apr 2, 2021

If we did want to support monorepos by default then various tools have their own way to find the root of the workspace:

As we can see this is a bit of a moving target (and there are more tools than these).yarn and pnpm are the most common as far as I am aware, those cases could be handled by default if this were deemed a 'good idea'.

I have no opinion on this as long as it is secure by default but leaving this info here in case it is useful.

@patak-dev
Copy link
Member

@marvinhagemeister I think this discussion may also be of interest for WMR. Maybe you already had similar talks about how to tackle the security implications of opening the dev server.

@marvinhagemeister
Copy link
Contributor

marvinhagemeister commented Apr 2, 2021

@patak-js Yes, indeed this is something I've been pondering a lot about and it was one of the reason we didn't add an @fs loader to WMR. Any request made to the dev server is user input and therefore is deemed unsafe and needs to be sanitized/normalized accordingly.

In our case we limit file serving to the web root for now. We're planning to expand that to include aliased directories in the future. So we'd essentially have an array of allowed folders to load files from.

Just before loading we normalize the path and check if the resolved path leads to a file inside one of those include directories (which is currently just the web root). If it it does indeed lies somewhere in those folders, we serve it and error if it does not.

@patak-dev
Copy link
Member

Thanks for the explanation. I like the idea of having web root + support for monorepos by default as @pngwn suggested (at least for common tools), and an array of allowed folders to manually cover the rest of the cases like it is done in WMR

@antfu
Copy link
Member

antfu commented Apr 4, 2021

Drafted a PR, #2820

Not sure if we should do the auto-detection, which could be a bit untransparent for users as the behavior would change based on users' environments. For example, having on package.json with workspace accidentally on your ~/ will still unsafely expose /@fs/home/username/.ssh/id_rsa and others. So, I'd think maybe it's better to strict by default and let users configure for monorepo setup explicitly.

@dominikg
Copy link
Contributor

dominikg commented Apr 5, 2021

Some thoughts:

  • Are there additional files inside root that need to be protected? eg. .env files that could contain serverside secrets?
  • Could the module graph / entries list be used to limit responses to files that are actually somehow attached to the vite server?
  • Do we need to protect against malicious modules trying to import known files and sending them off to a remote server?

@patak-dev
Copy link
Member

I think that #2850 is a good first step, and should be considered a fix for this issue. But I agree with @dominikg that further changes are needed

  • Are there additional files inside root that need to be protected? eg. .env files that could contain serverside secrets?
  • Could the module graph / entries list be used to limit responses to files that are actually somehow attached to the vite server?

This is a good idea. There is also a related issue #2587 so publicDir overrides the default public root in dev mode. I think we should only serve from the public directory for absolute paths and allow /@fs/ access only for imported files (also taking into account glob imports)

  • Do we need to protect against malicious modules trying to import known files and sending them off to a remote server?

How would you achieve something like this?

@dominikg
Copy link
Contributor

dominikg commented Apr 5, 2021

How would you achieve something like this?

Good question. A set of allow and deny list checks in the import analysis plugin and prohibiting imports that are not passing?
Or maybe an extra security/validation plugin that tests all ids for bad ones?

@antfu
Copy link
Member

antfu commented Apr 5, 2021

Do we need to protect against malicious modules trying to import known files and sending them off to a remote server?

I kinda think this is out-of-scope of Vite, developers should take the responsibility to use malicious modules. And we don't actually have the ability to completely prevent it as every node modules are capable of doing such things if they want.

eirslett added a commit to eirslett/vite that referenced this issue Apr 5, 2021
…default

See also vitejs#2820 which makes this problem critically worse.

Up until now, Vite has been listening on all public IP addresses
by default, which could be a potential security vulnerability.

This fixes the default behavior, so Vite only listens on 127.0.0.1.

You can get the old behavior back (listen to all IPs) by running
with the --listen-public CLI flag, or setting

```
export default defineConfig({
  server: {
    listenPublic: true
  }
  // ... more config here
})
```

in the Vite config file.
eirslett added a commit to eirslett/vite that referenced this issue Apr 12, 2021
…default

See also vitejs#2820 which makes this problem critically worse.

Up until now, Vite has been listening on all public IP addresses
by default, which could be a potential security vulnerability.

This fixes the default behavior, so Vite only listens on 127.0.0.1.

You can get the old behavior back (listen to all IPs) by running
with the --listen-public CLI flag, or setting

```
export default defineConfig({
  server: {
    listenPublic: true
  }
  // ... more config here
})
```

in the Vite config file.
@ElMassimo
Copy link
Contributor

ElMassimo commented Apr 26, 2021

Sharing a piece of information we've discussed with @patak-js a few times, but I forgot to add it here.


In a Vite Ruby project structure, vite.config.ts is at the project root while Vite's root targets an inner directory such as app/frontend/entrypoints.

The library leverages the fact that Vite can serve files in app/frontend, that is, outside of the root.

If the fix uses the location of package.json or the location of vite.config.ts to determine the root of the workspace (if failing to detect a mono repo), it wouldn't break Vite Ruby projects.

@Mlocik97
Copy link

Mlocik97 commented May 1, 2021

@ElMassimo is there no way to do that, you detect all package.json and vite.config.ts (also in parents directories), and allow serve only directories that contain these files or are subfolder of folder that contain this files, and just omit all folders and files that doesn't contain this file and are not subfolder of folder containing these files?

Or when I think about it, monorepo is just repo, so why not find .git folder?

antfu added a commit that referenced this issue May 7, 2021
Co-authored-by: Shinigami <chrissi92@hotmail.de>
Co-authored-by: patak <matias.capeletto@gmail.com>
fi3ework pushed a commit to fi3ework/vite that referenced this issue May 22, 2021
Co-authored-by: Shinigami <chrissi92@hotmail.de>
Co-authored-by: patak <matias.capeletto@gmail.com>
@antfu antfu reopened this Jun 19, 2021
@antfu
Copy link
Member

antfu commented Jun 19, 2021

Bring back for the record

@github-actions
Copy link

This issue gets locked because it has been closed for more than 14 days.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
p5-urgent Fix build-breaking bugs affecting most users, should be released ASAP (priority)
Projects
None yet
9 participants