Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Privacy and content blocking

Content blocking

Ads and trackers are blocked at the network level with Adblock Plus filter lists, using Brave's adblock-rust. Run :adblock-update once to download the lists in content.blocking.adblock.lists (by default EasyList, EasyPrivacy, and uBlock Origin's own lists: uBlock filters, Privacy, Quick fixes and Unbreak, as uBlock Origin enables them; file:// lists work too). The compiled engine is cached in the data directory and loads in the background at startup. Hosts files (lines like 0.0.0.0 ads.example.com, as in StevenBlack's lists) work in the same setting; riptide recognizes them and blocks each listed host:

"content.blocking.adblock.lists" = [
  "https://easylist.to/easylist/easylist.txt",
  "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts",
]

The status bar shows how many requests were blocked on the current page, e.g. ⊘12 (the blocked widget in statusbar.widgets).

  • content.blocking.enabled turns blocking on or off.
  • content.blocking.whitelist lists hosts where nothing is blocked (subdomains included).
  • Top-level pages are never blocked, so a bad rule can't make a site unreachable. Their tracking parameters are taken out, though ($removeparam): ?utm_source=mail&id=7 loads as ?id=7.
  • Element-hiding rules (##.ad, example.com##.sponsored) are applied once a page loads: the site-specific ones, and the generic ones for the classes and ids the page uses, checked again 2 and 6 seconds later for ads that arrive late.
  • Scriptlet rules (example.com##+js(set-constant, adsEnabled, false)) run in the page before its own scripts, which is how lists defeat anti-adblock walls and in-player video ads. $redirect rules answer a blocked request with a harmless stand-in (an empty script, a 1×1 image), so the page carries on as if it had loaded. Both use uBlock Origin's scriptlets and stand-ins, built into riptide. As in uBlock Origin, the "trusted" scriptlets, which can click page elements or set arbitrary values, only run for rules from uBlock Origin's own lists.

If you set content.blocking.adblock.lists yourself before uBlock Origin's lists became defaults, add them to get most of the scriptlet rules:

"content.blocking.adblock.lists" = [
  "https://easylist.to/easylist/easylist.txt",
  "https://easylist.to/easylist/easyprivacy.txt",
  "https://ublockorigin.github.io/uAssets/filters/filters.min.txt",
  "https://ublockorigin.github.io/uAssets/filters/privacy.min.txt",
  "https://ublockorigin.github.io/uAssets/filters/quick-fixes.min.txt",
  "https://ublockorigin.github.io/uAssets/filters/unbreak.min.txt",
]

Run :adblock-update after changing the lists.

Procedural element hiding works too, for elements CSS alone can't pick out: :has-text(), :upward(), :matches-css() (and -before, -after), :matches-attr(), :matches-path(), :min-text-length() and :xpath(), with the actions :remove(), :style(), :remove-attr() and :remove-class(). They're applied as the page loads and again whenever it changes, so content added later is caught too.

Frames get element hiding too, by the rules for their own site: an ad in a frame from another site is hidden like one in the page. The page's site still decides whether anything is blocked, so allowing a site (content.blocking.whitelist) covers its frames.

Not supported yet: scriptlets in frames from another site than the page (frames from the page's own site get them).

Your own rules

content.blocking.adblock.rules holds rules of your own, in the same syntax as the lists. They apply as soon as you change them, without :adblock-update, and work even with no lists at all:

"content.blocking.adblock.rules" = [
  "news.example.com##.newsletter-signup",
  "||tracker.example.net^",
]

To hide something on a page without writing the rule yourself, press ;x (:hint blocks hide) and pick it. riptide proposes a rule for it, such as example.com##.promo-box, which you can edit (to ##.promo-box for every site, say) before pressing Return. The element and others like it disappear at once, and the rule is saved to content.blocking.adblock.rules. To take a rule back, remove it from the setting, on the settings page or with :set.

Your rules are never trusted: their scriptlets can't use uBlock Origin's trusted ones.

Network traffic

Chromium calls Google in the background. riptide turns off the calls that only serve Google and keeps the security updates (crates/rt-cef/src/privacy.rs). Measured on a fresh profile left on about:blank for 90 seconds, with --log-net-log:

RequestPurposeStatus
update.googleapis.com, edgedl.me.gvt1.comComponent updates (all of them for one run if you turn on content.widevine)Only the components Chromium marks as security data still update: certificate revocation lists (CRLSets) and the subresource filter rules. The ~20 others no longer download, saving ~115 MB per profile. These include Widevine, optimization hints, the on-device suggest model, TTS and the password-strength data.
clients2.google.com/timeSecure network time, used to explain certificate date errorskept
redirector.gvt1.com/…/dictSpell-check dictionaryonly once per language in spellcheck.languages (empty by default)
www.google.com/async/folaeAI Mode eligibilityoff (--disable-features=AimEnabled)
www.google.com preconnectsDefault search engine warm-upoff (Chrome's default search engine is disabled; riptide has its own url.searchengines)
accounts.google.com/ListAccountsGoogle accounts in the cookie jarstill sent once at startup. Google sign-in is off, but something still asks for the cookie jar; it carries your google.com cookies if you have any.

Beyond the pages you visit, riptide goes online for what you set up or ask for: :adblock-update downloads the filter lists (from easylist.to and ublockorigin.github.io by default), :extension-install and :extension-update ask the Chrome Web Store (clients2.google.com), and plugins added with rt.pack.add are fetched with git the first time riptide starts with them, and when you check for updates.

The preferences are written into the profile (Local State, Default/Preferences) before Chromium starts, since most of these services start within 100 ms. To check for yourself: riptide --basedir /tmp/t --log-net-log=/tmp/net.json about:blank, then grep -o '"url":"[^"]*' /tmp/net.json | sort -u.

Proxy and network

SettingWhat it does
content.proxysystem (default), none, a proxy URL (socks5://127.0.0.1:9050, http://proxy:3128), or pac+ and a PAC script's URL. Names are looked up through a SOCKS5 proxy, not locally
content.webrtc_ip_handling_policyWhich addresses video calls may reveal: all-interfaces (default), default-public-and-private-interfaces, default-public-interface-only, or disable-non-proxied-udp to keep WebRTC behind the proxy
content.dns_prefetchfalse stops looking up the hosts of links before you follow them
content.canvas_readingfalse stops pages reading back what they drew, a common fingerprinting trick; some sites break (after a restart)
content.cache.sizeDisk cache size in bytes; 0 lets Chromium choose (after a restart)
content.local_content_can_access_file_urlstrue lets file:// pages read other local files (after a restart)
content.webglfalse turns off WebGL, which 3D graphics need and fingerprinting scripts use (after a restart)
content.proxy = "socks5://127.0.0.1:9050"
content.webrtc_ip_handling_policy = "disable-non-proxied-udp"

Cookies, JavaScript, images and the user agent

SettingWhat it does
content.cookies.acceptall (default), no-3rdparty to refuse cookies from other sites embedded in a page, or never
content.cookies.storefalse makes every cookie last only until the browser closes
content.javascript.enabledfalse turns JavaScript off; set it per site to block or allow it on chosen sites only
content.headers.user_agentThe user agent sites see, in requests and in navigator.userAgent; empty for Chromium's own. Set it per site for sites that check it
content.headers.do_not_trackSends DNT: 1 (the default); false stops it
content.headers.referersame-domain (default) sends the Referer only within a site and its subdomains; always or never
content.headers.accept_languageThe languages sites are asked for, e.g. de-DE,de;q=0.9. Requests follow a change at once; navigator.languages after a restart
content.headers.customExtra headers for every request, e.g. { "X-Requested-By" = "me" }
content.imagesfalse stops loading images
content.autoplayfalse keeps videos from playing until you interact with the page (after a restart)
content.pdf_viewerfalse downloads PDFs instead of showing them
content.prefers_reduced_motiontrue asks pages for fewer animations (after a restart)
content.javascript.can_close_tabsfalse stops pages closing their own tab with window.close() (login popups do this)
content.javascript.log_message.levelsPage console messages to show in the status bar and :messages, e.g. ["error", "warning"]; per site too
content.mutetrue mutes pages; :tab-mute mutes one tab instead
content.javascript.can_open_tabs_automaticallytrue lets pages open tabs without a click (popups)
content.javascript.clipboardnone, access (copy after a click, the default) or access-paste (read it too)

content.images, content.mute, popups, the clipboard, JavaScript, console messages and the user agent can also be set per site:

content.cookies.accept = "no-3rdparty"

[per_domain."*.example.org"]
"content.javascript.enabled" = false
"content.images" = false

Private windows

:open -p url opens a private window. Private windows share an in-memory profile: no cookies or cache on disk, no history, and they're left out of sessions. Their status bar is gray.

The sandbox

Riptide runs Chromium's sandbox wherever Linux allows it. See Installing for how to enable it on Ubuntu.