2.0.0-prerelease3, and how to migrate.
Running Bifrost Enterprise? This page covers the OSS behavior only. See the Enterprise v2.0.0 Migration Guide for how these changes interact with SCIM-based authentication.
Breaking Change 1: Custom Plugin Downloads Are Now SSRF-Protected
Starting in2.0.0-prerelease3, downloading a custom plugin binary (a path pointing at an http(s) URL) is hardened against server-side request forgery.
What changed: plugin downloads no longer succeed if the URL resolves to a loopback, private (RFC 1918), CGNAT, link-local, or otherwise non-public address.
This applies to plugins defined in
config.json too, not just ones added through the admin API. Every custom plugin path is re-verified on every server restart, regardless of whether it was configured via config.json or POST/PUT /api/plugins: there is no config-file exemption from the SSRF check..so on an internal artifact server, localhost, or any other private-network URL.
How to fix it: add the internal host to the new deploy-time allowlist, server.plugin_download_private_allowlist in config.json. Entries can be hostnames, IP addresses, or CIDR ranges.
Before (breaks after upgrading to 2.0.0-prerelease3 - the plugin’s path resolves to a private-network host, so DownloadPlugin now refuses it):
path; the allowlist entry is the only change):
This setting is deploy-time only: it is read from
config.json/environment at server startup and cannot be changed through the plugin admin API. An invalid entry (not a valid hostname, IP, or CIDR) fails server startup with an error naming the entry..so file into the container/host and reference it by local file path instead of a URL; local paths are unaffected by this change.
Custom LLM providers are not affected. This hardening applies only to downloading native plugin (
.so) binaries via framework/plugins. Custom providers (an LLM endpoint registered with a custom base_url, e.g. a self-hosted or OpenAI-compatible server) use a separate, unmodified mechanism (the existing per-provider allow_private_network setting) and are untouched by this change or by server.plugin_download_private_allowlist.Breaking Change 2: Custom Plugin Creation and Update Now Requires Admin Authentication
Starting in2.0.0-prerelease3, creating or updating a custom-path plugin requires genuine admin authentication: it is no longer allowed through on a request that only passed because dashboard auth is disabled or unconfigured. Any of Bifrost’s supported admin authentication methods (Basic auth or a dashboard session) satisfies this; no particular method is required.
What changed: POST /api/plugins and PUT /api/plugins/{name} now reject a request that sets a custom path if the caller reached the endpoint only because dashboard auth is disabled or unconfigured.
Who is affected: deployments that run with dashboard auth disabled or unconfigured and manage custom-path plugins through the admin API in that mode.
How to fix it: enable and configure dashboard auth, then authenticate as admin (Basic auth or a dashboard session, either is sufficient) before creating or updating a plugin with a custom path.
Only adding or updating a custom (path-based) plugin requires admin login. The auth check only runs when
path is set on a non-built-in plugin: built-in plugins, and any plugin management that doesn’t touch path, are unaffected.Plugins defined directly in
config.json are not affected by this specific check. This auth requirement only runs inside the POST /api/plugins / PUT /api/plugins/{name} HTTP handlers. A plugin listed in config.json’s plugins array loads at server startup through a completely separate code path (loadCustomPlugins) that never calls those handlers: it loads the same way regardless of your dashboard auth configuration. (It is still subject to Breaking Change 1’s SSRF check above if its path is a URL.)Migration Checklist
1
Check for internally-hosted custom plugins
Look at every entry in
config.json’s plugins list (or the equivalent admin-API-managed plugin configs) for a path that is an http:// or https:// URL pointing at a private, loopback, or otherwise internal address.2
Allowlist internal plugin hosts, or switch to a local file path
For any internal URL found above, add the host (or its CIDR) to
server.plugin_download_private_allowlist in config.json, or mount the binary locally and use a file path instead.3
Confirm dashboard auth is configured before creating a custom-path plugin
If dashboard auth is disabled or unconfigured,
POST /api/plugins and PUT /api/plugins/{name} will now reject any request that sets a custom path. Enable dashboard authentication first if you need to register a plugin with a custom binary path.
