Skip to content

System Policy

Settings an administrator applies to a machine, in a file only an administrator can write. Most of them are mandates: a user who sets the same thing through a flag, an environment variable or their own configuration is refused or warned, rather than quietly winning.

Where policy is read from

Platform Sources, in the order they are merged
Linux, macOS /etc/bb/config.yaml
Windows %ProgramData%\bb\config.yaml, then HKEY_LOCAL_MACHINE\Software\Policies\bb

Later sources win, so on Windows a registry value overrides the same key in the file. %ProgramData% is resolved through the Windows known-folder API rather than read from the environment, so setting a ProgramData variable cannot redirect where policy comes from.

Keys may sit at the top level of the file, under a policies: mapping, or under policy:. All three are read, in that order, and a later one wins. Every key follows this order, including update_base_url.

policies:
  require_keyring: true
  allowed_hosts:
    - https://bitbucket.example.com
  disable_update: true

Windows registry values

Under HKEY_LOCAL_MACHINE\Software\Policies\bb, each key above has a value with a different name and a registry type. The names are not the YAML spellings:

Value name Type YAML key
RequireKeyring boolean require_keyring
AllowedHosts REG_MULTI_SZ, or a comma-separated REG_SZ allowed_hosts
CAFile REG_SZ ca_file
AllowInsecureSkipVerify boolean allow_insecure_skip_verify
DisableUpdate boolean disable_update
UpdateBaseURL REG_SZ update_base_url
AllowHTTPUpdate boolean allow_http_update
UpdateTrustedRoot REG_SZ update_trusted_root
UpdateTUFURL REG_SZ update_tuf_url
UpdateSignatureIdentity REG_SZ update_signature_identity
UpdateSignatureIssuer REG_SZ update_signature_issuer
AllowUnverifiedUpdate boolean allow_unverified_update

A boolean is a REG_DWORD of 0 or 1, or a REG_SZ. A REG_DWORD other than 0 reads as true. The string form takes the spellings an administrator is likely to write, in any case: true/false, 1/0, yes/no, on/off, enable/disable, enabled/disabled.

A value bb cannot read is not treated as unset. The restrictive side of that control applies until it is corrected — keyring storage mandated, insecure TLS refused, updates disabled, plain-HTTP updates refused, unverified updates refused — and bb doctor reports the value and what is in force meanwhile.

An empty string value is treated as unset, so a REG_SZ left blank does not mandate an empty path or an empty host list.

The environment variables a user sets take the same two spellings and no others: BB_ALLOW_HTTP_UPDATE=yes is refused with BB_ALLOW_HTTP_UPDATE must be true or false (or 1 or 0) and the run fails.

mcp_audit_file has no registry value. Mandating where bb ai mcp serve writes its audit trail on Windows needs %ProgramData%\bb\config.yaml.

Check that a policy took effect

bb doctor

Run it on a machine after deploying policy. It needs no host and no network, and its Settings section gives each effective setting with where it came from, naming the registry when that is the answer. A value that does not appear there is one bb did not read — check the value's name and type against the table above.

Keys

Key Type Effect
require_keyring boolean Mandate OS keyring storage for credentials and prohibit the plaintext config file fallback.
allowed_hosts list of strings Permitted Bitbucket instances, written as full URLs or bare hostnames. A host outside the list is refused with exit 3 before any request is made. See the note below on what an entry does and does not constrain.
ca_file string Path to a PEM CA bundle that bb must use.
allow_insecure_skip_verify boolean When false, --insecure-skip-verify cannot be enabled.
disable_update boolean Disable bb update machine-wide.
update_base_url string Base URL of an internal release manifest and asset mirror.
allow_http_update boolean Whether bb update may fetch over plain HTTP. false refuses http:// update URLs and --allow-http for every user; true permits plain HTTP for every user. See below.
mcp_audit_file string Mandate where bb ai mcp serve writes its JSON Lines audit trail. Accepts a path or the literal stderr.
update_trusted_root string Path to a Sigstore trusted_root.json, so release signatures verify without reaching the Sigstore TUF CDN.
update_tuf_url string Base URL of an internally mirrored Sigstore TUF repository. Mutually exclusive with update_trusted_root.
update_signature_identity string Expected certificate SAN of the release signer, for organisations that re-sign mirrored artifacts.
update_signature_issuer string Expected OIDC issuer of the release signer.
allow_unverified_update boolean Permit bb update without Sigstore signature verification. A last resort; SHA256 checksum verification still applies.

allowed_hosts constrains the host, not the port or the path

An entry matches when the whole normalised URL is equal, or when the hostnames match. The second case is what most entries hit, and it ignores scheme, port and context path — so https://bitbucket.example.com in the list also permits https://bitbucket.example.com:9999/anything.

That is usually what an administrator wants, since one Bitbucket instance can be reached several ways. It is worth knowing before treating the list as a defence against a rogue service on the same host.

What a user meets when policy refuses them

Policy does not fail silently, and the message names policy as the reason:

  • A host outside allowed_hosts is refused before any request is sent.
  • A --ca-file naming a different bundle from the mandated one is an error; omitting it uses the mandated bundle.
  • BB_REQUIRE_KEYRING=false against require_keyring: true is ignored, and bb prints a warning saying policy mandates keyring storage.
  • bb update under disable_update exits 3 (authorization) and says to use the system package manager.
  • --allow-http or BB_ALLOW_HTTP_UPDATE under allow_http_update: false exits 3, and so does an http:// update URL.

update_base_url is a default, not a mandate

It is the one key here a user can override. The updater takes the first of --base-url, BB_UPDATE_BASE_URL, the workspace configuration, the user's stored configuration, and only then policy — so setting it in policy supplies a mirror to anyone who has not chosen one, and does not pin them to it.

Use disable_update: true where the requirement is that a machine never fetches its own binary. Setting update_base_url alone does not achieve that.

Update URLs are https unless someone asks for plain HTTP

bb update fetches over https only: the base URL, every asset URL a manifest names, and every redirect along the way. A user permits plain HTTP explicitly, with bb update --allow-http or BB_ALLOW_HTTP_UPDATE=1, and every run that uses it warns on stderr. There is no configuration file key for it, because a workspace file arrives with a cloned repository.

allow_http_update overrides the user in both directions when policy sets it. false refuses the opt-in and every http:// update URL, whatever the user passes. true permits plain HTTP for everyone, for a fleet whose internal mirror has no TLS.

Update trust is settable from policy only

update_trusted_root, update_tuf_url, update_signature_identity, update_signature_issuer and allow_unverified_update are read from policy and from nowhere else — there is no flag and no environment variable for any of them, and the names above are ignored if exported.

That asymmetry is deliberate rather than an oversight. These five decide who may vouch for a new bb binary, so a value settable by anything that can write a variable into a shell would let that thing approve its own update.

See also