halfsheet browser
how it's tested
Updated October 28, 2026.
A browser handles your passwords, your bank and your mail, so "trust us" isn't enough. This page says what is Apple's work and what is ours, what the app promises, and what we check before a release. The parts we don't cover are listed too.
what's Safari's and what's ours
Every browser on iPhone runs on WebKit, the engine inside Safari, because Apple requires it. How a page is drawn, how sites are kept apart from each other, how cookies, passwords and encryption work, and how web pages are kept from reading one another's data: all of that is WebKit's, and Halfsheet gets it exactly as Safari does. When we run BrowserAudit, an independent test of several hundred of those protections, Halfsheet and Safari give the same result on the same iPhone Duo.
What's ours is the part around the page: what the address says and when it shows, the dialogs and questions the app puts up, which pop-ups and links to other apps get through, reader view, downloads, and the ad and tracker blocking the app adds. That's what the rest of this page is about.
what the address promises
The address is the one thing on screen a page can't draw over, so it has to tell the truth even when a page is trying to look like somewhere else.
- It shows the site's name and nothing else: no page title, no path, nothing a page chose.
- A long name that won't fit loses its start, never its end, which is the part that says whose site it is. A page at accounts.google.com.something.evil.example can never read as Google.
- A name in another alphabet reads as itself when it's genuinely in that alphabet, and stays in its coded form when it mixes alphabets or is made of letters that look like English ones. A fake "apple" in Cyrillic can't pass for the real one.
- A port that isn't the usual one is shown, so bank.com:8080 doesn't read as bank.com.
- A page with no site of its own, like a pop-up a page wrote into itself, shows no site. It can't borrow one.
- A page over plain http carries a warning. A site whose certificate can't be checked gets a full-screen warning first, and keeps the address's warning if you choose to visit anyway.
- While a page sends you somewhere else, the address keeps naming the page you're looking at until the new one has actually arrived. A page can't show a bank's name over its own content by starting a load that never finishes, and a page sending itself back in its history isn't treated as you pressing Back.
dialogs, pop-ups and other apps
- A dialog from a page is titled with the site that put it up. An ad in a frame from another site gets that site's name, not the page's, so "your session has expired, sign in again" from an ad can't pass for the page you're on.
- From a page's second dialog on, you can block the rest, so a page can't trap you in a loop of them.
- A link that opens another app asks first and names the page asking, never the link, which a page could fill with a bank's name. Calls, messages and email go to iOS, which asks you itself. A frame inside a page can't send you to another app at all unless you tapped it.
- A frame from another site may open a tab only to its own site or the page's. A tap on a see-through layer laid over a video player opens nothing. A blank pop-up that's then sent on to an ad is closed. One tap opens one tab.
- Reader view shows an article with the page's scripts off, and keeps them off.
- Typing a "javascript:" or "data:" address, as a page might tell you to, runs nothing: it's searched for instead.
the app's own scripts
Blocking, dark pages and cookie answering are done with scripts and rules the app adds to pages. They run in a separate JavaScript world from the page's own scripts, so a page can't call them or read what they hold, and the page only hears from the app through a few named messages. The blocking and dark mode lists are downloaded over https from fixed addresses, with limits on their size and on the number of rules. A list can only block or hide things on a page, or restyle it; it can't run code or read anything. The lists aren't signed by their publishers, so if a list's publisher were compromised, that list could hide or block the wrong things until we noticed. We'd rather say that than pretend otherwise.
what runs before a release
- Hundreds of automated tests, on the simulator, covering the layout in every fold and orientation of the iPhone Duo and the behaviour above.
- A spoofing sweep, added October 28, 2026, which plays every attack from a published catalogue of mobile browser address-bar and interface tricks (the Hindsight study, from 2017) against the app in each pose and keeps a picture of each. Its checklist, and what it leaves out, is summarised below.
- A bug bash: a set of real sites opened in every pose, photographed and compared against the last release that was looked over by a person.
- Hands on the phone. Simulators don't fold, and some things only show on the real thing.
what we know we don't cover
- WebKit's own bugs. Those are Apple's to fix, and they reach Halfsheet with iOS updates, the same as Safari.
- Whether a page over https that quietly loads a picture over plain http is marked differently from one that doesn't. WebKit blocks scripts loaded that way; we don't yet test the address's marking for pictures.
- A site you've allowed to go full screen in Website Settings can use the whole screen. Nothing checks what you see while it does.
- The correctness of the blocking lists themselves, which are other people's work.
reporting a security problem
If you've found a way to make Halfsheet say something untrue, or do something it shouldn't, please tell us before you tell anyone else: support@terracraft.fyi with "security" in the subject. A real person reads it, usually within two business days, and we'll tell you what we find and when it's fixed. We don't run a bounty programme, but we will credit you if you'd like.