Which of your hostnames does a hosted browser provider's tunnel carry, and what happens to the rest?
answer
- a tunnel is not an on switch
- it carries a set of names
- what is outside the set still loads
- loading is not the same as reaching
- assert something only your host shows
basics
~20 sA tunnel carries traffic for a defined set of names; anything outside that set the remote browser fetches the ordinary way. The danger is silence: an unlisted internal name can resolve publicly and the test passes against the wrong site.
solid answer
~50 sA tunnel is not a switch that puts the whole remote browser inside your network. It carries traffic for a **set of names**, and that set is a decision somebody makes. Send everything through it and every request the browser makes — public pages, fonts, third-party scripts — travels back through your network and leaves by your egress, so your outbound rules now govern the run and a stutter on your side breaks requests that had nothing to do with your application. Send only listed names and everything else is fetched directly, which is narrower and faster but silent when an entry is missing. That is the failure worth planning for: a payroll portal's branch staging host left out of the set resolves to whatever answers publicly, and a run that loads *something* can go green against the wrong target.
go deeper
Know that a tunnel carries only the names it was told to carry. If a run reports that a page loaded but the content looks like the public site, suspect the routed set before you suspect the test.
Be able to argue both ends of the scope decision: routing everything puts your egress and your outbound rules in the path of every request, while routing a list leaves an unlisted name to be fetched from outside.
Expect the silent-pass scenario. Show that you would make the first assertion of the run prove the target's identity, so a page fetched from the wrong place fails loudly rather than scoring green.
You will be asked how the routed set stays correct when staging hosts are created per branch. Argue for deriving it from the same source that creates those hosts, so the list cannot be forgotten as a separate chore.
## A tunnel is a route for names, not a mode for the browser The common mental model is that starting a tunnel puts the rented browser *inside* your network. It does not. The browser stays where it is, on somebody else's machine, and a tunnel gives it a way to reach a **set of names** that would otherwise resolve to nothing useful from out there — in this case a payroll portal whose staging host is built per branch and published nowhere public. Which names are in that set is a decision somebody makes, and it is separate from which tunnel a session attaches to. A session can attach to exactly the right tunnel and still be unable to reach the host it came for, because that host was never in the routed set. Diagnosing the two together is why these problems take a morning; they fail independently and should be ruled out one at a time. ## The two ends of the scope decision | | Everything through the tunnel | Only listed names through it | |---|---|---| | Where public requests go | back through your network, out by your egress | fetched directly by the far side | | What governs them | your outbound rules and filtering | the provider's own network | | If your path stutters | every request in the run is affected | only the internal ones are | | A missing entry costs | nothing; there is no list to miss | silence: the name is fetched from outside | | What the run resembles | a browser sitting on your network | a browser outside, with a door to a few hosts | Neither column is the safe default. Routing everything removes the silent-miss failure and pays for it in speed, in your outbound rules deciding whether third-party assets load at all, and in a much wider blast radius when your own side has a bad minute. Routing a list is narrower and quicker and leaves you one editing mistake from the worst failure on this page. ## The failure that has no error If a hostname is not in the routed set, the request is not refused. It is fetched the ordinary way, from wherever that name resolves publicly — and names collide with the public world more often than people expect: - A staging hostname under a domain the company also uses publicly, where a wildcard record answers everything. - A name that used to be public and still is, pointing at an old deployment nobody retired. - A parked or defensive registration that serves a placeholder page with a success status. - A name nobody owns, resolved by a search-and-redirect layer somewhere in the path. In each case something answers, the browser renders it, and the run continues. A suite written to check that a page loads will pass. A suite written to check the payroll portal's behaviour will fail on an assertion whose message is about a missing element, sending the reader to look for a front-end regression that does not exist. The defence is to make identity an assertion rather than an assumption: 1. **Assert on something only the internal target can produce**, as early in the run as possible — the branch name rendered in the page, a build identifier in a footer, a value the public site does not serve. 2. **Do it before the interesting assertions**, so a wrong-target run fails with a message that names the real problem rather than a downstream symptom. 3. **Record where the run believed it was**, so the next morning's question has a written answer. ## Keeping the set right when branches come and go Per-branch staging hosts are created and destroyed continuously, and a routed set maintained by hand goes stale exactly when a new branch needs it — the branch is new, the host is new, and the list is not. Two structural answers beat diligence: - **Route a pattern rather than an enumeration**, where the naming scheme allows it, so a new host that follows the convention is covered the moment it exists. - **Generate the set from whatever creates the environments**, in the same step, so the list and the hosts cannot disagree. A list edited afterwards by a human is one that will eventually be edited late. ## What you can observe, and what you must establish What a given provider does by default — whether an unlisted name is fetched directly, refused, or handled some third way — is that provider's own behaviour, and it is not something any artefact of yours can check. Treat it as a question to answer once, deliberately, rather than a fact to assume: - Ask what the default scope is, and write the answer down where the pipeline lives. - Prove it at least once, by pointing a run at a name you deliberately left out of the set and seeing what the browser does. - Re-prove it when the pipeline's shape changes: a default established for one configuration is evidence about that configuration only. The subject reduces to one sentence worth carrying into an interview: **a tunnel decides which names a remote browser can reach; anything outside that decision is still reachable — just not from you.**
- Why is routing every request through the tunnel not simply the safer default?It is safer against the silent-miss failure and worse at nearly everything else. Every public asset the page pulls now makes a round trip into your network and back out, so the run is slower and your outbound filtering decides whether third-party resources load at all. It also widens the blast radius of your own side: when your path stutters, requests with no connection to your application fail too.
- How would you make a run prove it reached the internal target rather than a public site at the same name?Assert on something only the internal host can produce, as early in the run as possible — the branch name rendered in the page, a build identifier, a value the public site does not serve. The check costs one assertion and converts the worst failure mode, a green run against the wrong system, into an ordinary red one that says what happened.
- Your branch staging hosts are created on demand. How does the routed set keep up?Derive it from whatever creates the hosts rather than maintaining it by hand. If the naming follows a convention, route the pattern; if the set must be enumerated, generate it in the same step that provisions the environment. A list edited by people after the fact goes stale exactly when a new branch needs it most.
saying these in an interview costs you the question
- Thinks a running tunnel puts the whole browser inside your network
- Assumes every request the remote browser makes goes through it
- Treats a page that loaded as proof it was the internal one
- Adds a new branch host and never updates the routed set
- Believes an unrouted internal name simply fails to resolve
- Ignores that routing everything makes your egress the browser's egress