facebook / react · Issue No. 37624
React DevTools standalone package: https://github.com/react/react/tree/main/packages/react-devtools
react-devtools@8.0.0 passes its configured host toreact-devtools-core/standalone.startServer(port, host). The default host is
documented as localhost, but the supplied value is not applied to the HTTP
listening socket.
Create an empty directory and install the current packages used by this
reproduction:
npm init -y
npm install react-devtools-core@8.0.0 jsdom@26.1.0
Save the following as bind-check.cjs:
'use strict';
const { JSDOM, VirtualConsole } = require('jsdom');
const net = require('node:net');
const os = require('node:os');
const dom = new JSDOM('<!doctype html><body></body>', {
pretendToBeVisual: true,
url: 'http://localhost',
virtualConsole: new VirtualConsole(),
});
dom.window.ResizeObserver = class {
observe() {}
unobserve() {}
disconnect() {}
};
for (const key of [
'window',
'document',
'navigator',
'HTMLElement',
'Element',
'Node',
'localStorage',
'sessionStorage',
]) {
global[key] = key === 'window'
? dom.window
: key === 'document'
? dom.window.document
: dom.window[key];
}
global.getComputedStyle = dom.window.getComputedStyle.bind(dom.window);
global.requestAnimationFrame = dom.window.requestAnimationFrame.bind(dom.window);
global.cancelAnimationFrame = dom.window.cancelAnimationFrame.bind(dom.window);
const nonLoopback = Object.values(os.networkInterfaces())
.flat()
.filter(Boolean)
.find(entry => entry.family === 'IPv4' && !entry.internal);
if (!nonLoopback) throw new Error('No non-loopback IPv4 address found');
const DevTools = require('react-devtools-core/standalone').default;
DevTools.setContentDOMNode(document.body);
const port = 18098;
const requestedHost = '127.0.0.1';
const server = DevTools.startServer(port, requestedHost);
function finish(code) {
server.close();
setTimeout(() => process.exit(code), 50);
}
setTimeout(() => {
const socket = net.connect(port, nonLoopback.address);
socket.on('connect', () => {
console.log(JSON.stringify({
requestedHost,
connectedVia: nonLoopback.address,
}));
socket.destroy();
finish(0);
});
socket.on('error', error => {
console.error(error);
finish(1);
});
}, 100);
setTimeout(() => finish(2), 5000);
Run:
node bind-check.cjs
Although startServer() was explicitly called with 127.0.0.1, the
connection through the same machine's non-loopback address succeeds:
{"requestedHost":"127.0.0.1","connectedVia":"<non-loopback IPv4>"}
The test makes only a local connection to the same machine.
Expected: passing 127.0.0.1 or localhost restricts the listening socket
to that host, as described by the API and standalone documentation.
Actual: the implementation calls httpServer.listen(port) without the
supplied host, so Node listens on an unspecified address.
A direct fix would be to forward the argument:
httpServer.listen(port, host, callback)
Environment used: macOS, Node.js 20.19.5.
Every time
No response
No response
No response
Relay reads this issue against the repository's contribution signals: the files it is likely to touch, how the maintainers triage work this size, and what the first contribution would exercise.
The full analysis for this issue is still being assembled. Until then, the description above and the thread on GitHub are the most reliable context.