# Risk map — react/create-react-app

> Canonical page: https://codevetter.com/unpack/create-react-app/risk-map

# Risk map — react/create-react-app

Scanned commit 6254386531d263688ccfa542d0e628fbc0de0b28 (2025-02-14). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The highest-risk surfaces are process spawning during install (npm/yarn), the dev server's host check and proxy, env inlining, and eject rewriting package.json. Secrets are not stored in-repo; the dangerous pattern is REACT_APP_* being baked into the client bundle. Several code paths shell out to git. The project is in maintenance mode (v5.1.0) so dependency CVEs in webpack 5 / Jest 27 will linger unless backporting continues. Dead weight includes IE polyfill entrypoints and Flow leftovers.
- createReactApp.js spawns the package manager (npm, yarn, or pnpm when use-pnp) with user-influenced package specifiers (--scripts-version and --template). Specifiers are passed as arguments (not a shell string) in the spawn path, but a malicious --scripts-version file: URL or git URL can still execute that package's install scripts. This is inherent to any scaffolder. — [packages/create-react-app/createReactApp.js#L400-700](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/create-react-app/createReactApp.js#L400-L700)
- executeNodeScript writes a temporary JS file and runs it with the Node binary to invoke init.js, passing serialized arguments. The temp file is removed afterwards. If cwd or the template path were attacker-controlled beyond the CLI user, this is an arbitrary Node execution primitive — acceptable for a local CLI, unsafe if wrapped as a service. — [packages/create-react-app/createReactApp.js#L550-750](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/create-react-app/createReactApp.js#L550-L750)
- Dev server host check: allowedHosts is set to all when DANGEROUSLY_DISABLE_HOST_CHECK=true, which re-opens DNS-rebinding exposure against the webpack-dev-server. Proxy middleware (http-proxy-middleware) forwards to package.json proxy and can be abused if a malicious site is allowed to hit the dev server. sockHost/sockPath/sockPort (WDS_SOCKET_*) are also env-controlled. — [packages/react-scripts/config/webpackDevServer.config.js#L40-180](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/webpackDevServer.config.js#L40-L180) [packages/react-scripts/config/env.js#L80-130](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/env.js#L80-L130)
- env.js documents and implements that any REACT_APP_* variable is embedded into the JS bundle via DefinePlugin. Putting secrets in REACT_APP_ keys ships them to every browser. .env.local is loaded for development and production but intentionally skipped for test. — [packages/react-scripts/config/env.js#L1-130](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/env.js#L1-L130) [docusaurus/docs/adding-custom-environment-variables.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/adding-custom-environment-variables.md#L1-L40)
- init.js and eject.js invoke git (init, add, commit, status) through cross-spawn or execSync. A hostile git hook in an existing repo (eject) or a strange GIT_* environment can run code. eject refuses a dirty tree unless forced, which is a safety check not a security boundary. — [packages/react-scripts/scripts/init.js#L180-280](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/init.js#L180-L280) [packages/react-scripts/scripts/eject.js#L40-120](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/eject.js#L40-L120)
- HTTPS dev server: when HTTPS=true, start.js / webpackDevServer.config.js enables https. Certificate handling uses webpack-dev-server defaults (self-signed) unless SSL_CRT_FILE and SSL_KEY_FILE are set. Those paths are read from disk; a wrong path fails the start rather than falling back silently in the config that reads them. — [packages/react-scripts/config/webpackDevServer.config.js#L80-160](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/webpackDevServer.config.js#L80-L160) [packages/react-scripts/scripts/start.js#L80-160](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/start.js#L80-L160)
- ModuleScopePlugin and the image inline size limit are integrity features, not auth. There is no authentication layer anywhere: CRA generates static SPAs. Anyone who treats the dev server as an authenticated backend proxy inherits the proxy's lack of CSRF protection. — [packages/react-dev-utils/ModuleScopePlugin.js#L1-50](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-dev-utils/ModuleScopePlugin.js#L1-L50) [docusaurus/docs/proxying-api-requests-in-development.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/proxying-api-requests-in-development.md#L1-L40)
- Dependency blast radius is react-scripts/package.json: webpack, webpack-dev-server, Jest, babel, eslint, postcss, and workbox are pinned to the v5 line (webpack 5, Jest 27, ESLint 8). A vulnerability in webpack-dev-server affects every app that has not ejected. Ejected apps freeze a copy and stop receiving fixes. — [packages/react-scripts/package.json#L30-120](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/package.json#L30-L120) [packages/react-scripts/scripts/eject.js#L100-180](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/eject.js#L100-L180)
- IE compatibility code (react-app-polyfill/js/ie11.js and ie9) and confusing-browser-globals are legacy surfaces. They still ship because older generated apps import them. Changing the globals list is a breaking ESLint change for every consumer of eslint-config-react-app. — [packages/react-app-polyfill/package.json#L1-30](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-app-polyfill/package.json#L1-L30) [packages/confusing-browser-globals/index.js#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/confusing-browser-globals/index.js#L1-L40) [packages/eslint-config-react-app/index.js#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/eslint-config-react-app/index.js#L1-L40)
- eslint-config-react-app uses try/catch require.resolve to optionally enable TypeScript, Jest, and Testing Library rules. If those plugins are installed but at an incompatible major, ESLint crashes the build/start because CRACO-less CRA fails compilation on ESLint errors (ESLINT_NO_DEV_ERRORS can soften dev). That coupling is a frequent break when users upgrade plugins independently. — [packages/eslint-config-react-app/index.js#L60-180](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/eslint-config-react-app/index.js#L60-L180) [packages/react-scripts/config/webpack.config.js#L500-650](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/webpack.config.js#L500-L650)
- The docs site and the published README can drift from the code. available-scripts.md and adding-custom-environment-variables.md are the contract users trust. netlify.toml only publishes the website; a docs-only claim about runtime behavior must be checked against packages/react-scripts before editing code. — [docusaurus/docs/available-scripts.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/available-scripts.md#L1-L40) [README.md#L1-60](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/README.md#L1-L60) [netlify.toml#L1-25](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/netlify.toml#L1-L25)
- CI docker e2e is the only place the full behavior matrix runs. A change to webpack.config.js or env.js can pass unit tests and e2e-simple yet break typescript fixtures or PUBLIC_URL handling. Those fixtures are the regression net. (inferred) — [.github/workflows/build-and-test.yml#L60-140](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/.github/workflows/build-and-test.yml#L60-L140) [test/fixtures/typescript-typecheck/src/App.tsx#L1-20](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/test/fixtures/typescript-typecheck/src/App.tsx#L1-L20) [packages/react-scripts/config/env.js#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/env.js#L1-L40)
- No in-repo secret material was observed in the manifests or workflows read: no private keys, no production service credentials. Workflows use GitHub-hosted runners and standard checkout/setup-node. The risk is downstream (user apps embedding REACT_APP secrets), not this repo's own deploy tokens being hard-coded. — [.github/workflows/build-and-test.yml#L1-80](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/.github/workflows/build-and-test.yml#L1-L80) [.github/workflows/lint.yml#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/.github/workflows/lint.yml#L1-L40) [package.json#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/package.json#L1-L40)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
