1. Authentication
By default, the Figranium UI requires an account. When you create your account during initial setup, Figranium enforces the following requirements:- Name: Must be 100 characters or fewer.
- Email: Must be a valid email address (max 255 characters).
- Password: Must be between 8 and 128 characters long.
400 error.
After setup, you should also:
- API Key: Generate a strong API key in Settings > System. All API keys are limited to 512 characters.
- Rotate: Regularly regenerate the API key if you suspect it’s compromised.
- Header: Always use
x-api-keyorAuthorization: Bearerfor API calls.
2. IP Allowlist (ALLOWED_IPS)
The most effective way to secure a deployment is to restrict access to trusted IP addresses.
- Environment Variable:
ALLOWED_IPS - Example:
ALLOWED_IPS=127.0.0.1,192.168.1.5,10.0.0.0/8 - Config File: Alternatively, edit
data/allowed_ips.json.
3. SSRF Protection (ALLOW_PRIVATE_NETWORKS)
Server-Side Request Forgery (SSRF) is a risk when allowing users to trigger scrapes of arbitrary URLs.
- Default:
ALLOW_PRIVATE_NETWORKS=false— private network access is blocked out of the box.- This prevents users from scanning your internal network (e.g.,
http://169.254.169.254/latest/meta-data).
- This prevents users from scanning your internal network (e.g.,
- Local development: If you need to scrape services on your local network, set
ALLOW_PRIVATE_NETWORKS=true.
Blocked destinations
WhenALLOW_PRIVATE_NETWORKS is false, the following addresses are blocked:
| Category | Blocked ranges |
|---|---|
| IPv4 private | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 (RFC 1918) |
| IPv4 special | 0.0.0.0/8 (current network), 127.0.0.0/8 (loopback), 169.254.0.0/16 (link-local), 100.64.0.0/10 (shared/CGN) |
| IPv4 reserved | 192.0.0.0/24 (IETF protocol assignments), 192.0.2.0/24 (TEST-NET-1), 198.18.0.0/15 (benchmarking), 198.51.100.0/24 (TEST-NET-2), 203.0.113.0/24 (TEST-NET-3), 224.0.0.0/4 (multicast), 240.0.0.0/4 (reserved) |
| IPv6 private | ::1/128 (loopback), fc00::/7 (unique local), fe80::/10 (link-local), ::/128 (unspecified), ff00::/8 (multicast) |
| Hostnames | localhost, *.localhost, host.docker.internal |
host.docker.internal is blocked because it resolves to the Docker host machine, which could expose internal services. This includes Ollama connections — both Ollama configuration URLs and API calls are validated against the SSRF blocklist. If you need to reach Ollama on the Docker host, set ALLOW_PRIVATE_NETWORKS=true.ALLOW_PRIVATE_NETWORKS setting. Only http: and https: URLs are allowed. Schemes such as file://, ftp://, and javascript: are blocked even when private network access is enabled.
SSRF protection also applies to output provider credentials. When you add or update a credential with a baseUrl (for example, a Baserow instance URL), Figranium validates the URL to block requests to private or internal network addresses. If the URL fails validation, the credential is rejected with an INVALID_BASE_URL error.
Proxy server validation
Proxy server addresses are validated against the same SSRF blocklist when you add, import, or update proxies in Settings > Proxies or through the API. If a proxy server URL points to a private or internal address, the request is rejected with anINVALID_URL error.
This prevents an attacker (or a misconfiguration) from routing scrape traffic through a proxy that resolves to your internal network. The validation applies to all proxy management endpoints:
POST /api/settings/proxies— adding a single proxyPOST /api/settings/proxies/import— bulk importing proxiesPUT /api/settings/proxies/:id— updating an existing proxy
ALLOW_PRIVATE_NETWORKS=true.
Ollama URL validation
Ollama base URLs are validated against the same SSRF blocklist when you save them in Settings > System > API Keys. If an Ollama URL points to a private or internal address (such aslocalhost or host.docker.internal), the save is rejected with an INVALID_URL error.
Figranium also validates Ollama URLs at request time, not just when they are saved. Every outbound call to an Ollama instance — including AI-powered selector generation and extraction script generation — goes through redirect-safe fetching. This means:
- The Ollama URL is re-validated against the SSRF blocklist before each request.
- If the URL returns a redirect, every hop is validated before following it.
- Sensitive headers are stripped on cross-origin redirects.
Other AI providers (Gemini, OpenAI, Claude) connect to fixed public API endpoints and do not require this additional validation. Only Ollama uses user-supplied URLs, so only Ollama calls go through request-time SSRF checks.
Gemini API key transport
Gemini API keys are sent to Google’s API using thex-goog-api-key HTTP header rather than a URL query parameter. This prevents keys from appearing in server access logs, reverse-proxy logs, or Referer headers — all common sources of credential leakage. No configuration is required; this is the default behavior for all Gemini-powered endpoints (selector generation and script generation).
If you run Ollama on the same machine or local network as Figranium, set ALLOW_PRIVATE_NETWORKS=true to permit these connections.
Redirect protection
WhenALLOW_PRIVATE_NETWORKS is false, all outbound HTTP requests — including webhook callbacks and output provider requests (such as Baserow) — are protected against redirect-based SSRF attacks. If a URL returns a redirect (HTTP 3xx), Figranium validates the destination URL at every hop before following it. This prevents an attacker from providing a URL that initially resolves to a public address but redirects to a private one (such as 169.254.169.254 or localhost).
- Up to 5 redirects are followed per request. If this limit is exceeded, the request fails.
- Each redirect destination is checked against the same private-IP blocklist used for scrape URLs.
- No configuration is needed — this protection is automatic when
ALLOW_PRIVATE_NETWORKS=false. - Redirects that change method (HTTP 301, 302, 303) automatically switch to
GETand drop the request body, following HTTP standards.
Cross-origin credential stripping
When a redirect crosses origin boundaries (for example, fromapi.baserow.io to a different domain), Figranium automatically strips sensitive headers from the redirected request. This prevents credentials from leaking to untrusted third-party servers.
The following headers are removed on cross-origin redirects:
AuthorizationX-API-KeyTokenCookieProxy-Authorization
Browser navigation protection
WhenALLOW_PRIVATE_NETWORKS is false, Figranium also guards against SSRF at the browser level. Every cross-origin navigation in a scrape, headful, or agent browser session is validated before the request leaves the browser. If a page attempts to navigate to a private network address, the navigation is blocked.
- Same-origin navigations (where the destination shares the same origin as the current page) are allowed without additional checks.
- Only top-level navigations are validated; sub-resource requests (images, scripts, etc.) are not intercepted.
- Blocked navigations are logged to the server console with a
[SECURITY]prefix.
Sandbox isolation
Extraction scripts and the extraction worker run inside a sandboxed environment that isolates them from the host Node.js runtime. The sandbox enforces the following restrictions on all data objects passed into your script:- Read-only access — you cannot set, define, or delete properties on proxied data objects. Attempts to do so are silently ignored.
- Null prototypes —
Object.getPrototypeOf()returnsnullon sandboxed objects, preventing prototype-chain traversal back to host objects.
If you have existing extraction scripts that modify proxied data objects, update them to copy values into new objects instead of mutating the originals.
DNS validation caching
To reduce the overhead of repeated DNS lookups during URL validation, Figranium caches hostname resolution results for 30 seconds. Both allowed and blocked hostnames are cached, so subsequent requests to the same host resolve instantly. The cache is cleared automatically after the TTL expires.4. Session Security
- Session Lifetime: Dashboard sessions expire after 7 days of inactivity. You will need to log in again after this period.
- HTTPS: Always run Figranium behind a reverse proxy (Nginx, Caddy) that handles TLS/SSL.
- Secure Cookies: Set
SESSION_COOKIE_SECURE=truein your.envfile to ensure cookies are only sent over HTTPS. Session cookies are always set with thehttpOnlyflag, which prevents client-side JavaScript from accessing the session token and mitigates XSS-based session theft. - HSTS: When
SESSION_COOKIE_SECUREis enabled, Figranium automatically setsStrict-Transport-Securityheaders (max-age=31536000; includeSubDomains) on every response. This instructs browsers to only communicate with your instance over HTTPS for one year, preventing protocol-downgrade attacks. - Strong Secret: Ensure
SESSION_SECRETis a long, random string.
5. Content Security Policy
Figranium sets aContent-Security-Policy (CSP) header on every HTTP response. This header tells browsers which origins are allowed to load scripts, styles, fonts, images, and network connections — providing defense-in-depth against cross-site scripting (XSS) and code injection attacks.
The policy is applied automatically with no configuration required. The default directives are:
| Directive | Allowed sources |
|---|---|
default-src | 'self' |
script-src | 'self', inline scripts, eval (required by the editor runtime) |
style-src | 'self', inline styles, Google Fonts |
font-src | 'self', Google Fonts static assets |
img-src | 'self', data:, blob:, Google, jsDelivr CDN, GitHub raw content |
connect-src | 'self', GitHub API, Google Generative Language API, OpenAI API, Anthropic API, Baserow API, Ollama (local) |
media-src | 'self', blob: |
frame-src | 'self' |
If you integrate a third-party service whose domain is not in the allow-list above, the browser will block those requests. Check the browser console for CSP violation reports to diagnose connectivity issues with external services. Ollama requests are made server-side, so CSP does not affect connectivity to your Ollama instance.
X-Content-Type-Options: nosniff— prevents browsers from MIME-sniffing responses.X-Frame-Options: SAMEORIGIN— blocks your instance from being embedded in iframes on other domains.X-XSS-Protection: 1; mode=block— enables legacy XSS filters in older browsers.Referrer-Policy: strict-origin-when-cross-origin— limits referrer information sent to external sites.
6. Reverse proxy and TRUST_PROXY
If you run Figranium behind a reverse proxy (Nginx, Caddy, AWS ALB), you should set TRUST_PROXY=true so the server can read the real client IP from proxy headers for logging and rate limiting.
Loopback bypass hardening
The internal task-execution bypass (used by thex-internal-run header) requires both the proxy-resolved client IP and the direct TCP connection address to be loopback addresses. This dual validation prevents an external attacker from bypassing API key authentication by spoofing the X-Forwarded-For header — even when TRUST_PROXY is enabled, the raw socket address must also resolve to 127.0.0.1 or ::1.
In practice this means:
- Local processes calling the API from the same machine pass both checks automatically.
- Remote requests that spoof a loopback
X-Forwarded-Forvalue are still rejected because the TCP connection originates from an external address.
TRUST_PROXY enabled:
- Only set
TRUST_PROXY=truewhen Figranium is actually behind a trusted proxy. - Configure your proxy to overwrite (not append to) the
X-Forwarded-Forheader so untrusted values from clients are stripped. - Combine with
ALLOWED_IPSto restrict which addresses can reach the server.
7. Rate Limiting
Figranium includes built-in rate limiting to prevent abuse.- Authentication: Max 10 failed login attempts per 15 minutes (
AUTH_RATE_LIMIT_MAX). - Setup check: The setup status endpoint is rate-limited with the same authentication limiter to prevent attackers from probing whether your instance has been configured.
- Data API: Max 100 data requests per 15 minutes (
DATA_RATE_LIMIT_MAX). - Settings endpoints: API key, proxy, and other settings routes are rate-limited to prevent automated abuse.
.env if legitimate traffic is being blocked.
8. Sanitized error responses
API error responses return generic error codes instead of detailed internal messages. This prevents information disclosure that could help an attacker map your infrastructure or discover implementation details. For example, a failed credential URL validation returnsINVALID_BASE_URL with a fixed description rather than the underlying system error. The same applies to authentication endpoints, settings routes, and webhook URL validation.
Each error response includes a structured error code you can match on programmatically:
| Error code | Endpoint | Meaning |
|---|---|---|
INVALID_WEBHOOK_URL | POST /api/execute/:id | Webhook URL failed SSRF validation |
INVALID_BASE_URL | POST /api/credentials, PUT /api/credentials/:id | Credential base URL is malformed or points to a restricted address |
INVALID_URL | POST /api/settings/ollama-api-key | Ollama base URL failed SSRF validation |
INVALID_URL | POST /api/settings/proxies, POST /api/settings/proxies/import, PUT /api/settings/proxies/:id | Proxy server address failed SSRF validation |
INVALID_DATABASE_ID | GET /api/credentials/:id/proxy/baserow/databases/:dbId/tables | Database ID is not a valid numeric identifier |
INTERNAL_ERROR | Various | An unexpected server-side error occurred |