SafeToOpenBrowser Security Docs

SafeToOpen Browser Security

Linux: Chrome and Edge

JSON policy files under /etc, delivered by Ansible, Puppet, Landscape or any package

Guide 10 of 11 · April 2026

On Linux, Chrome and Edge read policy from JSON files. Force-install and the four enrolment values are two small files per browser, owned by root. Anything that can place files on a machine (Ansible, Puppet, Salt, Chef, Canonical Landscape, a .deb or .rpm you build, or a first-boot script) can deploy SafeToOpen. Per-user values come from the login name and the hostname at file-creation time.

BrowserPolicy directoryExtension policy directory
Google Chrome/etc/opt/chrome/policies/managed//etc/opt/chrome/policies/managed/ (same directory, key 3rdparty)
Chromium/etc/chromium/policies/managed/same
Microsoft Edge/etc/opt/edge/policies/managed/same

1. Force-install#

# /etc/opt/chrome/policies/managed/safetoopen-install.json
{ "ExtensionInstallForcelist": ["ekfkopmgnijagfmjgcjkbffcnmggekec;https://clients2.google.com/service/update2/crx"] }

# /etc/opt/edge/policies/managed/safetoopen-install.json
{ "ExtensionInstallForcelist": ["bbgoikmidjfiaaadlgkpdlppilhkjfke;https://edge.microsoft.com/extensionwebstorebase/v1/crx"] }

2. Enrolment values#

Extension policy on Linux lives under the 3rdparty key of the browser policy, keyed by extension ID:

# /etc/opt/chrome/policies/managed/safetoopen-enrol.json
{
  "3rdparty": {
    "extensions": {
      "ekfkopmgnijagfmjgcjkbffcnmggekec": {
        "enrol_key":   "PASTE-ENROLMENT-KEY",
        "user_name":   "[email protected]",
        "asset_name":  "ws-0421",
        "domain_name": ""
      }
    }
  }
}

Edge: the same file under /etc/opt/edge/policies/managed/ with the Edge ID. Files must be readable by all users (0644) and the directories owned by root; the browser ignores world-writable policy files.

3. A first-boot or config-management script#

#!/bin/bash
# Writes SafeToOpen policy for Chrome and Edge. Run as root at provisioning or on a timer.
KEY="PASTE-ENROLMENT-KEY"; WS=""
USER_NAME="$(logname 2>/dev/null || who | awk 'NR==1{print $1}')"
ASSET="$(hostname -s)"
for b in "chrome ekfkopmgnijagfmjgcjkbffcnmggekec https://clients2.google.com/service/update2/crx" "edge bbgoikmidjfiaaadlgkpdlppilhkjfke https://edge.microsoft.com/extensionwebstorebase/v1/crx"; do
  set -- $b; D="/etc/opt/$1/policies/managed"; ID=$2; UPD=$3
  install -d -m 755 "$D"
  printf '{ "ExtensionInstallForcelist": ["%s;%s"] }\n' "$ID" "$UPD" > "$D/safetoopen-install.json"
  cat > "$D/safetoopen-enrol.json" <<EOT
{ "3rdparty": { "extensions": { "$ID": {
  "enrol_key": "$KEY", "user_name": "$USER_NAME", "asset_name": "$ASSET", "domain_name": "$WS" } } } }
EOT
  chmod 644 "$D"/safetoopen-*.json
done

Ansible#

- name: SafeToOpen Chrome policy
  ansible.builtin.template:
    src: safetoopen-enrol.json.j2      # uses {{ ansible_user_id }} / {{ inventory_hostname_short }}
    dest: /etc/opt/chrome/policies/managed/safetoopen-enrol.json
    owner: root
    mode: "0644"
Note Multi-user Linux workstations: write the file at login from a PAM or systemd user hook, or use DOMAIN\login-style values with the email domain set in the console. The extension re-reads policy files within minutes; a browser restart is immediate.

4. Verify#

  1. chrome://policy → Reload policies. ExtensionInstallForcelist lists the ID; the extension section shows the four values. A red “error” beside a policy means a JSON syntax problem in the file.
  2. Console → Settings → Unattended enrolment → Enrolled devices shows the workstation.