mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-19 16:54:47 +00:00
* fix(agents): scope provider SSRF trust by origin * fix(provider): preserve explicit private-network deny * docs(provider): document exact-origin SSRF trust * test(provider): cover exact-origin SSRF edges * docs(provider): align local model private-origin guidance * refactor(ssrf): keep policy merging in infra * test(ssrf): cover exact-origin trust through guard * test(ssrf): block sibling private-origin redirects * fix(provider): keep loopback trust origin-scoped * fix(provider): block metadata origin trust * fix(ssrf): keep metadata rebinding blocked * fix(ssrf): block cloud metadata origins * fix(ssrf): block ipv6 metadata origins * fix(ssrf): block embedded metadata origins * test(ssrf): cover embedded link-local metadata * test(provider): cover custom anthropic proxy classification * test(provider): widen transport policy mock * test(plugin-sdk): assert metadata-IP allowedOrigins entries are rejected Plugin authors can construct an SsrFPolicy that lists any well-formed http(s) origin in allowedOrigins. The abuse-resistance lives one layer deeper, in resolvePinnedHostnameWithPolicy's metadata/link-local block. Add an SDK-level smoke test asserting that contract directly: - AWS/Alibaba IMDS IPv4 literals, GCP metadata canonical hostname, IPv6 ULA metadata literal, and non-metadata link-local IPv4 entries build a policy via ssrfPolicyFromHttpBaseUrlAllowedOrigin and are then rejected at resolvePinnedHostnameWithPolicy. - DNS rebinding from a trusted private DNS origin to a metadata IP is rejected even when the request hostname is origin-trusted. This would fail if the SDK helper or resolveSsrFPolicyForUrl ever short-circuited past the metadata block. * chore(docs): regenerate baselines after upstream rebase upstream/main moved between rebases; the merged source state for the PR's `src/config/schema.help.ts` change and the upstream plugin-sdk surface changes both produce different hashes than the committed baselines, so `config:docs:check` and `plugin-sdk:api:check` would fail. Regenerated via `pnpm config:docs:gen` + `pnpm plugin-sdk:api:gen` on Crabbox; both baselines verified with their respective `--check` generators. * test(plugin-sdk): assert SSRF blocked error class * fix(lint): satisfy exact-origin PR lint rules * docs: clarify custom provider origin trust * chore(docs): refresh plugin sdk api baseline --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
// Narrow SSRF helpers for extensions that need pinned-dispatcher and policy
|
|
// utilities without loading the full infra-runtime surface.
|
|
|
|
export {
|
|
closeDispatcher,
|
|
createPinnedDispatcher,
|
|
SsrFBlockedError,
|
|
isBlockedHostnameOrIp,
|
|
isPrivateIpAddress,
|
|
resolvePinnedHostname,
|
|
resolvePinnedHostnameWithPolicy,
|
|
resolveSsrFPolicyForUrl,
|
|
ssrfPolicyFromHttpBaseUrlAllowedHostname,
|
|
ssrfPolicyFromHttpBaseUrlAllowedOrigin,
|
|
type LookupFn,
|
|
type SsrFPolicy,
|
|
} from "../infra/net/ssrf.js";
|
|
export { formatErrorMessage } from "../infra/errors.js";
|
|
export { fetchWithSsrFGuard } from "../infra/net/fetch-guard.js";
|
|
export {
|
|
assertHttpUrlTargetsPrivateNetwork,
|
|
buildHostnameAllowlistPolicyFromSuffixAllowlist,
|
|
createLegacyPrivateNetworkDoctorContract,
|
|
hasLegacyFlatAllowPrivateNetworkAlias,
|
|
isPrivateNetworkOptInEnabled,
|
|
mergeSsrFPolicies,
|
|
migrateLegacyFlatAllowPrivateNetworkAlias,
|
|
ssrfPolicyFromDangerouslyAllowPrivateNetwork,
|
|
ssrfPolicyFromPrivateNetworkOptIn,
|
|
ssrfPolicyFromAllowPrivateNetwork,
|
|
} from "./ssrf-policy.js";
|
|
export { isPrivateOrLoopbackHost } from "../gateway/net.js";
|