Skip to content

Security ​

headless-prerender drives a real browser and fetches whatever URL it is given. Treat an unprotected instance as a server-side request forgery (SSRF) proxy. Apply these controls before exposing it.

1. Restrict which origins can be rendered ​

Without allowedOrigins, any http(s) URL is fair game - including http://169.254.169.254/ (cloud metadata) and internal hostnames.

bash
headless-prerender serve \
  --allow-origin https://www.example.com \
  --allow-origin https://blog.example.com
ts
new PrerenderServer({
  allowedOrigins: ["https://www.example.com", "https://blog.example.com"],
});

A request for any other origin is rejected before a browser page is opened.

2. Require a token ​

bash
headless-prerender serve --token "$(openssl rand -hex 32)"

Callers must then supply it as ?token=... or an x-prerender-token header. Your reverse proxy adds this; external callers cannot.

3. Do not expose the port publicly ​

Bind to localhost or a private interface and let only your proxy reach it:

bash
headless-prerender serve --host 127.0.0.1

Or keep --host 0.0.0.0 inside a private network / container network with no public route, plus a firewall rule.

4. Protocol enforcement (built in) ​

Non-http(s) URLs (file:, ftp:, data:, ...) are always rejected. You do not need to configure this.

5. Run the browser sandboxed ​

The bundled launch flags include --no-sandbox so Chromium starts inside containers without extra privileges. If you can run with the sandbox enabled (non-root user, proper kernel support), that is stronger - launch your own Renderer with launchArgs that omit --no-sandbox, or run the container as a non-root user with --cap-add SYS_ADMIN avoided in favour of a seccomp profile.

6. Resource limits ​

A headless browser can consume significant memory and CPU.

  • Run it in a container with memory and CPU limits.
  • Keep --timeout modest (the default is 20 s) so hung pages are abandoned.
  • Put a concurrency limit in your proxy if bot traffic is bursty.
  • Restart the process periodically (e.g. a scheduled container restart) to reclaim memory.

Hardening checklist ​

  • [ ] allowedOrigins set to your site's origins only
  • [ ] token set and required
  • [ ] Port not reachable from the public internet
  • [ ] Runs in a container with memory/CPU limits
  • [ ] Timeout kept low
  • [ ] Process restarted on a schedule or on deploy

Released under the MIT License.