init
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
assets/
|
||||||
200
README.md
Normal file
200
README.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# Brave Settings Backup
|
||||||
|
|
||||||
|
## Quick: Manual intervention
|
||||||
|
|
||||||
|
When opening the browser using the backup, these are the only need actions:
|
||||||
|
- brave://settings/getStarted
|
||||||
|
- Get started > On startup > Open the New Tab Page
|
||||||
|
- brave://settings/search
|
||||||
|
- Set Search engine
|
||||||
|
|
||||||
|
## Explanation
|
||||||
|
|
||||||
|
Goal: Backup Brave Settings while disabling unnecessary features.
|
||||||
|
|
||||||
|
Resources at:
|
||||||
|
- Brave: https://support.brave.app/hc/en-us/articles/360039248271-Group-Policy
|
||||||
|
- Google: https://chromeenterprise.google/intl/en_us/policies/
|
||||||
|
|
||||||
|
### Using Group-Based Policies (GBP)
|
||||||
|
|
||||||
|
There are two groups:
|
||||||
|
- Mandatory (system-wide) <- use this one
|
||||||
|
- Stored at `/Library/Managed Preferences/com.brave.Browser.plist`
|
||||||
|
- It is an editable file. This tool can be used too `PlistBuddy`
|
||||||
|
- Commands:
|
||||||
|
```
|
||||||
|
sudo mkdir -p "/Library/Managed Preferences"
|
||||||
|
sudo chown root:wheel "/Library/Managed Preferences"
|
||||||
|
sudo chmod 755 "/Library/Managed Preferences"
|
||||||
|
|
||||||
|
# Run this see the effect
|
||||||
|
sudo killall cfprefsd
|
||||||
|
```
|
||||||
|
- Recommended (user-level)
|
||||||
|
- Stored at: `~/Library/Preferences/com.brave.Browser.plist`
|
||||||
|
- It is a binary and can be used via:
|
||||||
|
- `defaults read com.brave.Browser`
|
||||||
|
- `defaults delete com.brave.Browser`
|
||||||
|
- `defaults write com.brave.Browser DefaultSearchProviderEnabled -bool true`
|
||||||
|
- `defaults import com.brave.Browser ./com.brave.Browser.plist`
|
||||||
|
|
||||||
|
Some policies only work if the instance is managed via MDM.
|
||||||
|
Because of that, we have to rely on preferences too.
|
||||||
|
|
||||||
|
### Using Preferences
|
||||||
|
|
||||||
|
This method is not recommened neither is documented; however, there is no other alternative.
|
||||||
|
|
||||||
|
Whenever the browser is opened for the first time, this dir is created and populated:
|
||||||
|
- `~/Library/Application Support/BraveSoftware/Brave-Browser`
|
||||||
|
|
||||||
|
Note: For testing purposes, after everything is backed up, feel free to completely delete it.
|
||||||
|
|
||||||
|
Inside, there are four main files:
|
||||||
|
- `Brave-Browser/First Run` (empty file used as flag to skip "Welcome page")
|
||||||
|
- `Brave-Browser/Local State`
|
||||||
|
- `Brave-Browser/<Default_or_Profile>/Preferences`
|
||||||
|
- `Brave-Browser/<Default_or_Profile>/Secure Preferences`
|
||||||
|
|
||||||
|
How the browser starts up (as a new tab, for instance) and the default search engine are
|
||||||
|
preferences stored in "Secure Preferences", and these values are hashed to ensure the integrity.
|
||||||
|
This means that the file cannot be edited manually: only via UI or by backing up the whole file.
|
||||||
|
These hashes change based on the machine, so be aware.
|
||||||
|
|
||||||
|
## How does the backup work?
|
||||||
|
|
||||||
|
There are a few files:
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── _assets All settings.
|
||||||
|
│ ├── Default
|
||||||
|
│ │ └── Preferences
|
||||||
|
│ ├── First Run
|
||||||
|
│ └── Local State
|
||||||
|
├── assets Settings with hashes. Not important and can be deleted.
|
||||||
|
│ ├── Default
|
||||||
|
│ │ ├── Preferences
|
||||||
|
│ │ └── Secure Preferences
|
||||||
|
│ ├── First Run
|
||||||
|
│ └── Local State
|
||||||
|
├── policies Browser policies. Generated by `brave_set_policies.py`
|
||||||
|
│ └── com.brave.Browser.plist
|
||||||
|
├── README.md
|
||||||
|
├── brave_debug.sh
|
||||||
|
├── brave_set_assets.py If `assets` dir not present, uses `_assets`.
|
||||||
|
├── brave_set_policies.py
|
||||||
|
└── brave_update_assets.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
First, make sure to delete these files:
|
||||||
|
```
|
||||||
|
rm -rf ./assets
|
||||||
|
rm -rf '~/Library/Application Support/BraveSoftware/Brave-Browser'
|
||||||
|
```
|
||||||
|
|
||||||
|
Set `policies/com.brave.Browser.plist` by executing `./brave_set_policies.py`.
|
||||||
|
You can check them at: `brave://policy`.
|
||||||
|
|
||||||
|
Set `_assets` by executing `./brave_set_assets.py`.
|
||||||
|
|
||||||
|
Open the browser and manually follow the steps in "Manual intervention". Close the browser.
|
||||||
|
|
||||||
|
Run `./brave_update_assets.sh` to copy over `assets` the preferences with the new proper hashes.
|
||||||
|
|
||||||
|
## Debug or find new preferences
|
||||||
|
|
||||||
|
The script `./brave_debug.sh` helps finding the preference property by comparing the files.
|
||||||
|
|
||||||
|
After deleting the directory `~/Library/Application Support/BraveSoftware/Brave-Browser`,
|
||||||
|
open the browser (to load the `Brave-Browser` dir), close it and run `./brave_debug.sh backup init`.
|
||||||
|
|
||||||
|
Open agian the browser, change the desired settings, close it and run `./brave_debug.sh diff init`.
|
||||||
|
|
||||||
|
This will compare the old files with the new ones and help you find the differences.
|
||||||
|
|
||||||
|
The script basically creates named checkpoints in `/tmp`
|
||||||
|
following the structure `./brave_debug.sh <command> <checkpoint_name>`.
|
||||||
|
|
||||||
|
## All preferences files
|
||||||
|
|
||||||
|
- "Brave-Browser/Local State"
|
||||||
|
- Create empty file "Brave-Browser/First Run"
|
||||||
|
- Check asset file
|
||||||
|
|
||||||
|
- "Brave-Browser/Default/Preferences"
|
||||||
|
- Check asset file
|
||||||
|
|
||||||
|
- "Brave-Browser/Default/Secure Preferences"
|
||||||
|
- Search engine is set in "Default/Preferences" but unless
|
||||||
|
it is hashed in "Default/Secure Preferences", browser does not set it.
|
||||||
|
- `restore_on_startup: 5` sets "On startup: Open the New Tab Page". It needs to be hashed too.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"session": {
|
||||||
|
"restore_on_startup": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## All settings mapped
|
||||||
|
|
||||||
|
---
|
||||||
|
Brave 1.83.118 (Official Build) (arm64)
|
||||||
|
Chromium: 141.0.7390.108
|
||||||
|
---
|
||||||
|
|
||||||
|
### Get started
|
||||||
|
- On startup >> "Open the New Tag page"
|
||||||
|
- [Secure Preferences]:session.restore_on_startup
|
||||||
|
- New tab page shows >> "Blank page"
|
||||||
|
- brave.new_tab_page.shows_options
|
||||||
|
|
||||||
|
### Appearance
|
||||||
|
- Show tab groups in bookmarks >> OFF
|
||||||
|
- bookmark_bar.show_tab_groups
|
||||||
|
- Automatically pin new tab groups created on any device to the bookmarks >> OFF
|
||||||
|
- auto_pin_new_tab_groups
|
||||||
|
|
||||||
|
### Shields
|
||||||
|
- Show the number of blocked items on the Shields icon >> OFF
|
||||||
|
- brave.shields.stats_badge_visible
|
||||||
|
- Store contact information for future broken site reports >> OFF
|
||||||
|
- brave.webcompat.report.contact_info: "" (empty string)
|
||||||
|
- brave.webcompat.report.enable_save_contact_info: false
|
||||||
|
|
||||||
|
### Privacy and security
|
||||||
|
- Only resolve .onion addresses in Tor windows >> OFF
|
||||||
|
- tor.onion_only_in_tor_windows
|
||||||
|
- Allow privacy-preserving product analytics (P3A) >> OFF
|
||||||
|
- [Local State]:brave.p3a.enabled
|
||||||
|
- Automatically send diagnostic reports >> OFF
|
||||||
|
- [Local State]:brave.user_experience_metrics.reporting_enabled
|
||||||
|
|
||||||
|
### Search engine
|
||||||
|
- Improve search suggestions >> OFF
|
||||||
|
- search.suggest_enabled
|
||||||
|
|
||||||
|
### Extensions
|
||||||
|
- Media Router >> OFF
|
||||||
|
- media_router.enable_media_router
|
||||||
|
- Widevine >> ON
|
||||||
|
- brave.widevine_opted_in
|
||||||
|
|
||||||
|
### Autofill and passwords
|
||||||
|
- (Passwords.Settings) Sign in automatically >> OFF
|
||||||
|
- credentials_enable_autosignin
|
||||||
|
- Allow auto-fill in private windows >> OFF
|
||||||
|
- brave.autofill_private_windows
|
||||||
|
|
||||||
|
### Languages
|
||||||
|
- Websites in your languages >> "en"
|
||||||
|
- intl.accept_languages
|
||||||
|
- intl.selected_languages
|
||||||
|
|
||||||
|
### System
|
||||||
|
- Memory Saver >> ON
|
||||||
|
- [Local State]:performance_tuning.high_efficiency_mode
|
||||||
|
- Energy Saver >> OFF
|
||||||
|
- [Local State]:performance_tuning.battery_saver_mode
|
||||||
|
|
||||||
37
_assets/Default/Preferences
Normal file
37
_assets/Default/Preferences
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"brave": {
|
||||||
|
"new_tab_page": {
|
||||||
|
"shows_options": 2
|
||||||
|
},
|
||||||
|
"webcompat": {
|
||||||
|
"report": {
|
||||||
|
"contact_info": "",
|
||||||
|
"enable_save_contact_info": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shields": {
|
||||||
|
"stats_badge_visible": false
|
||||||
|
},
|
||||||
|
"autofill_private_windows": false,
|
||||||
|
"other_search_engines_enabled": true,
|
||||||
|
"show_side_panel_button": false
|
||||||
|
},
|
||||||
|
"intl": {
|
||||||
|
"accept_languages": "en",
|
||||||
|
"selected_languages": "en"
|
||||||
|
},
|
||||||
|
"media_router": {
|
||||||
|
"enable_media_router": false
|
||||||
|
},
|
||||||
|
"tor": {
|
||||||
|
"onion_only_in_tor_windows": false
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"suggest_enabled": false
|
||||||
|
},
|
||||||
|
"credentials_enable_autosignin": false,
|
||||||
|
"bookmark_bar": {
|
||||||
|
"show_tab_groups": false
|
||||||
|
},
|
||||||
|
"auto_pin_new_tab_groups": false
|
||||||
|
}
|
||||||
0
_assets/First Run
Normal file
0
_assets/First Run
Normal file
25
_assets/Local State
Normal file
25
_assets/Local State
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"brave": {
|
||||||
|
"first_run_finished": true,
|
||||||
|
"p3a": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"user_experience_metrics": {
|
||||||
|
"reporting_enabled": false
|
||||||
|
},
|
||||||
|
"widevine_opted_in": true
|
||||||
|
},
|
||||||
|
"browser": {
|
||||||
|
"enabled_labs_experiments": [
|
||||||
|
"brave-compact-horizontal-tabs@1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"performance_tuning": {
|
||||||
|
"battery_saver_mode": {
|
||||||
|
"state": 0
|
||||||
|
},
|
||||||
|
"high_efficiency_mode": {
|
||||||
|
"state": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
brave_debug.sh
Executable file
111
brave_debug.sh
Executable file
@@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Brave Browser configuration backup & diff tool (jq-enhanced)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# brave_backup.sh backup [prefix]
|
||||||
|
# brave_backup.sh diff <prefix>
|
||||||
|
#
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# --- CONFIG ---
|
||||||
|
BRAVE_DIR="$HOME/Library/Application Support/BraveSoftware/Brave-Browser"
|
||||||
|
FILES=(
|
||||||
|
"Local State"
|
||||||
|
"Default/Preferences"
|
||||||
|
"Default/Secure Preferences"
|
||||||
|
)
|
||||||
|
BACKUP_DIR="/tmp/brave_backups"
|
||||||
|
|
||||||
|
# --- FUNCTIONS ---
|
||||||
|
|
||||||
|
jq_pretty() {
|
||||||
|
local src="$1"
|
||||||
|
local dest="$2"
|
||||||
|
|
||||||
|
if jq -e . "$src" >/dev/null 2>&1; then
|
||||||
|
jq --sort-keys . "$src" >"$dest"
|
||||||
|
echo " (jq formatted)"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
cp "$src" "$dest"
|
||||||
|
echo " (raw copy - not valid JSON)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
backup_files() {
|
||||||
|
local prefix="${1:-$(date +%Y%m%d_%H%M%S)}"
|
||||||
|
local target_dir="${BACKUP_DIR}/${prefix}"
|
||||||
|
mkdir -p "$target_dir"
|
||||||
|
|
||||||
|
echo "🔒 Backing up Brave files to: $target_dir"
|
||||||
|
for f in "${FILES[@]}"; do
|
||||||
|
local src="${BRAVE_DIR}/${f}"
|
||||||
|
local dest="${target_dir}/$(basename "$f")"
|
||||||
|
if [[ -f "$src" ]]; then
|
||||||
|
jq_pretty "$src" "$dest"
|
||||||
|
echo "✅ Backed up (pretty JSON): $f → $dest"
|
||||||
|
else
|
||||||
|
echo "⚠️ Missing: $src"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "✅ Backup complete: $target_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff_files() {
|
||||||
|
local prefix="${1:-}"
|
||||||
|
if [[ -z "$prefix" ]]; then
|
||||||
|
echo "❌ Please provide a prefix for diff comparison."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
local backup_dir="${BACKUP_DIR}/${prefix}"
|
||||||
|
|
||||||
|
if [[ ! -d "$backup_dir" ]]; then
|
||||||
|
echo "❌ Backup not found: $backup_dir"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🔍 Comparing current files with backup: $backup_dir"
|
||||||
|
for f in "${FILES[@]}"; do
|
||||||
|
local current="${BRAVE_DIR}/${f}"
|
||||||
|
local backup="${backup_dir}/$(basename "$f")"
|
||||||
|
if [[ -f "$current" && -f "$backup" ]]; then
|
||||||
|
echo
|
||||||
|
echo "=== DIFF for $(basename "$f") ==="
|
||||||
|
|
||||||
|
local tmp_current=$(mktemp)
|
||||||
|
# Try pretty-print; if fails, fall back to raw copy
|
||||||
|
if ! jq_pretty "$current" "$tmp_current" >/dev/null; then
|
||||||
|
cp "$current" "$tmp_current"
|
||||||
|
fi
|
||||||
|
|
||||||
|
diff -u "$backup" "$tmp_current" || true
|
||||||
|
rm -f "$tmp_current"
|
||||||
|
else
|
||||||
|
echo "⚠️ Missing file in current or backup for: $(basename "$f")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- MAIN ---
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
backup)
|
||||||
|
backup_files "${2:-}"
|
||||||
|
;;
|
||||||
|
diff)
|
||||||
|
diff_files "${2:-}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage:"
|
||||||
|
echo " $0 backup [prefix] # Backup Brave config files (prettified JSON)"
|
||||||
|
echo " $0 diff <prefix> # Compare with a specific backup"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
42
brave_set_assets.py
Executable file
42
brave_set_assets.py
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
def copy_tree(src_dir, dst_dir):
|
||||||
|
"""Recursively copy all files and folders from src_dir to dst_dir."""
|
||||||
|
for root, dirs, files in os.walk(src_dir):
|
||||||
|
rel_path = os.path.relpath(root, src_dir)
|
||||||
|
dest_root = os.path.join(dst_dir, rel_path) if rel_path != "." else dst_dir
|
||||||
|
os.makedirs(dest_root, exist_ok=True)
|
||||||
|
for file in files:
|
||||||
|
src_file = os.path.join(root, file)
|
||||||
|
dst_file = os.path.join(dest_root, file)
|
||||||
|
shutil.copy2(src_file, dst_file)
|
||||||
|
print(f"✔ Copied: {src_file} → {dst_file}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Source directory (next to this script)
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
assets_dir = os.path.join(script_dir, "assets")
|
||||||
|
|
||||||
|
# Fallback to _assets if assets/ doesn't exist
|
||||||
|
if not os.path.exists(assets_dir):
|
||||||
|
alt_assets_dir = os.path.join(script_dir, "_assets")
|
||||||
|
if os.path.exists(alt_assets_dir):
|
||||||
|
print(f"⚠️ 'assets' not found, using '_assets' instead.")
|
||||||
|
assets_dir = alt_assets_dir
|
||||||
|
else:
|
||||||
|
print(f"❌ Neither 'assets' nor '_assets' directory found in {script_dir}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Destination (Brave profile folder)
|
||||||
|
base_dir = os.path.expanduser("~/Library/Application Support/BraveSoftware/Brave-Browser")
|
||||||
|
|
||||||
|
# Copy everything from assets → Brave-Browser
|
||||||
|
copy_tree(assets_dir, base_dir)
|
||||||
|
|
||||||
|
print("\n✅ Brave configuration copied successfully.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
135
brave_set_policies.py
Executable file
135
brave_set_policies.py
Executable file
@@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
BUNDLE_ID = "com.brave.Browser"
|
||||||
|
# BUNDLE_ID = "com.google.chrome"
|
||||||
|
MANAGED_PLIST = f"/Library/Managed Preferences/{BUNDLE_ID}.plist"
|
||||||
|
|
||||||
|
# === Brave-specific feature lockdown ===
|
||||||
|
managed_policies = {
|
||||||
|
# "RestoreOnStartup": 5, # Open new tab on startup
|
||||||
|
# "HomepageIsNewTabPage": True, # Use New Tab as homepage
|
||||||
|
"AutofillAddressEnabled": False, # Disable address autofill
|
||||||
|
"AutofillCreditCardEnabled": False, # Disable credit card autofill
|
||||||
|
"BackgroundModeEnabled": False, # Disable background tasks
|
||||||
|
"BookmarkBarEnabled": False, # Disable bookmark bar
|
||||||
|
"BraveAIChatEnabled": False, # Disable Brave AI features
|
||||||
|
"BraveNewsDisabled": True, # Disable Brave News
|
||||||
|
"BravePlaylistEnabled": False, # Disable Brave Playlist
|
||||||
|
"BraveRewardsDisabled": True, # Disable Brave Rewards
|
||||||
|
"BraveSpeedreaderEnabled": False, # Disable Speedreader
|
||||||
|
"BraveStatsPingEnabled": False, # Disable telemetry pings
|
||||||
|
"BraveTalkDisabled": True, # Disable Brave Talk
|
||||||
|
"BraveVPNDisabled": True, # Disable Brave VPN
|
||||||
|
"BraveWalletDisabled": True, # Disable Brave Wallet
|
||||||
|
"BraveWalletShowInToolbar": False, # Hide wallet icon
|
||||||
|
"BraveWebDiscoveryEnabled": False, # Disable web discovery
|
||||||
|
"BrowserSignin": 0, # Disable browser sign-in
|
||||||
|
"DefaultGeolocationSetting": 2, # Block location access
|
||||||
|
"EnableMediaRouter": False, # Disable Google Cast
|
||||||
|
"GoogleSearchSidePanelEnabled": False, # Disable Google Search side panel
|
||||||
|
"PasswordLeakDetectionEnabled": False, # Disable password leak check
|
||||||
|
"PasswordManagerEnabled": False, # Disable password manager
|
||||||
|
"PasswordManagerPasskeysEnabled": False, # Disable passkeys
|
||||||
|
"PasswordSharingEnabled": False, # Disable password sharing
|
||||||
|
"PaymentMethodQueryEnabled": False, # Disable payment autofill
|
||||||
|
"PrivacySandboxAdMeasurementEnabled": False, # Disable Privacy Sandbox ads
|
||||||
|
"PrivacySandboxAdTopicsEnabled": False, # Disable ad topics
|
||||||
|
"PrivacySandboxPromptEnabled": False, # Disable Privacy Sandbox prompt
|
||||||
|
"PrivacySandboxSiteEnabledAdsEnabled": False, # Disable site-enabled ads
|
||||||
|
"PromotionsEnabled": False, # Disable promotional content
|
||||||
|
"ShowHomeButton": False, # Hide Home button
|
||||||
|
"SideSearchEnabled": False, # Disable side search
|
||||||
|
"SpellcheckEnabled": False, # Disable spellcheck
|
||||||
|
"SuggestedContentEnabled": False, # Disable content suggestions
|
||||||
|
"SyncDisabled": True, # Disable Brave Sync
|
||||||
|
"TorDisabled": True, # Disable Tor integration
|
||||||
|
"TranslateEnabled": False, # Disable translate feature
|
||||||
|
"UserFeedbackAllowed": False, # Disable sending feedback
|
||||||
|
"DeviceMetricsReportingEnabled": False,
|
||||||
|
# "MetricsReportingEnabled": False,
|
||||||
|
"SafeBrowsingExtendedReportingEnabled": False,
|
||||||
|
"DefaultBrowserSettingEnabled": False,
|
||||||
|
"AlternateErrorPagesEnabled": False,
|
||||||
|
"URLKeyedAnonymizedDataCollectionEnabled": False,
|
||||||
|
"SpellCheckServiceEnabled": False,
|
||||||
|
"SearchSuggestEnabled": False,
|
||||||
|
"SigninInterceptionEnabled": False
|
||||||
|
}
|
||||||
|
|
||||||
|
def run(cmd, use_sudo=False, silent=False):
|
||||||
|
if use_sudo:
|
||||||
|
cmd = ["sudo"] + cmd
|
||||||
|
if not silent:
|
||||||
|
print("→", " ".join(cmd))
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
def keep_sudo_alive():
|
||||||
|
"""Refresh sudo timestamp every 60 s."""
|
||||||
|
while True:
|
||||||
|
subprocess.run(["sudo", "-v"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
|
time.sleep(60)
|
||||||
|
|
||||||
|
def ensure_managed_dir():
|
||||||
|
os.makedirs("/Library/Managed Preferences", exist_ok=True)
|
||||||
|
run(["chown", "root:wheel", "/Library/Managed Preferences"], use_sudo=True)
|
||||||
|
run(["chmod", "755", "/Library/Managed Preferences"], use_sudo=True)
|
||||||
|
|
||||||
|
def set_policy(key, value):
|
||||||
|
# Remove existing key before adding (avoid duplicate errors)
|
||||||
|
subprocess.run(
|
||||||
|
["sudo", "/usr/libexec/PlistBuddy", "-c", f"Delete :{key}", MANAGED_PLIST],
|
||||||
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
||||||
|
)
|
||||||
|
# Choose correct PlistBuddy type
|
||||||
|
if isinstance(value, bool):
|
||||||
|
cmd = ["Add", f":{key}", "bool", "true" if value else "false"]
|
||||||
|
elif isinstance(value, int):
|
||||||
|
cmd = ["Add", f":{key}", "integer", str(value)]
|
||||||
|
elif isinstance(value, str):
|
||||||
|
cmd = ["Add", f":{key}", "string", value]
|
||||||
|
elif isinstance(value, list):
|
||||||
|
# array
|
||||||
|
run(["/usr/libexec/PlistBuddy", "-c", f"Add :{key} array", MANAGED_PLIST], use_sudo=True)
|
||||||
|
for v in value:
|
||||||
|
run(["/usr/libexec/PlistBuddy", "-c", f"Add :{key}: string {v}", MANAGED_PLIST], use_sudo=True)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Unsupported type for key {key}")
|
||||||
|
return
|
||||||
|
run(["/usr/libexec/PlistBuddy", "-c", " ".join(cmd), MANAGED_PLIST], use_sudo=True)
|
||||||
|
|
||||||
|
def set_managed_policies():
|
||||||
|
ensure_managed_dir()
|
||||||
|
for key, value in managed_policies.items():
|
||||||
|
set_policy(key, value)
|
||||||
|
|
||||||
|
def refresh_preferences():
|
||||||
|
run(["killall", "cfprefsd"], use_sudo=True)
|
||||||
|
|
||||||
|
def cleanup_brave_data():
|
||||||
|
"""Optionally remove crypto-related folders."""
|
||||||
|
profile = os.path.expanduser("~/Library/Application Support/BraveSoftware/Brave-Browser/Default")
|
||||||
|
for folder in ["brave_rewards", "ethereum_wallet", "brave_vpn", "ai_chat"]:
|
||||||
|
path = os.path.join(profile, folder)
|
||||||
|
if os.path.exists(path):
|
||||||
|
print(f"🧹 Removing {path}")
|
||||||
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("🔐 Applying full Brave Browser hardening policies (mandatory).")
|
||||||
|
subprocess.run(["sudo", "-v"], check=True) # ask for password once
|
||||||
|
threading.Thread(target=keep_sudo_alive, daemon=True).start()
|
||||||
|
|
||||||
|
set_managed_policies()
|
||||||
|
cleanup_brave_data()
|
||||||
|
refresh_preferences()
|
||||||
|
|
||||||
|
print(f"\n✅ All mandatory policies applied under:\n {MANAGED_PLIST}")
|
||||||
|
print(" Restart Brave and check brave://policy — all should show Level = Mandatory.")
|
||||||
|
print(" You can re-run this script anytime to refresh or update settings.")
|
||||||
|
|
||||||
8
brave_update_assets.sh
Executable file
8
brave_update_assets.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BR_PATH="$HOME/Library/Application Support/BraveSoftware/Brave-Browser"
|
||||||
|
cp -r ./_assets ./assets
|
||||||
|
cp "${BR_PATH}/Local State" ./assets
|
||||||
|
cp "${BR_PATH}/Default/Preferences" ./assets/Default
|
||||||
|
cp "${BR_PATH}/Default/Secure Preferences" ./assets/Default
|
||||||
|
|
||||||
114
policies/com.brave.Browser.plist
Normal file
114
policies/com.brave.Browser.plist
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>AlternateErrorPagesEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>AutofillAddressEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>AutofillCreditCardEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BackgroundModeEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BookmarkBarEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BraveAIChatEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BraveNewsDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>BravePlaylistEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BraveRewardsDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>BraveSpeedreaderEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BraveStatsPingEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BraveTalkDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>BraveVPNDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>BraveWalletDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>BraveWalletShowInToolbar</key>
|
||||||
|
<false/>
|
||||||
|
<key>BraveWebDiscoveryEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>BrowserSignin</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>DefaultBrowserSettingEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>DefaultGeolocationSetting</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
<key>DeviceMetricsReportingEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>EnableMediaRouter</key>
|
||||||
|
<false/>
|
||||||
|
<key>GoogleSearchSidePanelEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PasswordLeakDetectionEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PasswordManagerEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PasswordManagerPasskeysEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PasswordSharingEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PaymentMethodQueryEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PrivacySandboxAdMeasurementEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PrivacySandboxAdTopicsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PrivacySandboxPromptEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PrivacySandboxSiteEnabledAdsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>PromotionsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SafeBrowsingExtendedReportingEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SearchSuggestEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>ShowHomeButton</key>
|
||||||
|
<false/>
|
||||||
|
<key>SideSearchEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SigninInterceptionEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SpellCheckServiceEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SpellcheckEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SuggestedContentEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>SyncDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>TorDisabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>TranslateEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>URLKeyedAnonymizedDataCollectionEnabled</key>
|
||||||
|
<false/>
|
||||||
|
<key>UserFeedbackAllowed</key>
|
||||||
|
<false/>
|
||||||
|
<key>ExtensionSettings</key>
|
||||||
|
<dict>
|
||||||
|
<key>ghmbeldphafepmbegfdlkpapadhbakde</key>
|
||||||
|
<dict>
|
||||||
|
<key>installation_mode</key>
|
||||||
|
<string>force_installed</string>
|
||||||
|
<key>update_url</key>
|
||||||
|
<string>https://clients2.google.com/service/update2/crx</string>
|
||||||
|
<key>toolbar_pin</key>
|
||||||
|
<string>force_pinned</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>DefaultSearchProviderEnabled</key><true/>
|
||||||
|
<key>DefaultSearchProviderName</key><string>Brave</string>
|
||||||
|
<key>DefaultSearchProviderSearchURL</key><string>https://search.brave.com/search?q={searchTerms}</string>
|
||||||
|
<key>DefaultSearchProviderSuggestURL</key><string>https://search.brave.com/api/suggest?q={searchTerms}</string>
|
||||||
|
<key>DefaultSearchProviderKeyword</key><string>brave</string>
|
||||||
|
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Reference in New Issue
Block a user