A secure-by-default web browser in pure C. Zero telemetry. Zero backdoors. Zero implicit trust.
Click the URL bar (or press Ctrl+L), type, and press
Enter or click Go.
example.com opens https://example.com (the scheme is added; http:// is upgraded to https).best linux distro runs a DuckDuckGo HTML search (the no-JS version). A dangerous scheme like javascript: is searched, never executed./path/file.html or a relative path opens it from disk.| Shortcut | Action |
|---|---|
Enter / Go | Open the address, or search the web if it is not a URL |
Ctrl+L | Focus the URL bar |
Ctrl+I | Toggle remote images (off by default — Privacy by Default) |
Ctrl+D | Distraction-free (reader) mode: drop nav/header/footer/aside + author styles, center the text |
Ctrl+P | Save the current page as a vector PDF (selectable text). Headless equivalent for automated/visual review: freedom --download-pdf=PATH <url-or-file> |
Ctrl+Shift+P | Save the current page as a single PNG image (full-height bitmap). Headless equivalent — the cheapest artifact for visual review, no PDF rasterise step: freedom --download-png=PATH <url-or-file> |
Ctrl+S | Save the current page to ~/Downloads/freedom/ |
Ctrl+R / F5 | Reload the current page (re-applies the full TLS/PQ policy). A reload button is also in the toolbar. |
Ctrl+Shift+B | Block this site: add the current host to block.conf (applies on the next fetch) |
Ctrl+Shift+A | Allow this site: add the current host to allow.conf (sovereignty override & omnibox favorite) |
Ctrl+Shift+J | Allow JavaScript here: add the current host to js.conf |
| Omnibar | Type to autocomplete from your allow.conf favorites (Tab completes, ↑/↓ pick, Enter/click open). Edit with selection (Shift+arrows, Ctrl+A), cut/copy/paste (Ctrl+X/Ctrl+C/Ctrl+V). |
F12 | Freebug developer console (also in the hamburger menu): opens a second window with a log pane showing the page's console.* output + uncaught JS errors, over a resizable JS editor — type/paste JavaScript and run it with Ctrl+Enter against the live page (see the value, the error, and any console output). Each error is tagged with its source location file:line:col (e.g. inline #2:3:1 — the 2nd inline <script>, line 3, column 1), shown in a muted devtools-style link. Ctrl+L clears the editor; F12/Esc closes; drag the divider to resize. Headless equivalent: freedom --dump-console <url-or-file> prints the same console (with locations) without a window. |
--dump-dom | Render-tree dump (headless, layout debugging): freedom --dump-dom <url-or-file> prints the paint-ready tree — every block (kind, tag, container/flex/grid group, the container item it belongs to as item=N, box, author style) and the box-definition tree — in a deterministic, agent-readable form. The instrument for diagnosing why a node lays out wrong; add --author-css to populate the box tree. |
--dump-layout | Resolved-layout dump (headless, the layout-side counterpart to --dump-dom): freedom --dump-layout <url-or-file> prints the geometry the box engine actually produced — every line row (top, h, x_off, w) exposing the flex/grid column each line landed in, every in-flow box rect (x, top, w, h) and every out-of-flow positioned box (with z-index and stacking order). Where --dump-dom shows the structure (input), --dump-layout shows the rectangles (output): positioning/z-index/flex-distribution/fragmentation bugs are visible as plain numbers, no display or image needed. Add --author-css to populate the box tree. |
Ctrl++ / Ctrl+- | Zoom in / out (snaps to a 50–300% ladder) |
Ctrl+0 | Reset zoom to 100% |
Ctrl+C | Copy the focused field, or the page URL |
Ctrl+V | Paste into the focused field |
Ctrl+T | New tab |
Ctrl+W | Close tab |
Ctrl+Tab | Next tab |
Ctrl+Shift+E | Per-host exception for a weak-but-valid certificate (this session) |
j / k | Scroll down / up one line |
Space / b | Scroll down / up one page |
gg / G | Jump to top / bottom |
Home / End | Jump to top / bottom |
User-Agent and Accept-Language (a common Firefox-on-Linux identity) so every user looks the same. It never advertises "Freedom" on the wire. Override the User-Agent per session in the menu (top-right).Ctrl+I for images). Supported formats are PNG and JPEG, decoded inside the sandboxed worker (never in the UI process); anything else shows a placeholder. A page that uses images shows a tracking warning and a placeholder per image. Press Ctrl+I to see the logo above. Local pages get a file:// origin, so relative images load from disk — confined to the document's own directory (no ../ escape, no phone-home).off / allowlist / on, set in the menu, --js, or FREEDOM_JS) plus a per-host js.conf allowlist. When enabled, inline scripts run in the per-tab sandbox against a memory-safe writable DOM (document.title, textContent, createElement/appendChild, innerHTML, onload). Click events are wired end-to-end: addEventListener('click', fn) and element.onclick = fn fire when you click the element, the worker mutates the live DOM, and the GUI repaints the result (links still navigate after the handler runs). Storage is in-memory and ephemeral, cookies are empty — JS runs without leaking your identity. Scripts read a real read-only location, and a JS-requested navigation (location.href = …) is re-checked against the full network policy by the trusted parent before it loads — a hostile or compromised script can never drive the browser off-policy. External (src) scripts run only for a host you trusted twice (in allow.conf and js.conf): the sandboxed worker never touches a socket — script bytes come from the trusted parent over the same gated channel as XMLHttpRequest/fetch, with the full network policy re-applied per script (host filter, realm routing, TLS-PQ) and a JavaScript Content-Type required (a 404 HTML page is never evaluated). Errors report their url:line:col in Freebug. For every other host, external scripts still never run. Real querySelector and a modern DOM surface: document.querySelector/querySelectorAll and element.matches/closest run through the same author-CSS selector engine as the stylesheets (identical matching from JS and CSS); elements expose parentNode/children/classList/style and DocumentFragment, with node identity cached so === works. The globals a modern site touches at startup are present but inert and identity-safe: matchMedia never matches, the observers never fire, getComputedStyle returns "", performance.timing is a fixed epoch, and the viewport reads a fixed 1920 width — while window.open/postMessage stay undefined (no popups, no cross-frame messaging). Real homepages like google.com render; web-component apps (YouTube's Polymer shell) do not yet, since custom-element upgrade is unimplemented. Google may still show its server-side "unusual traffic" wall (an IP/cookie decision on their end; Freedom never persists cookies) — the address bar searches via the no-JS DuckDuckGo HTML, which renders cleanly. With JS off, <noscript> fallback content is shown..onion uses Tor only; .i2p uses I2P only — fail-closed, never leaked over clearnet.<style> blocks and inline style= — using a deliberately simpler subset: color, background, text-align, font-size, line-height, font-weight, font-style, text-decoration (underline/line-through/overline/none), display (incl. display:none), with type/class/id/group selectors plus the descendant (div p) and child (nav > a) combinators, attribute selectors ([type=text], [href^="https"], ~=/|=/$=/*= with the i case flag), !important, the sibling combinators (h2 + p, h2 ~ p) and a pseudo-class subset — :link (Zero Knowledge: no history, every link is unvisited), :root, :first-child/:last-child/:only-child/:nth-child(An+B)/:nth-last-child(), :checked/:disabled/:enabled; :visited and :hover/:focus/:active parse but never match (no CSS history sniffing, no interactive state), and unknown pseudos / all pseudo-elements fail closed. It never phones home: any value with url( and the network/font @-rules (@import/@font-face) are dropped, so author CSS can never trigger a fetch or a tracking beacon. CSS is hostile content: the parser is bounded (anti-DoS), fails closed, executes nothing, and is fuzzed.display:flex / display:grid container now takes its layout params (gap, justify-content, grid-template-columns) from the same cascade, so a <style> rule lays out columns — not just an inline style=. Because layout is structure, not styling, the columns render even with author colors off (geometry opens no socket and leaks nothing — only author colors stay gated by the toggle). See examples/css-sheet-layout.html.float:left / float:right + clear): the classic two-column era layout — a floated sidebar, a floated main column, a clear:both footer beneath — now lays out side by side instead of stacking. The float band nests inside the open box stack, so a wrapping position:relative background panel stays in-flow and paints its background behind the columns (no more grey stripes showing through). Like flex/grid, layout is structure: the columns appear even with author colors off. v1: no text wrap around a lone float (the band is a self-contained row; the next non-floated block clears below it). See examples/float.html.<link rel=stylesheet>): with Author styles on, Freedom fetches the page's external sheets the same Zero-Trust way it fetches trusted scripts: the sandboxed worker never touches a socket — each sheet is requested through the trusted parent, which re-applies the full network policy (tracker blocklist, realm routing, TLS-PQ) before any byte moves, serves style-only loads as GET exclusively, and never parses a wrong Content-Type as CSS. With the toggle off, nothing is fetched at all (Privacy by Default). This is what makes real sites (Hacker News' news.css class colors, for example) render as the webmaster styled them.margin / padding / width / max-width): resolved through the same cascade (lengths in px, a bare 0, or em/rem; %/viewport units fail closed). The headline is the modern centered reading column — max-width + margin: 0 auto + horizontal padding — and an author margin-top/margin-bottom overrides the default block spacing. An author box can shrink content to unreadability, so the box model is gated behind the Author-styles toggle like the colors (Secure by Default). The CSS parser now also resolves the values of position, border/border-radius, box-sizing, box-shadow, outline and per-item flexbox/grid (so a page using them no longer confuses the cascade) — but these are not painted yet: honouring them needs the per-block box engine and is the next milestone. See examples/box-model.html.font-family (mapped to a generic family — serif / sans-serif / monospace / cursive / fantasy; exact font files are never matched and @font-face/url() are dropped, so it never fetches), text-transform (uppercase/lowercase/capitalize), letter-spacing, word-spacing, text-shadow (single layer), opacity, vertical-align (sub/super), text-indent, white-space (nowrap/pre suppress wrapping) and list-style-type (decimal/lower-alpha/upper-roman/disc/circle/square… changes the <li> marker). All but list-style are gated behind the Author-styles toggle. See examples/text-presentation.html and the full supported-vs-missing inventory in spec/css.md.@media is supported as a safe subset — with the dark theme on (and Author styles enabled), a page's @media (prefers-color-scheme: dark) rules apply automatically. screen/print and min/max-width queries evaluate against a fixed, normalized desktop width (no real viewport size leaks — anti-fingerprinting); not and unknown features fail closed. @media only chooses which local rules apply — it still never fetches.Ctrl+D): a clean reading view — nav/header/footer/aside boilerplate is dropped, author styling and images are turned off, and the text is centered in a comfortable reading column. Toggle again to restore. Your persistent image/CSS toggles are untouched.@font-face/url() are dropped), and never persists. If no font resolves it falls back cleanly to the previous renderer.~/Downloads/freedom/ instead of being parsed as a page; Ctrl+S saves the current page there too. The filename is derived fail-closed from the hostile Content-Disposition / URL (only [A-Za-z0-9._-], no path separators, no traversal, no hidden dot), the body is size-capped, and the file is written atomically with 0600 perms.Ctrl++ / Ctrl+- step through a 50–300% ladder; Ctrl+0 resets. The page reflows at the new size with no network round-trip.X25519MLKEM768) preferred.Ctrl+Shift+E for a session exception.mmap/mprotect requesting PROT_EXEC are killed, so it cannot stage native shellcode), and the worker is made undumpable (no core file, no foreign ptrace) so its secrets cannot be exfiltrated. The allowlist is deny-by-default, so io_uring is blocked — it is a seccomp-bypass primitive (its operations skip the filtered syscall entry), so it never enters the worker, not even for async I/O; async I/O lives only on the trusted side. The parent survives a compromised worker.[ Isolated Session: Local Storage Ephemeral / Isolated PID ]