Skip to content

Commit a5df793

Browse files
Merge PR #25: Brave Origin on Linux - detection, proven policy dir, inert rows for what Origin compiles out
Origin reads /etc/brave/policies/managed like regular Brave (verified on a real install); detected as origin / origin-beta / origin-nightly on Arch, deb, rpm and PATH; the 13 rows Origin compiles out are shown inert on Origin-only machines and stay live beside a regular Brave. Linux only. TESTING-brave-origin.md carries the remaining per-machine checks.
2 parents f0b32d1 + 21106a5 commit a5df793

6 files changed

Lines changed: 1209 additions & 52 deletions

File tree

‎AUDIT.md‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,37 @@ against them instead of re-verifying every key from scratch. A row marked
3535
original wording is kept because the *reasoning* is the audit trail, and
3636
knowing why a decision was made — and what changed under it — is the point.
3737

38+
### 2026-09-11 — targeted: Brave Origin on Linux — detection added, policy directory proven
39+
40+
**Not a policy pass.** Issue #13 asked for Brave Origin support; the July
41+
answer declined on two doubts — that Origin might not read
42+
`/etc/brave/policies`, and that most rows would be dead there. Both
43+
re-examined on the maintainer's machine with Origin installed (CachyOS,
44+
`brave-origin-bin 1:1.94.121-1`; the AUR PKGBUILD carries
45+
`Maintainer: brave <aur-release@brave.com>`, and CachyOS mirrors it).
46+
Linux only: Origin is a paid upgrade elsewhere and the Windows and macOS
47+
scripts are untouched.
48+
49+
- **Read at:** brave-core `v1.94.121` (`e894693`), and the shipped artifacts rather than the docs about them — the AUR install of `brave-origin-1.94.121-linux-amd64.zip`, `brave-origin_1.94.121_amd64.deb` (130,821,188 B, sha256 `0f76ec5f…1495`, the same bytes the apt repo's `Packages` index lists) and `brave-origin-1.94.121-1.x86_64.rpm` (132,609,317 B, sha256 `9844f1b9…6b3e`, same as the rpm repo's `primary.xml`), both fetched from the GitHub release and unpacked with bsdtar; the Flathub API and `flathub/com.brave.Browser`; the Snap store API; brave.com/origin/linux (stable, beta, nightly) and dl.brave.com/install.sh. Seven readers, one per packaging or source modality, two refuters each — one re-reading every cited source, one re-deriving each claim by a different method — with the refuters' corrections folded in before anything reached this file.
50+
- **The policy directory is `/etc/brave/policies/managed`, Origin included — proven four ways.** (1) Source: `app/brave_main_delegate.cc:166-170` overrides `chrome::DIR_POLICY_FILES` to `/etc/brave/policies` under `IS_POSIX && !IS_MAC` with no branding or channel guard, and Chromium's `config_dir_policy_loader.cc`, which brave-core does not patch, appends `managed` and `recommended`. (2) Binary: `strings` on the Origin ELF — byte-identical across the zip, the deb and the rpm, sha256 `e2061ff6…05c5`, 301,268,288 B — holds `/etc/brave/policies` and `BraveSoftware/Brave-Origin` and no `/etc/brave-origin` string at all. (3) Runtime: the running Origin process's inotify watches, read from `/proc/<pid>/fdinfo`. Before `/etc/brave` existed they sat on `/` and `/etc` and not on the existing `/etc/chromium` — Chromium's `FilePathWatcher` parked on the deepest existing ancestor of `/etc/brave/policies/managed`, and `/etc/chromium/policies` would have parked it one level lower. After the directory was created, a fresh Origin process watched `/etc/brave`, `/etc/brave/policies` and `/etc/brave/policies/managed` themselves. (4) End to end: a managed `ExtensionInstallForcelist` written to that directory installed all six listed extensions into `~/.config/BraveSoftware/Brave-Origin/Default`, each recorded in `Preferences` as `extensions.settings.<id>.location = 7` — `ManifestLocation::kExternalPolicyDownload` — with no browser restart. And with this tool itself: `--import` of the Brave Origin preset wrote the fifteen keys to `slimbrave.json`, and `chrome://policy` in a throwaway Origin profile — read over the DevTools pipe, since the page's shadow DOM defeats `--dump-dom` — listed every one as `Platform`, `Machine`, `Mandatory`, status `OK`; `--export` round-tripped them and `--reset` removed only its own file. The "untested" in the July comment is closed.
51+
- **`/etc/brave-origin` is a red herring.** `chromium_src/chrome/installer/linux/common/brave-origin/chromium-browser.info` sets `ENROLLMENTDIR=/etc/brave-origin/policies/enrollment` — Chrome Browser Cloud Management's enrollment-token directory, touched only by the deb and rpm post-install scripts and only when `/etc/default/brave-origin` opts into the device-trust key. Managed policy never reads it, and the binary never names it. Do not write policies there.
52+
- **Where Origin lives on Linux**, every row from the artifact:
53+
54+
| Packaging | Install dir | Binary | Launcher | On `PATH` | Profile |
55+
|---|---|---|---|---|---|
56+
| Arch: AUR `brave-origin-bin` (CachyOS repo mirrors it); unpacks the upstream zip | `/opt/brave-origin-bin/` | `brave` | `brave-origin`, Chromium's stock wrapper | `/usr/bin/brave-origin`, a bash script that reads `~/.config/brave-origin-flags.conf` and execs the launcher | `~/.config/BraveSoftware/Brave-Origin` |
57+
| deb: `brave-origin`, from the same `brave-browser-apt-release.s3.brave.com` repo as `brave-browser`; no Conflicts, so both co-install | `/opt/brave.com/brave-origin/` | `brave` | `brave-origin` | `/usr/bin/brave-origin-stable`, a shipped symlink; bare `/usr/bin/brave-origin` comes from `update-alternatives` in postinst (priority 201) | same |
58+
| rpm: `brave-origin`, from `brave-browser-rpm-release.s3.brave.com` (dnf, zypper, rpm-ostree; the bucket also serves `brave-browser-origin.repo` plus `-beta` and `-nightly` variants, byte-identical to `brave-browser.repo`) | `/opt/brave.com/brave-origin/` | `brave` | `brave-origin` | `/usr/bin/brave-origin-stable`, shipped; bare `/usr/bin/brave-origin` is a `%ghost` that `%post`'s `update-alternatives` creates (priority 200) | same |
59+
| Beta, Nightly: `brave-origin-beta`, `brave-origin-nightly` (the apt and rpm beta and nightly repos; AUR `brave-origin-beta-bin` and `-nightly-bin` repackage the deb) | `/opt/brave.com/brave-origin-beta/`, `…-nightly/` | `brave` | `brave-origin-beta`, `-nightly` | `/usr/bin/brave-origin-beta`, `-nightly`, direct symlinks | `Brave-Origin-Beta`, `Brave-Origin-Nightly` — the `-Beta`/`-Nightly` suffixes of `brave_channel_info_posix.cc:27-38` |
60+
| Flatpak | none. Flathub has only `com.brave.Browser`; every Origin-shaped id 404s; `flathub/com.brave.Browser` has no Origin branch, issue or PR across 994 of them; brave/brave-browser #55196 asking for one is open and unanswered. Brave's own RDN for Origin, `com.brave.Origin` (the `.info` file), is used only by a one-star unofficial bundle with no remote. Nothing to probe. | | | | |
61+
| Snap | none. The store has `brave` only, publisher Brave Software, verified; `brave-origin` is `resource-not-found`, and the `brave` snap's channel map is `latest/{stable,candidate,beta,edge}` with no Origin track. Its rev-678 squashfs was downloaded and listed: `opt/brave.com/brave/` only, and its binary carries `BraveSoftware/Brave-Browser` and not `Brave-Origin` — regular Brave. `brave-core`'s `snapcraft.yaml` dumps the `brave-browser` deb and never mentions Origin. Side finding, likely rather than confirmed: snapd's `browser-support` interface grants the snap `/etc/opt/chrome` and `/etc/chromium` and nothing under `/etc/brave`, which is the mechanism behind this tool's long-standing Snap warning. | | | | |
62+
63+
- **Names the detector relies on.** Profile: `chromium_src/chrome/common/chrome_paths_linux.cc:26-27` — `BraveSoftware/Brave-Origin` plus the channel suffix under `IS_BRAVE_ORIGIN_BRANDED`. Package: `build/config.gni:71-79` (`brave_linux_package_name = "brave-origin"`) and `installer/linux/sources.gni:8-9`. Desktop ids: `chromium_src/chrome/common/channel_info_posix.cc:64-74` — `brave-origin[-beta|-nightly|-dev].desktop`, `StartupWMClass=brave-origin`. Processes: the browser's comm is `brave` on every packaging (its `exe` sits under the install dir), so the stable row's `pgrep -x brave` already sees a running Origin; the launcher's bash process stays alive around it — brave-core's `chrome-installer-linux-common-wrapper.patch` drops Chromium's `exec -a` — with the comm it was started by — `brave-origin` from the AUR wrapper, `brave-origin-st` (comm's 15-character cap) from the deb/rpm desktop file's `/usr/bin/brave-origin-stable`; the new rows carry `brave-origin` as `process_name`, and the profile's `SingletonLock` covers the truncated case as it does for every channel whose name overruns the cap. The shipped man page's `$HOME/.config/brave-origin` is Chromium template text and wrong.
64+
- **Detection shipped.** `LINUX_CHANNELS` gains `origin`, `origin-beta` and `origin-nightly` — no `origin-dev`: `channel_info_posix.cc` names it, nothing publishes it. `detect_brave()` probes `/opt/brave-origin-bin/brave`, `/opt/brave.com/brave-origin/brave-origin`, `/opt/brave.com/brave-origin/brave`, then `brave-origin-stable` and `brave-origin` on `PATH`, and reports `arch (Brave Origin)`, `deb/rpm (Brave Origin)`, `unknown (Brave Origin)`, or `arch: Stable, Origin` beside a regular Brave; beta and nightly Origin are found by profile directory or launcher, as Brave's own are. Origin's profiles join prefs repair and the running check, and `--channels` accepts the three ids. A `notes` list — a new key beside `warnings`, so the status line keeps the success colour — says on launch that policies apply and the rows Origin removes are inert, or, beside a regular Brave, that every row stays live. Both scripts, README, and the tests.
65+
- **Regular Brave in "Origin mode" is still regular Brave.** On Linux the free tier is a click at `brave://settings/origin` (`components/brave_origin/brave_origin_settings_handler_impl.cc`, `ProceedFree` → `BraveOriginService::AcceptFreeTier`); it sets `brave.origin.free_tier_accepted` and `policies_were_enforced` in `Local State` and keeps its toggles in `brave.brave_origin.policies` there. Same binary, same `Brave-Browser` profile, every feature still compiled in — the Flatpak included. Nothing for the detector to do, and every row is live.
66+
- **A managed file outranks Origin's own layer; it cannot revive what Origin compiled out.** Origin enforces its debloat through two `ConfigurationPolicyProvider`s (`BraveBrowserPolicyProvider`, `BraveProfilePolicyProvider`) that emit `POLICY_SOURCE_BRAVE` at `kBravePriority`, which brave-core inserts below `kEnterpriseDefault` — the lowest browser-policy priority there is, and its own test `BravePolicySourceTest.BraveHasLowerPriority` says so. `PolicyMap::MergeFrom` resolves on (level, priority), so a mandatory platform entry from `/etc/brave/policies/managed` wins every conflict: `{"BraveP3AEnabled": true}` there would switch P3A back on in Origin. Nothing this tool writes points that way, and for the compiled-out features the question is moot — no handler, no pref, no feature to switch.
67+
- **Which rows are dead on Origin — the inventory, and what the tool does with it.** Thirteen keys. Each one's entry in `browser/policy/brave_simple_policy_map.h` sits under a `BUILDFLAG` — `ENABLE_BRAVE_REWARDS`, `ENABLE_BRAVE_WALLET`, `ENABLE_TOR`, `ENABLE_BRAVE_VPN`, `ENABLE_AI_CHAT`, `ENABLE_LOCAL_AI`, `ENABLE_PLAYLIST`, `ENABLE_WEB_DISCOVERY`, `ENABLE_BRAVE_NEWS`, `ENABLE_BRAVE_TALK`, `ENABLE_SPEEDREADER`, `ENABLE_BRAVE_WAYBACK_MACHINE`, `ENABLE_EMAIL_ALIASES` — and every one of those flags is `… && !is_brave_origin_branded` in its `components/<feature>/…/buildflags.gni` (`enable_brave_vpn` already lacked `is_linux`). The keys: `BraveRewardsDisabled`, `BraveWalletDisabled`, `TorDisabled`, `BraveVPNDisabled`, `BraveAIChatEnabled`, `BraveLocalAIEnabled`, `BravePlaylistEnabled`, `BraveWebDiscoveryEnabled`, `BraveNewsDisabled`, `BraveTalkDisabled`, `BraveSpeedreaderEnabled`, `BraveWaybackMachineEnabled`, `EmailAliasesEnabled`. Confirmed on the shipped binary: the target prefs are not registered at all (a `chrome://prefs-internals` dump of a throwaway profile has nothing under `brave.wallet`, `brave.ai_chat`, `brave.playlist`, `brave.speedreader`, `brave.news`, `brave.talk`, `brave.email_aliases`, `brave.web_discovery` or `brave.wayback`, and `Local State` no `tor.*`), and injecting every SlimBrave Brave key as a mandatory machine platform policy through `chrome://policy/test` made none of those thirteen prefs managed — while `brave://policy` listed each as applied, status OK, the same blind spot the `BraveVPNDisabled` row already documents. `BraveP3AEnabled` and `BraveStatsPingEnabled` are the other two of the preset's fifteen: unguarded, dispatched, and Origin's own provider sets them `false` at the lowest priority, so a managed `false` is redundant but pins them. `MetricsReportingEnabled` is live too, against a default Origin already forces to `false`. Everything else — the five unguarded Brave privacy toggles, both Shields lists, the `DefaultBrave*` content settings, every Chromium key — is live. The 2026-09-07 parity bullet under Cross-cutting describes the metadata tables as compiled into regular Brave; on the branded build only those two of the fifteen are enforced by Origin itself. **In the tool:** `ORIGIN_BUILTIN_KEYS` in both scripts carries the thirteen. When every detected Brave is Origin (`is_origin_only`), `build_rows` marks them inert: drawn `[-]`, dimmed, `(built into Origin)`, out of the header counts, untoggleable, never written or exported, unticked on sync so the next Apply drops a stale key, and an import that names them reports `13 keys built into Brave Origin left unmanaged`. Beside any regular Brave every row stays live, because the one file serves both — and "beside" is judged on the whole machine: a regular Brave found by package, Flatpak, Snap or launcher but never started still gets its record next to Origin's, and every record carries the machine-wide `origin_only` verdict, so `--channels origin` cannot narrow a mixed machine into an Origin-only one. Under `--policy-file` the rows come from the override record and stay live, and the launch note stays off.
68+
3869
### 2026-09-07 — all 77 keys re-verified against the shipping tag; one dead key found
3970

4071
- **Read at:** Chromium **152.0.7977.83** — the tag brave-core `v1.94.121` pins, i.e. the browser installed here — policy_definitions tree `04b4c4f` (1,518 YAML, 66 group files, **1,452 policies**), and `chromium/main` `34e8449` (tree `2546ed1`; 1,525 YAML, 67 group files, **1,458 policies**). brave-core `v1.94.121` (tag `76a06f2` → `e894693`) and master `20512a1`, **30 policies each**, with the `1.95.x` and `1.96.x` release branches for probes.
@@ -212,7 +243,7 @@ case.
212243
## Cross-cutting checks
213244

214245
- **Windows registry path** — `HKLM:\SOFTWARE\Policies\BraveSoftware\Brave` confirmed correct against Brave's official Group Policy documentation (`BraveSoftware\Brave-Browser` is the *install* dir name, not the policy path). **Source-confirmed 2026-09-07:** Chromium generates the key — `components/policy/tools/generate_policy_source.py` emits `kRegistryChromePolicyKey` from `CHROMIUM_POLICY_KEY` for non-Google branding, and brave-core's `chromium_src/components/policy/tools/generate_policy_source.py` overrides that constant to `SOFTWARE\Policies\BraveSoftware\Brave`; `chrome_browser_policy_connector.cc` hands the constant to `PolicyLoaderWin`, which brave-core does not touch. The key carries no channel or Brave Origin suffix (`install_static` varies only the install-dir names), so the same path serves stable, beta, nightly and Origin.
215-
- **Linux policy directory** — `/etc/brave/policies/managed` (2026-09-07). Chromium's default is `/etc/chromium/policies` (`policy_paths.cc`); brave-core does not patch that file — `app/brave_main_delegate.cc` overrides `chrome::DIR_POLICY_FILES` to `/etc/brave/policies` at startup under `IS_POSIX && !IS_MAC`, unconditionally, and Chromium's `config_dir_policy_loader.cc` appends `managed` / `recommended`. Channel- and Origin-independent. `slimbrave-mac.py`'s comment citing `brave_main_delegate.cc` is correct.
246+
- **Linux policy directory** — `/etc/brave/policies/managed` (2026-09-07). Chromium's default is `/etc/chromium/policies` (`policy_paths.cc`); brave-core does not patch that file — `app/brave_main_delegate.cc` overrides `chrome::DIR_POLICY_FILES` to `/etc/brave/policies` at startup under `IS_POSIX && !IS_MAC`, unconditionally, and Chromium's `config_dir_policy_loader.cc` appends `managed` / `recommended`. Channel- and Origin-independent. `slimbrave-mac.py`'s comment citing `brave_main_delegate.cc` is correct. **Confirmed at runtime on Brave Origin 1.94.121, 2026-09-11** — inotify watches on the directory itself and a managed policy seen taking effect; see that pass.
216247
- **macOS managed-preferences plists** — `com.brave.Browser` / `.beta` / `.nightly` (2026-09-07). Chromium's `chrome_browser_policy_connector.cc` uses the running app's own bundle id for non-Google branding, and `policy_loader_mac.mm` builds `/Library/Managed Preferences/<bundle id>.plist` from it; the ids come from brave-core `app/theme/brave/BRANDING*` via `branding.gni`. `MAC_CHANNELS` matches those files exactly; a Dev channel (`com.brave.Browser.dev`) exists and is not listed — low priority.
217248
- **`ForUrls` wildcard patterns** — Brave's docs say "wildcards are not supported", meaning patterns like `*.example.com`. The scheme-wide patterns SlimBrave uses (`https://*`, `http://*`) are valid ContentSettingsPattern syntax and are applied correctly. They are **not** written to your profile: `PolicyProvider` keeps policy content settings in an in-memory `OriginValueMap` (`content_settings_policy_provider.h`) and never writes them back to `Preferences`. The `profile.content_settings.exceptions.braveShields` entries the repair logic in all three scripts scrubs were written by **pre-1.x SlimBrave**, which set them as ordinary user content settings; the repair undoes that old damage rather than anything current Brave does. **Re-verified 2026-09-07** at 152.0.7977.83 (`PolicyProvider` is read-only: `SetWebsiteSetting` returns false, `ClearAllContentSettingsRules` is empty) — and the Shields keys take the same in-memory path, wired by brave-core's `patches/components-content_settings-core-browser-content_settings_policy_provider.cc.patch` and its `rewrite/…content_settings_policy_provider.cc.yaml` twin, both present at the tag and on master.
218249
- **Ad Block Only Mode writes policies too (2026-09-07).** brave-core `v1.94.121` ships `components/brave_policy/ad_block_only_mode/ad_block_only_mode_policy_manager.cc`: when `brave_shields::features::kAdblockOnlyMode` is on **and** the local-state opt-in `kAdBlockOnlyModeEnabled` is true, `BraveProfilePolicyProvider` injects thirteen values at `MANDATORY / USER / POLICY_SOURCE_BRAVE` — `BlockThirdPartyCookies=false`, `DefaultCookiesSetting=1`, `DefaultJavaScriptSetting=1`, `DefaultBraveAdblockSetting=2`, `DefaultBraveFingerprintingV2Setting=1`, `DefaultBraveHttpsUpgradeSetting=3`, `DefaultBraveReferrersSetting=1`, `DefaultBraveRemember1PStorageSetting=1`, and `BraveReduceLanguageEnabled` / `BraveDeAmpEnabled` / `BraveDebouncingEnabled` / `BraveTrackingQueryParametersFilteringEnabled` / `BraveGlobalPrivacyControlEnabled` all `false` — eleven of them keys this project writes, mostly to the opposite value. The feature is off at `v1.94.121` and `1.95.x` and **on by default on desktop from `1.96.x`**; the opt-in pref defaults to false, so nothing happens until a user turns the mode on in Shields. Precedence is settled in SlimBrave's favour: brave-core's `chromium_src/components/policy/core/common/policy_types.h` inserts `kBravePriority` as the **lowest** browser priority, below `kEnterpriseDefault`, and `policy_map.cc` maps `POLICY_SOURCE_BRAVE` to it; a registry or policy-file value is `MANDATORY / kPlatformMachine` and wins in `EntryHasHigherPriority`. The loser is kept as a conflict, so from 1.96 a user with the mode on will see `IDS_POLICY_CONFLICT_DIFF_VALUE` warnings on `brave://policy` for those keys. No script change; worth a README sentence when 1.96 ships.

0 commit comments

Comments
 (0)