Why does a chromedriver started by Selenium refuse HTTP requests from another machine, and what changes that?
answer
- The port is unauthenticated remote control
- Loopback is the only real boundary
- Widening it is a security decision
- Chromium names addresses, Firefox names hosts
- allowed-ips takes a comma-separated list
basics
~20 sThe driver executable listens on loopback and rejects non-local clients by default, because anyone who can reach it can drive a browser on that machine. ChromeDriver's --allowed-ips, and geckodriver's --host with --allow-hosts, open it deliberately.
solid answer
~40 sA driver's HTTP port is an unauthenticated remote-control surface: whoever can post to it can open a session, navigate anywhere, run scripts and read what the browser can read. So chromedriver and geckodriver bind to the local loopback interface and refuse requests from other hosts unless you say otherwise. In Selenium 4's Java bindings you widen that on the Chromium-based services through `withAllowedListIps(String)`, which becomes chromedriver's `--allowed-ips` with a comma-separated list of permitted remote addresses; geckodriver's equivalents are `--host` for the bind address and `--allow-hosts` for the permitted Host headers. Widen it only for a specific address on a trusted network, never to everything, and remember the driver still has no authentication of its own.
code
java · 14 linesChromeDriverService service = new ChromeDriverService.Builder()
.usingPort(9515)
.withAllowedListIps("10.4.19.7")
.build();
service.start();
System.out.println(service.getUrl());
try {
WebDriver driver = new RemoteWebDriver(service.getUrl(), new ChromeOptions());
driver.get("https://lims.internal.example/samples");
driver.quit();
} finally {
service.stop();
}go deeper
Recall that a driver started locally is reachable only from that machine by default, and that a connection from elsewhere is refused rather than failing with an authorisation message.
Explain the reason for the default and name the mechanism that changes it, including that the allow-list takes specific addresses rather than a blanket setting.
Show the risk assessment: an unauthenticated remote-control surface, the network as the only boundary, a named allow-list of one, and a widened service that is stopped when the run ends.
Own the rule for the organisation on when a driver may be exposed beyond loopback at all, and steer teams toward the fleet arrangement instead of hand-widened driver processes.
## What an open driver port would let anyone do A driver process is a remote-control server with **no authentication**. Anything that can send it HTTP can `POST /session`, get a browser, navigate it, execute scripts in the page, read cookies and local storage, and interact with whatever that machine's browser is allowed to reach — including internal systems such as a laboratory sample-tracking application that trusts the host's network position. There is no password, no token and no allow-list of pages. The only protection the driver has is **who can reach the socket at all**. That is why the interesting default here is a security default, not a convenience one. ## The default: local only - chromedriver and msedgedriver bind their HTTP server to the **loopback interface** and reject connections from other hosts unless told otherwise. - geckodriver behaves the same way, listening on the local address by default. - Nothing about this changes when Selenium launches the process: the service's job is the command line and the port, and the local-only default comes from the executable itself. - The practical consequence is the one people hit first — a driver started on one machine is simply unreachable from another, and the failure looks like a connection refused rather than an authorisation message. ## The flags that widen it | | Chromium-based drivers (chromedriver, msedgedriver) | geckodriver | |---|---|---| | Permit named remote clients | `--allowed-ips` with a comma-separated list | `--allow-hosts` for permitted Host headers | | Bind address | widened as a consequence of allowing remote IPs | `--host` | | Origin header control | `--allowed-origins` | `--allow-origins` | | Java builder call | `withAllowedListIps(String)` on the service builder | set through the geckodriver arguments | The header-oriented flags exist for a second, subtler threat: a page open in an ordinary browser on the same machine could otherwise be scripted into sending requests to `localhost` and driving the driver from inside. Restricting acceptable `Host` and `Origin` values closes that door, which is why the modern drivers ship those checks on by default rather than leaving them to you. ## Doing it deliberately If a driver genuinely has to be reachable from another host: 1. **Name the addresses.** Pass the specific client addresses to `--allowed-ips` rather than anything that means "everyone". An allow-list of one is the normal correct size. 2. **Pin the port** so the address is known and can be reasoned about, rather than changing on every run. 3. **Keep it on a trusted network segment.** The driver has no authentication of its own, so the network is the only boundary you actually have. 4. **Scope it in time.** Start the widened service for the run that needs it and stop it afterwards — a widened driver left running is a much worse orphan than a loopback-only one. ## What this is not This is about a single driver process on a single host and the flags that control who may talk to it. Running a fleet of browsers behind Selenium's Grid, or in containers, is a different arrangement with its own components and its own configuration, and reaching for `--allowed-ips` is not a way to build one. If the requirement is "several machines run browsers for one suite", the honest answer in an interview is that the driver flag is the wrong tool and the fleet arrangement is the right one. ## The symptom, when it bites The first encounter with this default is almost always a confusing one. A driver runs happily on the machine that started it, and a client on another host gets a refused connection with nothing explaining why. Nothing has crashed, the process is healthy, the suite works when run locally, and the driver's own log may show no trace of the attempt at all — because the request never reached anything that would log it. Recognising that shape saves an afternoon of chasing the wrong cause: a driver that answers locally and refuses remotely is behaving exactly as designed, and the real question is whether you should widen it, not why it broke. ## The answer an interviewer is listening for Two halves. First, the **reason**: an unauthenticated remote-control surface is exactly the thing you do not expose by default, and the driver's authors chose loopback rather than trusting every deployment to lock it down. Second, the **mechanism**: the flag exists, it is named, it takes specific addresses, and turning it on is a deliberate decision with a blast radius rather than a checkbox. A candidate who names only the flag has learned a workaround; a candidate who explains why the default is closed has understood what the driver is.
- Why do the drivers also check the Host and Origin headers, not just the client address?Because a page loaded in an ordinary browser on the same machine can send requests to localhost, which passes any address-based check. Restricting the acceptable Host and Origin values stops a hostile page from driving a local driver through the victim's own browser, a class of attack that an IP allow-list alone cannot see.
- What would you say to a team that sets the allow-list to everything to make a run work?That they have turned a test tool into an open remote-control endpoint on that network. The driver has no authentication, so anyone reaching the port gets a browser on that host with its network access. Name the specific client address instead, keep the service alive only for the run, and if the real need is many machines, use the fleet arrangement built for it.
saying these in an interview costs you the question
- Believing the driver authenticates its callers in some way
- Opening the allow-list to everything to make a run pass
- Assuming a remote connection failure means the driver crashed
- Confusing the driver's port with the browser's own debugging port
- Thinking Selenium, not the executable, imposes the local-only default