Network boundary
How Scrydon limits the network — egress policy, ingress termination, and the cluster perimeter.
Scrydon's network model is shaped by one principle: the customer cluster is the trust boundary. Everything inside it is enforced by mTLS and capability checks; everything outside is treated as untrusted.
Inbound
Inbound traffic terminates at Traefik. Three classes of routes:
| Route class | Authenticated as | Where |
|---|---|---|
| User-facing app | User session (SSO + Better Auth) | Workflow editor, settings, chat, voice |
| Workflow API | API key (workflow-scoped) | POST /api/workflows/{id}/execute |
| Public assets | None | /favicon.ico, /health (liveness/readiness only) |
There are no public endpoints that expose customer data. The /health endpoint returns only platform liveness — it does not leak version, configuration, or tenant data.
See Ingress hardening for the header-stripping and TLS-termination rules.
Outbound
Outbound traffic falls into four buckets:
| Bucket | Required? | Where |
|---|---|---|
| License heartbeat | Yes, for licensed operation | license.scrydon.com — daily POST, 30-day grace window |
| Vendor calls | Opt-in per integration | The endpoints declared by installed integrations (OpenAI, Microsoft Graph, etc.) |
| Governed sandbox fetches | Opt-in per organization policy | Sandboxed notebooks and reviewed workflow integrations |
| Yes, for sign-in and invitations | The mail server you configure — your own SMTP server by default (Mail provider) |
Nothing else leaves the cluster. No telemetry, no error reporting to Scrydon, no anonymous analytics. AI-assistant (Chat/Cortex) LLM calls are brokered in-platform to the organization's configured vendor — they appear in the Vendor calls row above, not as a separate Scrydon-hosted egress. If your security policy requires a tightly scoped egress allowlist, the license endpoint, your mail server, and whatever installed integrations declare are the entire list.
Keeping model traffic to one provider
A Kubernetes NetworkPolicy works on IP addresses and ports, not host names, so it cannot tell api.openai.com from any other public HTTPS endpoint. With network policies and managed extension execution on, the chart allows the extension host to reach public addresses on port 443 and leaves the choice of destination to the vendor broker. The broker admits only the hosts each installed extension declares.
So the way to keep model traffic (LLM, speech, embeddings) to a single provider is to install and enable only that provider's extension. To add a network-level control as well, send outbound traffic through an egress proxy or firewall that filters by host name, and narrow networkPolicies.providerEgress.ipBlocks to that proxy's address range.
Email is not covered by any chart rule. When networkPolicies.enabled is on, add a NetworkPolicy that lets the auth, platform and api-agentic pods reach your mail server's address and port.
Air-gapped mode
In true air-gapped deployments, you can:
- Operate offline-only: skip the license heartbeat. Operations continue under your contractual licence; phone-home is disabled.
- Lock vendor integrations to self-hosted providers only. No outbound vendor calls happen. If no reachable LLM provider is configured, the AI assistant (Chat/Cortex) has no model to call and will be unavailable; the rest of the platform is unaffected.
See Deployment → Air-gapped for the full procedure.
Egress allowlist
For non-air-gapped deployments, the recommended egress policy is:
ALLOW license.scrydon.com:443 # required
ALLOW <endpoints declared by installed integrations>
DENY * # everything elseThe AI assistant's LLM calls go to the organization's configured provider (e.g. api.openai.com) and are covered by the "installed integrations" line above.
The platform never makes outbound calls to anything not in that list. The list is auditable from Settings → Platform → Extensions (each installed integration lists its declared egress endpoints).
A vendor's declared egress endpoints are part of the integration manifest, validated at install time, and rejected if they would expand the egress surface beyond the org's configured allowlist.
Organization egress policy
Settings → Governance → Egress controls destinations reached by sandboxed notebooks and by reviewed workflow integrations that use Scrydon's controlled fetch. In allowlist mode, a destination must match a configured domain (or an enabled Scrydon default) before any connection is opened. For these requests a missing, invalid, or temporarily unavailable policy denies the request; declarative data-source polls treat a missing policy differently (below).
A destination matches an allowlist or denylist entry regardless of letter case,
a trailing dot or IPv6 brackets, on either the entry or the destination, so
Feed.Example. and feed.example are the same domain.
An entry may name one port, such as feed.example:8443:
- On the allowlist, a port-scoped entry admits the domain on that port
only. An entry without a port admits every port. A URL without a port uses
its scheme's port, so
feed.example:443admitshttps://feed.exampleand nothing onhttps://feed.example:8443. - On the denylist, the port is ignored:
feed.example:8443blocksfeed.exampleon every port. - Some connections are only ever made on port 443: an extension's calls through the extension egress broker, and traffic leaving a microVM sandbox. An allowlist entry scoped to any other port admits nothing for them.
- An entry that can match nothing — a port of 0 or above 65535, or more than one port — is refused when the policy is saved.
Redirects do not bypass this decision. Scrydon evaluates the new hostname and
repeats DNS and address validation before each redirected connection. Policy
denials are recorded as egress.blocked audit events without request headers,
bodies, credentials, or full URLs.
The same policy governs declarative data-source polls, decided before any
credential is resolved or any DNS lookup is made. Polls follow the allowlist
and the denylist, but the Scrydon default package domains do not apply to them,
and Vendor-declared domains cannot admit a poll host. Polls do not follow
redirects at all: a poll that receives one fails instead of re-evaluating the
new host. With no policy at
all, polls are limited only by the public-HTTPS rules (loopback, private-host,
and plain-HTTP URLs are always refused). A policy that cannot be read refuses
the poll. A refused poll fails with the message "Outbound request blocked by
organization egress policy" and the reason is recorded on the source. An
on-demand fetch from a source that names a refused host is answered
CAPABILITY_NOT_CONFIGURED (409), the same answer as an unapproved connection
endpoint, because an administrator fixes both by allowlisting the host.
Vendor-declared domains
An integration declares the destinations its tools contact in its manifest. With Vendor-declared domains enabled (the default), those destinations are permitted without also listing them in your allowlist — so installing an integration does not require you to first discover which hosts it needs.
The domains an integration declares are shown on its setup screen, above the credential fields, so you can see what you are permitting before you connect an account.
Bounds that still apply:
- A domain on your denylist stays blocked. A manifest cannot reverse it.
- Only declared domains are permitted. Anything else is denied as before.
- Private, loopback, link-local, and metadata addresses remain denied.
Consider turning this off if your organization requires every destination to be explicitly approved. You then list each integration's domains yourself, and an integration whose domains are missing will fail to reach them.
An integration you install from a third party declares its own domains. With this setting enabled, installing it permits those destinations. Review the declared domains on the setup screen as you would any other permission.
Per-tool egress and SSRF protection
Web-fetch and tool-driven outbound calls are subject to a runtime SSRF check:
- The organization domain policy is applied before connecting.
- RFC 1918 (private) addresses are denied.
- Link-local (
169.254.0.0/16) is denied. - IPv6 unique-local (
fc00::/7) is denied. - Loopback is denied.
- Cluster-internal hostnames (
*.svc.cluster.local) are denied.
For these tools and extensions, the private-network opt-in reaches only the
private networks your Scrydon operator opened to your organization
(global.egress.privateNetworks), on those networks' ports; with no such
network it opens nothing. Loopback is never reachable from them: it is the
platform's own container. Every other address that is not publicly routable
stays denied whatever you enable: link-local and cloud metadata (169.254.169.254, the
AWS IPv6 endpoints in fd00:ec2::/64, the Azure platform address
168.63.129.16), shared address space (100.64.0.0/10), benchmarking,
documentation and reserved ranges, and multicast.
This applies to the built-in fetch-webpage tool, the API block, reviewed
workflow integrations, and vendor tools whose governed runtime permits an
outbound fetch.
An integration author can widen the set of domains reachable by their own integration, but only through the declared-domains mechanism above, only for public HTTPS destinations, and only while Vendor-declared domains is enabled. None of the address-level protections in this section can be widened by an integration, and a denylisted domain remains blocked.
Log Receivers and OAuth provider endpoints
Two addresses an organization admin configures are called from Scrydon's own
servers: a Log Receiver URL and an
extension's OAuth provider endpoints. Both are DNS-pinned, never follow a
redirect, and reach public https:// addresses only — except an address inside
a private network the operator opened to that organization with
global.egress.privateNetworks,
on that network's ports and verified against that network's trust anchors when
it names them. No organization setting opens a network. Loopback, link-local,
cloud metadata (169.254.169.254, fd00:ec2::/64, 168.63.129.16), the
cluster's own ranges (runtimePlane.blockedCidrs) and the other reserved
ranges are refused whatever the operator opens. The same rule is applied when
the address is saved and on every call.
Related
- Ingress hardening — the inbound side of the boundary.
- SPIFFE / mTLS — internal mesh authentication.
- Deployment → Air-gapped — full disconnect mode.