- Provider options, labels, and base-URL placeholders now come from
PROVIDER_INFO instead of hand-copied lists (fixes SiliconFlow .com/.cn
placeholder drift; panel names now match the model-config dialog)
- Replace free-text subgroup strings + SUBGROUP_PROVIDERS reverse map
with a typed provider field on SettingDef
- Precompute SETTINGS_BY_GROUP and PROVIDER_SUBGROUPS at module level
- Merge justSaved into saveMessage, drop unused mainRef, hoist
fetchSettings out of the component, dedupe savedText logic
- Serialize from SETTINGS_REGISTRY directly; json validators in a map
instead of a hardcoded key check
- Make allowPrivateUrls a function so ALLOW_PRIVATE_URLS edits in the
admin panel apply without restart
* fix: block private IPv6 URLs
* fix: cover full fe80::/10 link-local range and :: unspecified
- Replace startsWith("fe80:") with a check covering the full fe80::/10
range (fe80 through febf) per RFC 4291.
- Add :: (unspecified) to the localhost block.
- Drop the dead 0:0:0:0:0:0:0:1 branch (URL parser normalizes it to ::1).
- Add tests for fe9f::1, febf::1, and ::.
---------
Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
/api/parse-url accepted any URL the user submitted, fetched it via
@extractus/article-extractor, and returned the body as Markdown. With
ALLOW_PRIVATE_URLS unset (the default after #600) the SSRF guard
short-circuited entirely, so an unauthenticated POST could probe
container ports, read AWS IMDS / GCP metadata, and reach same-VPC
internal services.
- parse-url now always rejects private URLs regardless of
ALLOW_PRIVATE_URLS. The flag's only legitimate use case is local
LLM provider baseUrl overrides (validate-model, chat); article
extraction has no business fetching internal hosts. Local LLM
setups (Ollama, LM Studio, etc.) are unaffected.
- Strip a trailing dot from the hostname before equality checks so
the FQDN form "localhost." (which still resolves to 127.0.0.1) is
caught by the existing string match.
Known follow-ups (not addressed here):
- DNS rebinding: hostnames are matched as strings; a public domain
resolving to 127.0.0.1 (e.g. localtest.me) is not caught.
- HTTP redirects: @extractus/article-extractor uses cross-fetch with
default redirect: "follow" and exposes no hook, so a public URL
302-ing to an internal host still leaks.
* fix: allow private URLs by default for reverse proxy setups
Fixes#588 - Users with reverse proxy setups (e.g., Antigravity tools)
were getting "Invalid base URL" errors due to SSRF protection blocking
private/internal URLs.
Changes:
- Add ALLOW_PRIVATE_URLS env var (defaults to true)
- Set to "false" to enable strict SSRF protection if needed
* refactor: extract isPrivateUrl to shared utility