So my team had the same issue, with the same error of options.allowedHosts[0] should be a non-empty string.
The solution we outline below is a very specific error and most likely does not pertain to many people.
In our case, the allowedHosts[0]
variable was undefined and we traced the allowedHosts[0]
variable to be equal to allowedHost
in node_modules\react-scripts\config\webpackDevServer.config.js
.
module.exports = function (proxy, allowedHost) {
const disableFirewall =
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true';
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
// https://github.com/webpack/webpack-dev-server/issues/887
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
// However, it made several existing use cases such as development in cloud
// environment or subdomains in development significantly more complicated:
// https://github.com/facebook/create-react-app/issues/2271
// https://github.com/facebook/create-react-app/issues/2233
// While we're investigating better solutions, for now we will take a
// compromise. Since our WDS configuration only serves files in the `public`
// folder we won't consider accessing them a vulnerability. However, if you
// use the `proxy` feature, it gets more dangerous because it can expose
// remote code execution vulnerabilities in backends like Django and Rails.
// So we will disable the host check normally, but enable it if you have
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
// Note: ["localhost", ".localhost"] will support subdomains - but we might
// want to allow setting the allowedHosts manually for more complex setups
allowedHosts: disableFirewall ? 'all' : [allowedHost],
urls.lanUrlForConfig
is passed in to the config file from node_modules\react-scripts\scripts\start.js
to allowedHost
.
const createDevServerConfig = require('../config/webpackDevServer.config');
...
createDevServerConfig(proxyConfig, urls.lanUrlForConfig)
urls.lanUrlForCofig
is produced by the prepareUrls
function in node_modules\react-dev-utils\WebpackDevServerUtils.js
.
const urls = prepareUrls(
protocol,
HOST,
port,
paths.publicUrlOrPath.slice(0, -1)
);
In the prepareUrls
function, urls.lanUrlForConfig
is set as undefined in the case that the computer's IPv4 address is non-private as seen below:
try {
// This can only return an IPv4 address
lanUrlForConfig = address.ip();
if (lanUrlForConfig) {
// Check if the address is a private ip
// https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
if (
/^10[.]|^172[.](1[6-9]|2[0-9]|3[0-1])[.]|^192[.]168[.]/.test(
lanUrlForConfig
)
) {
// Address is private, format it for later use
lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig);
} else {
// Address is not private, so we will discard it
lanUrlForConfig = undefined;
}
}
} catch (_e) {
// ignored
}
So in the end, we determined that the reason why we were having the error was because the ip address that we being pulled from the machine was non-private due to some ethernet cable configurations (We were getting a 169. address, an APIPA one, that was because the machine couldn't reach a DHCP server). This caused the urls.lanUrlForConfig
to be undefined, which would ultimately get passed all the way down to the allowedHosts[0] variable and cause the error.
Fixing the inability of not being able to connect to the DHCP server is another issue itself, but as a hotfix for development purposes only, we added a DANGEROUSLY_DISABLE_HOST_CHECK=true
into our .env
file and it worked fine after restarting the development server. Setting "allowedHosts": "all"
in our package.json was another solution.