diff --git a/snippets/nuxt/server/utils/ProxiesConfig.js b/snippets/nuxt/server/utils/ProxiesConfig.js deleted file mode 100644 index f8e0b735..00000000 --- a/snippets/nuxt/server/utils/ProxiesConfig.js +++ /dev/null @@ -1,9 +0,0 @@ -import { arcjet as arcjetNuxt } from "#arcjet"; - -export const arcjet = arcjetNuxt({ - rules: [], - proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range - ], -}); diff --git a/snippets/nuxt/server/utils/ProxiesConfig.ts b/snippets/nuxt/server/utils/ProxiesConfig.ts index 1836bf7b..3add67cd 100644 --- a/snippets/nuxt/server/utils/ProxiesConfig.ts +++ b/snippets/nuxt/server/utils/ProxiesConfig.ts @@ -2,9 +2,9 @@ import { arcjet as arcjetNuxt } from "#arcjet"; export const arcjet = arcjetNuxt({ - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }); diff --git a/snippets/nuxt/server/utils/TrustedIp.ts b/snippets/nuxt/server/utils/TrustedIp.ts new file mode 100644 index 00000000..82cacc8a --- /dev/null +++ b/snippets/nuxt/server/utils/TrustedIp.ts @@ -0,0 +1,9 @@ +// @ts-expect-error +import { arcjet as arcjetNuxt, slidingWindow } from "#arcjet"; + +export const arcjet = arcjetNuxt({ + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/content/docs/concepts/client-ip.mdx b/src/content/docs/concepts/client-ip.mdx new file mode 100644 index 00000000..722f9c46 --- /dev/null +++ b/src/content/docs/concepts/client-ip.mdx @@ -0,0 +1,393 @@ +--- +description: "How the client IP is detected in Arcjet and how to change that." +frameworks: + - astro + - bun-hono + - bun + - deno + - fastify + - nest-js + - next-js + - node-js-express + - node-js-hono + - node-js + - nuxt + - react-router + - remix + - sveltekit +next: false +prev: false +title: "Client IP" +ajToc: + - anchor: "overview" + text: "Overview" + - anchor: "framework" + text: "Framework" + - anchor: "platform" + text: "Platform" + - anchor: "proxies" + children: + - anchor: "ip-ranges" + text: "IP ranges" + text: "Proxies" + - anchor: "overwriting-client-ips" + children: + - anchor: "development" + text: "Development" + - anchor: "production" + text: "Production" + text: "Overwriting client IPs" +--- + +import { Code } from "@astrojs/starlight/components"; +import SlotByFramework from "@/components/SlotByFramework"; +import { removeTSCCommentDirectives as removeTypeScriptDirectives } from "@/lib/utils"; +import AstroProxies from "/src/snippets/reference/astro/Proxies.mjs?raw"; +import AstroTrustedIp from "/src/snippets/reference/astro/TrustedIp.mjs?raw"; +import BunProxies from "/src/snippets/reference/bun/Proxies.ts?raw"; +import BunTrustedIp from "/src/snippets/reference/bun/TrustedIp.ts?raw"; +import DenoProxies from "/src/snippets/reference/deno/proxies.ts?raw"; +import DenoTrustedIp from "/src/snippets/reference/deno/trusted-ip.ts?raw"; +import FastifyProxies from "/src/snippets/reference/fastify/proxies.ts?raw"; +import FastifyTrustedIp from "/src/snippets/reference/fastify/trusted-ip.ts?raw"; +import NestProxies from "/src/snippets/reference/nestjs/Proxies.ts?raw"; +import NestTrustedIp from "/src/snippets/reference/nestjs/TrustedIp.ts?raw"; +import NextProxies from "/src/snippets/reference/nextjs/Proxies.ts?raw"; +import NextTrustedIp from "/src/snippets/reference/nextjs/TrustedIp.ts?raw"; +import NodeProxies from "/src/snippets/reference/nodejs/Proxies.ts?raw"; +import NodeTrustedIp from "/src/snippets/reference/nodejs/TrustedIp.ts?raw"; +import NuxtProxies from "@repo/nuxt/server/utils/ProxiesConfig.ts?raw"; +import NuxtTrustedIp from "@repo/nuxt/server/utils/TrustedIp.ts?raw"; +import ReactRouterProxies from "/src/snippets/reference/react-router/proxies.ts?raw"; +import ReactRouterTrustedIp from "/src/snippets/reference/react-router/trusted-ip.ts?raw"; +import RemixProxies from "/src/snippets/reference/remix/Proxies.ts?raw"; +import RemixTrustedIp from "/src/snippets/reference/remix/TrustedIp.ts?raw"; +import SveltekitProxies from "/src/snippets/reference/sveltekit/Proxies.ts?raw"; +import SveltekitTrustedIp from "/src/snippets/reference/sveltekit/TrustedIp.ts?raw"; + + + +Arcjet needs the public IP address of incoming requests for much of what it does. +By default, +Arcjet uses the IP as a characteristic to differentiate users. +If that doesn’t work correctly, +several good users may be denied access because they cannot be differentiated +from a bad user. +Or a malicious user could get around rate limits by appearing as different +users. +Arcjet also uses the client IP for geolocation and other reflected metadata. + +Finding the correct client IP address is tricky. +How to find that IP depends on the framework you build with, +the platform you deploy to, +and whether there are proxies or similar services in front of it. + +When developing an app locally, +there is no public client IP. +When testing Arcjet, +it is often needed to overwrite the IP. + +## Framework + +Each Arcjet SDK is made for a particular framework and detects the client IP +correctly from incoming requests out of the box. +Some frameworks provide that IP address on the request directly +(such as `request.ip` and `request.requestContext.identity.sourceIp`), +in other cases it can be inferred from headers +(see the next section “[Platform][section-platform]”). + +The found IP may be of a proxy or other service in front of your application. +See the section “[Proxies][section-proxies]” for these cases. + +If no IP is detected in production, +you’ll see a big warning in the logs. +In this case, +if you do know where to find the correct IP address, +you can [overwrite the client IP][section-overwrite-ip]. +But please also [open an issue][arcjet-arcjet-js-issues] so that this bug can +be fixed. + +## Platform + +Arcjet looks at request headers when frameworks do not provide the client IP +directly or when it matches a configured proxy. +Which headers to trust depends on the platform your app runs on. +Arcjet infers whether an app runs on Firebase, Fly, Render, or Vercel +(but not Cloudflare) from the environment. +On other platforms Arcjet looks for common headers. + +The considered [environment variables][arcjet-env-external] and their +corresponding platforms are as follows: + +| Environment variable | Platform | +| ------------------------------------------- | ------------ | +| [`FIREBASE_CONFIG`][google-firebase-config] | **Firebase** | +| [`FLY_APP_NAME`][fly-app-name] | **Fly** | +| [`RENDER`][render-render] | **Render** | +| [`VERCEL`][vercel-vercel] | **Vercel** | + +The considered headers, their formats, and their corresponding platforms are as +follows: + +| Header | Format | Platforms | +| --------------------------------------------------------- | ------------------- | --------------------------------- | +| [`cf-connecting-ipv6`][cloudflare-cf-connecting-ipv6] | IPv6 | **Cloudflare** | +| [`cf-connecting-ip`][cloudflare-cf-connecting-ip] | IP | **Cloudflare** | +| [`do-connecting-ip`][digitalocean-do-connecting-ip] | IP | Unknown | +| [`fastly-client-ip`][fastly-client-ip] | IP | Unknown | +| [`fly-client-ip`][fly-client-ip] | IP | **Fly** | +| `forwarded-for` | IP | Unknown | +| [`forwarded`][mdn-forwarded] | RFC 7239 | Unknown | +| `true-client-ip` | IP | **Render**, unknown | +| [`x-appengine-user-ip`][google-app-engine-user-ip] | IP | Unknown | +| `x-client-ip` | IP | Unknown | +| `x-cluster-client-ip` | IP | Unknown | +| `x-fah-client-ip` | IP | **Firebase** | +| [`x-forwarded-for`][mdn-x-forwarded-for] | Comma-separated IPs | **Firebase**, **Vercel**, unknown | +| `x-forwarded` | IP | Unknown | +| `x-real-ip` | IP | **Vercel**, unknown | +| [`x-vercel-forwarded-for`][vercel-x-vercel-forwarded-for] | Comma-separated IPs | **Vercel** | + +When using platforms not listed here and you know which header to trust, +you can [overwrite the client IP][section-overwrite-ip]. +It is important to trust this header because headers can be set by end users. +If your platform does not set for example `x-client-ip` but a malicious user +sets it, +that untrusted value would be used. + +If you use a platform not listed here which can be detected from the +environment and sets certain headers, +please [open an issue][arcjet-arcjet-js-issues] so that trusted support can be +added for it. + +## Proxies + +When you put services like proxies or load balancers in front of your +application, +the IP address that Arcjet finds will be that of the last proxy. + +Well-behaving services will use an `x-forwarded-for` or `forwarded` header to +forward the IP addresses that connect to them. + +Because malicious users can also set headers, +the left-most value in such headers cannot be trusted. +But the right-most value of these well-behaving services _can_ be trusted. +And when that IP belongs to another service that you trust, +the one before it can be used. + +To illustrate, +when you put a service like Cloudflare in front of your application, +and know that it sets headers correctly, +and know which IP addresses belong to it, +after verifying that the IP belongs to it, +you trust the IP _before_ it. + +Setting `proxies` works as follows: + + + + + + + + + + + + + + + + + + +Which values to pass in `proxies` depends on your setup. +Most services provide a list of their IP ranges as JSON. + +It is not needed to configure +documentation (`192.0.2.1`), +benchmarking (`198.19.255.255`), +broadcast (`255.255.255.255`), +link local (`169.254.255.255`), +loopback (`127.0.0.1`), +private (such as `10.1.1.1`), +reserved (`192.0.0.1`), or +shared (`100.127.255.255`) +IP addresses. +Whether IPv4 or IPv6, those are automatically filtered out. + +### IP ranges + +#### Cloudflare + +You can fetch Cloudflare IP ranges as follows: + +```ts +const [cloudflareIpv4, cloudflareIpv6] = await Promise.all( + [ + "https://www.cloudflare.com/ips-v4/", + "https://www.cloudflare.com/ips-v6/", + ].map(async function (url) { + const response = await fetch(url); + const body = await response.text(); + return body.trim().split("\n"); + }), +); +const cloudflare = [...cloudflareIpv4, ...cloudflareIpv6].toSorted(); +// You can now pass `...cloudflare` in `proxies`. +``` + +#### Google + +You can fetch Google IP ranges as follows: + +```ts +/** + * Google IP prefix info. + */ +interface GooglePrefixBaseFields { + /** + * Region. + */ + scope?: string; + /** + * Service. + */ + service?: "Google Cloud"; +} + +/** + * Google IPv4 prefix info. + */ +interface GooglePrefixIpv4 extends GooglePrefixBaseFields { + /** + * CIDR range. + */ + ipv4Prefix: string; +} + +/** + * Google IPv6 prefix info. + */ +interface GooglePrefixIpv6 extends GooglePrefixBaseFields { + /** + * CIDR range. + */ + ipv6Prefix: string; +} + +/** + * Google IP ranges response. + */ +interface GoogleResponse { + /** + * Creation date. + */ + createDate: string; + /** + * List of IP prefixes. + */ + prefixes: Array; + /** + * Sync token. + */ + syncToken: string; +} + +const googleResponse = await fetch( + "https://www.gstatic.com/ipranges/goog.json", +); +const googleBody = (await googleResponse.json()) as GoogleResponse; +const google = googleBody.prefixes + .map(function (d) { + return "ipv4Prefix" in d ? d.ipv4Prefix : d.ipv6Prefix; + }) + .toSorted(); +// You can now pass `...google` in `proxies`. +``` + +## Overwriting client IPs + +It is possible to overwrite the client IP address. +To make this easy locally but secure when deployed, +how to do this is different in development and production. +This difference is based on environment variables. +See [_How to define environment variables_][arcjet-env-set] for more info. + +### Development + +In development you can pass an `x-arcjet-ip` header. +This value is preferred over any other detected IP address. +An example with Curl is: + +```sh +curl https://example.com --header "x-arcjet-ip: 76.76.21.21" --verbose +``` + +This header is ignored in production because otherwise malicious users could +set it. +But in development it is useful to simulate different client IP addresses +without changing code and restarting your app, +and to check how that affects Arcjet behavior, +particularly around rate limiting and IP geolocation. + +### Production + +In production, +if the client IP is in a header that you trust, +you can pas a `trustedIpHeader` option. + + + + + + + + + + + + + + + + + + +[arcjet-arcjet-js-issues]: https://github.com/arcjet/arcjet-js/issues +[arcjet-env-external]: /environment#list-of-environment-variables-read-by-arcjet +[arcjet-env-set]: /environment#list-of-environment-variables-read-by-arcjet +[cloudflare-cf-connecting-ipv6]: https://developers.cloudflare.com/fundamentals/reference/http-request-headers/#cf-connecting-ipv6 +[cloudflare-cf-connecting-ip]: https://developers.cloudflare.com/fundamentals/reference/http-request-headers/#cf-connecting-ip +[digitalocean-do-connecting-ip]: https://docs.digitalocean.com/support/where-can-i-find-the-client-ip-address-of-a-request-connecting-to-my-app/ +[fastly-client-ip]: https://www.fastly.com/documentation/reference/http/http-headers/Fastly-Client-IP/ +[fly-app-name]: https://fly.io/docs/machines/runtime-environment/#fly_app_name +[fly-client-ip]: https://www.fly.io/docs/networking/request-headers/#fly-client-ip +[google-app-engine-user-ip]: https://cloud.google.com/appengine/docs/legacy/standard/java/reference/request-response-headers +[google-firebase-config]: https://firebase.google.com/docs/functions/config-env +[mdn-forwarded]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Forwarded +[mdn-x-forwarded-for]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For +[render-render]: https://render.com/docs/environment-variables#render-62 +[section-overwrite-ip]: #overwriting-client-ips +[section-platform]: #platform +[section-proxies]: #proxies +[vercel-vercel]: https://vercel.com/docs/environment-variables/system-environment-variables#VERCEL +[vercel-x-vercel-forwarded-for]: https://vercel.com/docs/headers/request-headers#x-vercel-forwarded-for diff --git a/src/content/docs/environment.mdx b/src/content/docs/environment.mdx index d874cd20..348b4a72 100644 --- a/src/content/docs/environment.mdx +++ b/src/content/docs/environment.mdx @@ -113,7 +113,7 @@ Arcjet checks whether values are non-empty. [`VERCEL`][vercel-vercel] is set by Vercel. The inferred platform affects which request headers are trusted when determining the -client IP. +[client IP][arcjet-client-ip]. When Fly is detected, that affects the default value of `ARCJET_BASE_URL`. {/* TODO: link to Client IP concept when that lands. */} @@ -201,6 +201,7 @@ you can use this package. [arcjet-app]: https://app.arcjet.com [arcjet-architecture-api-latency]: /architecture#api-latency [arcjet-architecture-cloud-api]: /architecture#arcjet-cloud-api +[arcjet-client-ip]: /concepts/client-ip [github-arcjet-env]: https://github.com/arcjet/arcjet/tree/main/packages/env [google-firebase-config]: https://firebase.google.com/docs/functions/config-env [fly-app-name]: https://fly.io/docs/machines/runtime-environment/#fly_app_name diff --git a/src/content/docs/fingerprints.mdx b/src/content/docs/fingerprints.mdx index 9a251b94..82b3e0e6 100644 --- a/src/content/docs/fingerprints.mdx +++ b/src/content/docs/fingerprints.mdx @@ -59,6 +59,8 @@ is a valid address. However, in non-production environments, we allow private/internal addresses so the SDKs work correctly. See the individual SDK references for more details. +See also “[Concepts: Client IP](/concepts/client-ip)” for more info. + ### Custom characteristics You can use custom characteristics to track clients based on various attributes. diff --git a/src/content/docs/reference/astro.mdx b/src/content/docs/reference/astro.mdx index 933ff67f..1ec4d6e2 100644 --- a/src/content/docs/reference/astro.mdx +++ b/src/content/docs/reference/astro.mdx @@ -31,7 +31,6 @@ import ProtectEndpointTS from "@repo/astro/src/reference/ProtectEndpoint.ts?raw" import ProtectPageAstro from "/src/snippets/reference/astro/ProtectPage.astro?raw"; import ProtectMiddlewareJS from "/src/snippets/reference/astro/ProtectMiddleware.js?raw"; import ProtectMiddlewareTS from "/src/snippets/reference/astro/ProtectMiddleware.ts?raw"; -import ProxiesConfigJS from "/src/snippets/reference/astro/Proxies.mjs?raw"; import DecisionLogConfigJS from "/src/snippets/reference/astro/DecisionLogConfig.mjs?raw"; import DecisionLogJS from "/src/snippets/reference/astro/DecisionLog.js?raw"; import DecisionLogTS from "/src/snippets/reference/astro/DecisionLog.ts?raw"; @@ -139,8 +138,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. ### Single instance @@ -214,41 +223,8 @@ The `NODE_ENV` environment variable is not used. If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that -the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/reference/bun.mdx b/src/content/docs/reference/bun.mdx index 1925f1f4..655943f7 100644 --- a/src/content/docs/reference/bun.mdx +++ b/src/content/docs/reference/bun.mdx @@ -19,7 +19,6 @@ import MultipleRulesTS from "/src/snippets/reference/bun/MultipleRules.ts?raw"; import MultipleRulesJS from "/src/snippets/reference/bun/MultipleRules.js?raw"; import LoggerTS from "/src/snippets/reference/bun/Logger.ts?raw"; import LoggerJS from "/src/snippets/reference/bun/Logger.js?raw"; -import ProxiesTS from "/src/snippets/reference/bun/Proxies.ts?raw"; import ProtectTS from "/src/snippets/reference/bun/Protect.ts?raw"; import ProtectJS from "/src/snippets/reference/bun/Protect.js?raw"; import DecisionLogTS from "/src/snippets/reference/bun/DecisionLog.ts?raw"; @@ -107,8 +106,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. @@ -235,37 +244,8 @@ print in development: If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP -address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/reference/nestjs.mdx b/src/content/docs/reference/nestjs.mdx index 3077ffae..68099333 100644 --- a/src/content/docs/reference/nestjs.mdx +++ b/src/content/docs/reference/nestjs.mdx @@ -13,7 +13,6 @@ import WhatIsArcjet from "/src/components/WhatIsArcjet.astro"; import ErrorLoggingTS from "/src/snippets/reference/nestjs/ErrorLogging.ts?raw"; import ErrorUserAgentTS from "/src/snippets/reference/nestjs/ErrorUserAgent.ts?raw"; import LoggerTS from "/src/snippets/reference/nestjs/ClientLogger.ts?raw"; -import ProxiesTS from "/src/snippets/reference/nestjs/Proxies.ts?raw"; import ConfigurationTS from "/src/snippets/reference/nestjs/Configuration.ts?raw"; import IPLocationTS from "/src/snippets/reference/nestjs/IPLocation.ts?raw"; import NodeVersions from "/src/snippets/reference/node-versions.mdx"; @@ -84,8 +83,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. @@ -138,37 +147,8 @@ controllers. If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so -that the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Decision diff --git a/src/content/docs/reference/nextjs.mdx b/src/content/docs/reference/nextjs.mdx index 6fef7800..02292dc9 100644 --- a/src/content/docs/reference/nextjs.mdx +++ b/src/content/docs/reference/nextjs.mdx @@ -44,7 +44,6 @@ import ProtectAppJS from "/src/snippets/reference/nextjs/ProtectApp.js?raw"; import ProtectAppTS from "/src/snippets/reference/nextjs/ProtectApp.ts?raw"; import ProtectPagesJS from "/src/snippets/reference/nextjs/ProtectPages.js?raw"; import ProtectPagesTS from "/src/snippets/reference/nextjs/ProtectPages.ts?raw"; -import ProxiesTS from "/src/snippets/reference/nextjs/Proxies.ts?raw"; import RuleModesJS from "/src/snippets/reference/nextjs/RuleModes.js?raw"; import RuleModesTS from "/src/snippets/reference/nextjs/RuleModes.ts?raw"; import ServerAction from "/src/snippets/reference/nextjs/ServerAction.tsx?raw"; @@ -155,8 +154,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. @@ -280,37 +289,8 @@ module.exports = nextConfig; If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that -the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/reference/nodejs.mdx b/src/content/docs/reference/nodejs.mdx index 9903b246..326c9a1c 100644 --- a/src/content/docs/reference/nodejs.mdx +++ b/src/content/docs/reference/nodejs.mdx @@ -13,7 +13,6 @@ import ProtectTS from "/src/snippets/reference/nodejs/Protect.ts?raw"; import ProtectJS from "/src/snippets/reference/nodejs/Protect.js?raw"; import LoggerTS from "/src/snippets/reference/nodejs/Logger.ts?raw"; import LoggerJS from "/src/snippets/reference/nodejs/Logger.js?raw"; -import ProxiesTS from "/src/snippets/reference/nodejs/Proxies.ts?raw"; import IPLocationTS from "/src/snippets/reference/nodejs/IPLocation.ts?raw"; import IPLocationJS from "/src/snippets/reference/nodejs/IPLocation.js?raw"; import WithRuleTS from "/src/snippets/reference/nodejs/WithRule.ts?raw"; @@ -94,8 +93,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. @@ -191,37 +200,8 @@ print in development: If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that -the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/reference/nuxt.mdx b/src/content/docs/reference/nuxt.mdx index 9587bce0..4c7dffd1 100644 --- a/src/content/docs/reference/nuxt.mdx +++ b/src/content/docs/reference/nuxt.mdx @@ -20,8 +20,6 @@ import RuleModesConfigTS from "@repo/nuxt/server/utils/RulesModesConfig.ts?raw"; import RuleModesConfigJS from "@repo/nuxt/server/utils/RulesModesConfig.js?raw"; import MultipleRulesTS from "@repo/nuxt/server/utils/MultipleRules.ts?raw"; import MultipleRulesJS from "@repo/nuxt/server/utils/MultipleRules.js?raw"; -import ProxiesConfigTS from "@repo/nuxt/server/utils/ProxiesConfig.ts?raw"; -import ProxiesConfigJS from "@repo/nuxt/server/utils/ProxiesConfig.js?raw"; import ServerRoutesTS from "@repo/nuxt/server/routes/ServerRoutes.get.ts?raw"; import ServerRoutesJS from "@repo/nuxt/server/routes/ServerRoutes.get.js?raw"; import ServerAPIRoutesTS from "@repo/nuxt/server/api/ServerAPIRoutes.post.ts?raw"; @@ -161,8 +159,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. ### Single instance @@ -249,52 +257,8 @@ explicitly in `nuxt.config.ts`. If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that -the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - - - - - - - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/reference/remix.mdx b/src/content/docs/reference/remix.mdx index fb915c91..4207272c 100644 --- a/src/content/docs/reference/remix.mdx +++ b/src/content/docs/reference/remix.mdx @@ -13,7 +13,6 @@ import ProtectTS from "/src/snippets/reference/remix/Protect.ts?raw"; import ProtectJS from "/src/snippets/reference/remix/Protect.js?raw"; import LoggerTS from "/src/snippets/reference/remix/Logger.ts?raw"; import LoggerJS from "/src/snippets/reference/remix/Logger.js?raw"; -import ProxiesTS from "/src/snippets/reference/remix/Proxies.ts?raw"; import IPLocationTS from "/src/snippets/reference/remix/IPLocation.ts?raw"; import IPLocationJS from "/src/snippets/reference/remix/IPLocation.js?raw"; import WithRuleTS from "/src/snippets/reference/remix/WithRule.ts?raw"; @@ -94,8 +93,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. @@ -191,37 +200,8 @@ print in development: If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that -the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/reference/sveltekit.mdx b/src/content/docs/reference/sveltekit.mdx index 3c5acfbd..0be73acc 100644 --- a/src/content/docs/reference/sveltekit.mdx +++ b/src/content/docs/reference/sveltekit.mdx @@ -21,7 +21,6 @@ import ProtectTS from "/src/snippets/reference/sveltekit/Protect.ts?raw"; import ProtectJS from "/src/snippets/reference/sveltekit/Protect.js?raw"; import LoggerTS from "/src/snippets/reference/sveltekit/Logger.ts?raw"; import LoggerJS from "/src/snippets/reference/sveltekit/Logger.js?raw"; -import ProxiesTS from "/src/snippets/reference/sveltekit/Proxies.ts?raw"; import DecisionLogTS from "/src/snippets/reference/sveltekit/DecisionLog.ts?raw"; import DecisionLogJS from "/src/snippets/reference/sveltekit/DecisionLog.js?raw"; import ErrorLoggingTS from "/src/snippets/reference/sveltekit/ErrorLogging.ts?raw"; @@ -127,8 +126,18 @@ The optional fields are: - `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client - IP address in a header. See [Load balancers & - proxies](#load-balancers--proxies) below for an example. + IP address in a header. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. +- `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you + trust (such as `x-fah-client-ip`). + This value is _preferred_ over IP addresses provided by the framework and IP + addresses found in other headers based on the platform, + in both development and production. + It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such + as `x-forwarded-for`). + It can contain IPv4 or IPv6 addresses. + Proxies are filtered out. + See “[Concepts: Client IP](/concepts/client-ip)” for more info. @@ -256,37 +265,8 @@ print in development: If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the -real client IP address plus a list of proxies that the request has passed -through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the -client, so you should only trust it if you are sure that the load balancer is -setting it correctly. See [the MDN -docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) -for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header -by setting the `proxies` field in the configuration. This should be a list of -the IP addresses or the CIDR range of your load balancers to be removed, so that -the last IP address in the list is the real client IP address. - -#### Example - -For example, if the load balancer is at `100.100.100.100` and the client IP -address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -```http -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use -`192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - - +You can configure Arcjet to trust particular IP addresses. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Protect diff --git a/src/content/docs/troubleshooting.mdx b/src/content/docs/troubleshooting.mdx index a3ed86c5..9eaa978a 100644 --- a/src/content/docs/troubleshooting.mdx +++ b/src/content/docs/troubleshooting.mdx @@ -85,20 +85,12 @@ When you deploy your app next, Arcjet should not trigger on this route. Arcjet's [IP geolocation](/blueprints/ip-geolocation) and [VPN & proxy detection](/blueprints/vpn-proxy-detection) features require a real IP address -to work. In local development, Arcjet defaults to `127.0.0.1` so the IP analysis -metadata will be empty. - -You can set the IP address to a real public IP by overriding the IP address -field (`ip`) in the `request` object that is passed to the Arcjet `protect` -function. - -```ts -// Override the IP address in the request object if `ip` is provided. You could -// set this using an environment variable or some other method to ensure it is -// only set in development. -//const ip = "8.8.8.8"; // Google's public DNS server -const decision = await aj.protect(ip ? { ...req, ip } : req); -``` +to work. +When you are developing your app locally, +there is no public IP. +In that case the IP analysis metadata will be empty. +In development you can pass an `x-arcjet-xxx` header. +See “[Concepts: Client IP](/concepts/client-ip)” for more info. ## Common errors @@ -165,6 +157,8 @@ development mode. If this appears in production, check that [`ARCJET_ENV`](/environment#arcjet-env) is not incorrectly set to `development`. +See also “[Concepts: Client IP](/concepts/client-ip)” for more info. + ### generateFingerprint: ip is empty / [failed_precondition] client IP not provided Arcjet normally detects when it is running in a local environment and uses a @@ -186,6 +180,8 @@ each request is coming from. If the IP address is not provided, or it is running in production and a private/internal address is provided, then Arcjet will show this error. +See also “[Concepts: Client IP](/concepts/client-ip)” for more info. + ### [failed_precondition] request details failed validation Arcjet expects certain fields to exist on the object used to analyze each diff --git a/src/lib/sidebars.ts b/src/lib/sidebars.ts index d8874a26..30e8a601 100644 --- a/src/lib/sidebars.ts +++ b/src/lib/sidebars.ts @@ -322,6 +322,16 @@ export const main = [ }, ], }, + { + label: "Concepts", + collapsed: false, + items: [ + { + label: "Client IP", + link: "/concepts/client-ip", + }, + ], + }, { label: "Advanced", collapsed: false, diff --git a/src/snippets/ip/proxies.ts b/src/snippets/ip/proxies.ts index 78884e9d..5de5758d 100644 --- a/src/snippets/ip/proxies.ts +++ b/src/snippets/ip/proxies.ts @@ -1,14 +1,14 @@ -import ip from "@arcjet/ip"; +import { findIp } from "@arcjet/ip"; // Some Request-like object, such as node's `http.IncomingMessage`, `Request` or // Next.js' `NextRequest` const request = new Request("/your-route"); // You can also pass a list of trusted proxies to ignore -const proxyExcludedPublicIp = ip(request, { +const proxyExcludedPublicIp = findIp(request, { proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], }); console.log(proxyExcludedPublicIp); diff --git a/src/snippets/reference/astro/Proxies.mjs b/src/snippets/reference/astro/Proxies.mjs index 71f72eab..78c58f21 100644 --- a/src/snippets/reference/astro/Proxies.mjs +++ b/src/snippets/reference/astro/Proxies.mjs @@ -1,22 +1,18 @@ // @ts-check -import { defineConfig } from "astro/config"; -import node from "@astrojs/node"; import arcjet from "@arcjet/astro"; +import node from "@astrojs/node"; +import { defineConfig } from "astro/config"; export default defineConfig({ - adapter: node({ - mode: "standalone", - }), - env: { - validateSecrets: true, - }, + adapter: node({ mode: "standalone" }), + env: { validateSecrets: true }, integrations: [ arcjet({ - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }), ], }); diff --git a/src/snippets/reference/astro/TrustedIp.mjs b/src/snippets/reference/astro/TrustedIp.mjs new file mode 100644 index 00000000..4a406f68 --- /dev/null +++ b/src/snippets/reference/astro/TrustedIp.mjs @@ -0,0 +1,18 @@ +// @ts-check +import arcjet, { slidingWindow } from "@arcjet/astro"; +import node from "@astrojs/node"; +import { defineConfig } from "astro/config"; + +export default defineConfig({ + adapter: node({ mode: "standalone" }), + env: { validateSecrets: true }, + integrations: [ + arcjet({ + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", + }), + ], +}); diff --git a/src/snippets/reference/bun/Proxies.ts b/src/snippets/reference/bun/Proxies.ts index f4160e66..c4f85c1b 100644 --- a/src/snippets/reference/bun/Proxies.ts +++ b/src/snippets/reference/bun/Proxies.ts @@ -1,11 +1,11 @@ -import arcjet from "@arcjet/bun"; +import arcjetBun from "@arcjet/bun"; import { env } from "bun"; -const aj = arcjet({ +const arcjet = arcjetBun({ key: env.ARCJET_KEY!, - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }); diff --git a/src/snippets/reference/bun/TrustedIp.ts b/src/snippets/reference/bun/TrustedIp.ts new file mode 100644 index 00000000..944202cd --- /dev/null +++ b/src/snippets/reference/bun/TrustedIp.ts @@ -0,0 +1,11 @@ +import arcjetBun, { slidingWindow } from "@arcjet/bun"; +import { env } from "bun"; + +const arcjet = arcjetBun({ + key: env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/deno/proxies.ts b/src/snippets/reference/deno/proxies.ts new file mode 100644 index 00000000..39ef66a7 --- /dev/null +++ b/src/snippets/reference/deno/proxies.ts @@ -0,0 +1,11 @@ +import "jsr:@std/dotenv/load"; +import arcjetDeno from "@arcjet/deno"; + +const arcjet = arcjetDeno({ + key: Deno.env.get("ARCJET_KEY")!, + proxies: [ + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. + ], + rules: [], +}); diff --git a/src/snippets/reference/deno/trusted-ip.ts b/src/snippets/reference/deno/trusted-ip.ts new file mode 100644 index 00000000..561a5869 --- /dev/null +++ b/src/snippets/reference/deno/trusted-ip.ts @@ -0,0 +1,11 @@ +import "jsr:@std/dotenv/load"; +import arcjetDeno, { slidingWindow } from "@arcjet/deno"; + +const arcjet = arcjetDeno({ + key: Deno.env.get("ARCJET_KEY")!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/fastify/proxies.ts b/src/snippets/reference/fastify/proxies.ts new file mode 100644 index 00000000..a1de733c --- /dev/null +++ b/src/snippets/reference/fastify/proxies.ts @@ -0,0 +1,10 @@ +import arcjetFastify from "@arcjet/fastify"; + +const arcjet = arcjetFastify({ + key: process.env.ARCJET_KEY!, + proxies: [ + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. + ], + rules: [], +}); diff --git a/src/snippets/reference/fastify/trusted-ip.ts b/src/snippets/reference/fastify/trusted-ip.ts new file mode 100644 index 00000000..e311bcfc --- /dev/null +++ b/src/snippets/reference/fastify/trusted-ip.ts @@ -0,0 +1,10 @@ +import arcjetFastify, { slidingWindow } from "@arcjet/fastify"; + +const arcjet = arcjetFastify({ + key: process.env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // Assumes requests will have an `x-my-ip` header that you trust: + // @ts-expect-error: TODO does not yet exist. + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/nestjs/Proxies.ts b/src/snippets/reference/nestjs/Proxies.ts index 17f3d6d5..e5ed099d 100644 --- a/src/snippets/reference/nestjs/Proxies.ts +++ b/src/snippets/reference/nestjs/Proxies.ts @@ -5,19 +5,19 @@ import { ConfigModule } from "@nestjs/config"; @Module({ imports: [ ConfigModule.forRoot({ - isGlobal: true, envFilePath: ".env.local", + isGlobal: true, }), ArcjetModule.forRoot({ isGlobal: true, key: process.env.ARCJET_KEY!, + proxies: [ + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. + ], rules: [ // Rules set here will apply to every request ], - proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range - ], }), // ... other modules ], diff --git a/src/snippets/reference/nestjs/TrustedIp.ts b/src/snippets/reference/nestjs/TrustedIp.ts new file mode 100644 index 00000000..c816679f --- /dev/null +++ b/src/snippets/reference/nestjs/TrustedIp.ts @@ -0,0 +1,23 @@ +import { ArcjetModule, slidingWindow } from "@arcjet/nest"; +import { Module } from "@nestjs/common"; +import { ConfigModule } from "@nestjs/config"; + +@Module({ + imports: [ + ConfigModule.forRoot({ + envFilePath: ".env.local", + isGlobal: true, + }), + ArcjetModule.forRoot({ + isGlobal: true, + key: process.env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", + }), + // ... other modules + ], +}) +export class AppModule {} diff --git a/src/snippets/reference/nextjs/Proxies.ts b/src/snippets/reference/nextjs/Proxies.ts index a4dc33d8..9346f276 100644 --- a/src/snippets/reference/nextjs/Proxies.ts +++ b/src/snippets/reference/nextjs/Proxies.ts @@ -1,10 +1,10 @@ -import arcjet from "@arcjet/next"; +import arcjetNext from "@arcjet/next"; -const aj = arcjet({ +const arcjet = arcjetNext({ key: process.env.ARCJET_KEY!, - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }); diff --git a/src/snippets/reference/nextjs/TrustedIp.ts b/src/snippets/reference/nextjs/TrustedIp.ts new file mode 100644 index 00000000..b6d09885 --- /dev/null +++ b/src/snippets/reference/nextjs/TrustedIp.ts @@ -0,0 +1,10 @@ +import arcjetNext, { slidingWindow } from "@arcjet/next"; + +const arcjet = arcjetNext({ + key: process.env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/nodejs/Proxies.ts b/src/snippets/reference/nodejs/Proxies.ts index e500ebc2..9a5b007e 100644 --- a/src/snippets/reference/nodejs/Proxies.ts +++ b/src/snippets/reference/nodejs/Proxies.ts @@ -1,10 +1,10 @@ -import arcjet from "@arcjet/node"; +import arcjetNode from "@arcjet/node"; -const aj = arcjet({ +const arcjet = arcjetNode({ key: process.env.ARCJET_KEY!, - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }); diff --git a/src/snippets/reference/nodejs/TrustedIp.ts b/src/snippets/reference/nodejs/TrustedIp.ts new file mode 100644 index 00000000..0d986938 --- /dev/null +++ b/src/snippets/reference/nodejs/TrustedIp.ts @@ -0,0 +1,10 @@ +import arcjetNode, { slidingWindow } from "@arcjet/node"; + +const arcjet = arcjetNode({ + key: process.env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/react-router/proxies.ts b/src/snippets/reference/react-router/proxies.ts new file mode 100644 index 00000000..f3a66b81 --- /dev/null +++ b/src/snippets/reference/react-router/proxies.ts @@ -0,0 +1,10 @@ +import arcjetReactRouter from "@arcjet/react-router"; + +const arcjet = arcjetReactRouter({ + key: process.env.ARCJET_KEY!, + proxies: [ + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. + ], + rules: [], +}); diff --git a/src/snippets/reference/react-router/trusted-ip.ts b/src/snippets/reference/react-router/trusted-ip.ts new file mode 100644 index 00000000..0ece8900 --- /dev/null +++ b/src/snippets/reference/react-router/trusted-ip.ts @@ -0,0 +1,10 @@ +import arcjetReactRouter, { slidingWindow } from "@arcjet/react-router"; + +const arcjet = arcjetReactRouter({ + key: process.env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/remix/Proxies.ts b/src/snippets/reference/remix/Proxies.ts index 378116dc..d4e02a9e 100644 --- a/src/snippets/reference/remix/Proxies.ts +++ b/src/snippets/reference/remix/Proxies.ts @@ -1,10 +1,10 @@ -import arcjet from "@arcjet/remix"; +import arcjetRemix from "@arcjet/remix"; -const aj = arcjet({ +const arcjet = arcjetRemix({ key: process.env.ARCJET_KEY!, - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }); diff --git a/src/snippets/reference/remix/TrustedIp.ts b/src/snippets/reference/remix/TrustedIp.ts new file mode 100644 index 00000000..f8e9ea69 --- /dev/null +++ b/src/snippets/reference/remix/TrustedIp.ts @@ -0,0 +1,10 @@ +import arcjetRemix, { slidingWindow } from "@arcjet/remix"; + +const arcjet = arcjetRemix({ + key: process.env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/src/snippets/reference/sveltekit/Proxies.ts b/src/snippets/reference/sveltekit/Proxies.ts index 7619a199..863dc7df 100644 --- a/src/snippets/reference/sveltekit/Proxies.ts +++ b/src/snippets/reference/sveltekit/Proxies.ts @@ -1,11 +1,11 @@ import { env } from "$env/dynamic/private"; -import arcjet from "@arcjet/sveltekit"; +import arcjetSveltekit from "@arcjet/sveltekit"; -const aj = arcjet({ +const arcjet = arcjetSveltekit({ key: env.ARCJET_KEY!, - rules: [], proxies: [ - "100.100.100.100", // A single IP - "100.100.100.0/24", // A CIDR for the range + "76.76.21.21", // An IP address. + "103.21.244.0/22", // A CIDR range of IP addresses. ], + rules: [], }); diff --git a/src/snippets/reference/sveltekit/TrustedIp.ts b/src/snippets/reference/sveltekit/TrustedIp.ts new file mode 100644 index 00000000..44c5ded1 --- /dev/null +++ b/src/snippets/reference/sveltekit/TrustedIp.ts @@ -0,0 +1,11 @@ +import { env } from "$env/dynamic/private"; +import arcjetSveltekit, { slidingWindow } from "@arcjet/sveltekit"; + +const arcjet = arcjetSveltekit({ + key: env.ARCJET_KEY!, + // To illustrate, allow 3 requests per minute per IP address. + rules: [slidingWindow({ interval: 60, max: 3, mode: "LIVE" })], + // @ts-expect-error: TODO does not yet exist. + // Assumes requests will have an `x-my-ip` header that you trust: + trustedIpHeader: "x-my-ip", +}); diff --git a/tests/llms-txt.test.ts-snapshots/reference-astro-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-astro-chromium-linux.md index fd4480fa..fb7fafb6 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-astro-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-astro-chromium-linux.md @@ -104,7 +104,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. ### Single instance @@ -168,34 +169,7 @@ The Arcjet Astro SDK uses several environment variables to configure its behavio [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -astro.config.mjs - -``` -1import { defineConfig } from "astro/config";2import node from "@astrojs/node";3import arcjet from "@arcjet/astro";4 -5export default defineConfig({6 adapter: node({7 mode: "standalone",8 }),9 env: {10 validateSecrets: true,11 },12 integrations: [13 arcjet({14 rules: [],15 proxies: [16 "100.100.100.100", // A single IP17 "100.100.100.0/24", // A CIDR for the range18 ],19 }),20 ],21}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- @@ -524,7 +498,7 @@ The following are available on all pricing plans: #### Example -[Section titled “Example”](#example-1) +[Section titled “Example”](#example) astro.config.mjs diff --git a/tests/llms-txt.test.ts-snapshots/reference-bun-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-bun-chromium-linux.md index e066c109..aa15a03e 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-bun-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-bun-chromium-linux.md @@ -53,7 +53,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) @@ -173,32 +174,7 @@ index.js [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -``` -1import arcjet from "@arcjet/bun";2import { env } from "bun";3 -4const aj = arcjet({5 key: env.ARCJET_KEY!,6 rules: [],7 proxies: [8 "100.100.100.100", // A single IP9 "100.100.100.0/24", // A CIDR for the range10 ],11}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- diff --git a/tests/llms-txt.test.ts-snapshots/reference-nestjs-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-nestjs-chromium-linux.md index 7ced727c..6ff7a9a2 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-nestjs-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-nestjs-chromium-linux.md @@ -64,7 +64,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. src/app.module.ts @@ -125,32 +126,7 @@ src/app.module.ts [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -``` -1import { ArcjetModule } from "@arcjet/nest";2import { Module } from "@nestjs/common";3import { ConfigModule } from "@nestjs/config";4 -5@Module({6 imports: [7 ConfigModule.forRoot({8 isGlobal: true,9 envFilePath: ".env.local",10 }),11 ArcjetModule.forRoot({12 isGlobal: true,13 key: process.env.ARCJET_KEY!,14 rules: [15 // Rules set here will apply to every request16 ],17 proxies: [18 "100.100.100.100", // A single IP19 "100.100.100.0/24", // A CIDR for the range20 ],21 }),22 // ... other modules23 ],24})25export class AppModule {} -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Decision -------- @@ -363,7 +339,7 @@ The following are available on all pricing plans: #### Example -[Section titled “Example”](#example-1) +[Section titled “Example”](#example) ``` 1import { ARCJET, type ArcjetNest } from "@arcjet/nest";2import {3 Controller,4 Get,5 HttpException,6 HttpStatus,7 Inject,8 Injectable,9 Logger,10 Req,11} from "@nestjs/common";12import type { Request } from "express";13 diff --git a/tests/llms-txt.test.ts-snapshots/reference-nextjs-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-nextjs-chromium-linux.md index a813e90a..b7547ae8 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-nextjs-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-nextjs-chromium-linux.md @@ -82,7 +82,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) @@ -213,32 +214,7 @@ next.config.js [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -``` -1import arcjet from "@arcjet/next";2 -3const aj = arcjet({4 key: process.env.ARCJET_KEY!,5 rules: [],6 proxies: [7 "100.100.100.100", // A single IP8 "100.100.100.0/24", // A CIDR for the range9 ],10}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- @@ -637,7 +613,7 @@ The following are available on all pricing plans: #### Example -[Section titled “Example”](#example-1) +[Section titled “Example”](#example) * [TS (App)](#tab-panel-XXX) * [TS (Pages)](#tab-panel-XXX) diff --git a/tests/llms-txt.test.ts-snapshots/reference-nodejs-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-nodejs-chromium-linux.md index a8237b89..4e7690d3 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-nodejs-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-nodejs-chromium-linux.md @@ -62,7 +62,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) @@ -171,32 +172,7 @@ index.js [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -``` -1import arcjet from "@arcjet/node";2 -3const aj = arcjet({4 key: process.env.ARCJET_KEY!,5 rules: [],6 proxies: [7 "100.100.100.100", // A single IP8 "100.100.100.0/24", // A CIDR for the range9 ],10}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- @@ -435,7 +411,7 @@ The following are available on all pricing plans: #### Example -[Section titled “Example”](#example-1) +[Section titled “Example”](#example) * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) diff --git a/tests/llms-txt.test.ts-snapshots/reference-nuxt-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-nuxt-chromium-linux.md index 8dd18f4f..0bde66f9 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-nuxt-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-nuxt-chromium-linux.md @@ -114,7 +114,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. ### Single instance @@ -192,44 +193,7 @@ The Arcjet Nuxt SDK uses several environment variables to configure its behavior [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -* [TS](#tab-panel-XXX) -* [JS](#tab-panel-XXX) - -server/utils/arcjet.ts - -``` -1import { arcjet as arcjetNuxt } from "#arcjet";2 -3export const arcjet = arcjetNuxt({4 rules: [],5 proxies: [6 "100.100.100.100", // A single IP7 "100.100.100.0/24", // A CIDR for the range8 ],9}); -``` - -server/utils/arcjet.js - -``` -1import { arcjet as arcjetNuxt } from "#arcjet";2 -3export const arcjet = arcjetNuxt({4 rules: [],5 proxies: [6 "100.100.100.100", // A single IP7 "100.100.100.0/24", // A CIDR for the range8 ],9}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- @@ -553,7 +517,7 @@ The following are available on all pricing plans: #### Example -[Section titled “Example”](#example-1) +[Section titled “Example”](#example) * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) diff --git a/tests/llms-txt.test.ts-snapshots/reference-remix-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-remix-chromium-linux.md index 6eb1e556..8787e675 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-remix-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-remix-chromium-linux.md @@ -62,7 +62,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) @@ -171,32 +172,7 @@ index.js [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -``` -1import arcjet from "@arcjet/remix";2 -3const aj = arcjet({4 key: process.env.ARCJET_KEY!,5 rules: [],6 proxies: [7 "100.100.100.100", // A single IP8 "100.100.100.0/24", // A CIDR for the range9 ],10}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- @@ -435,7 +411,7 @@ The following are available on all pricing plans: #### Example -[Section titled “Example”](#example-1) +[Section titled “Example”](#example) * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) diff --git a/tests/llms-txt.test.ts-snapshots/reference-sveltekit-chromium-linux.md b/tests/llms-txt.test.ts-snapshots/reference-sveltekit-chromium-linux.md index 947d47b6..0f37f529 100644 --- a/tests/llms-txt.test.ts-snapshots/reference-sveltekit-chromium-linux.md +++ b/tests/llms-txt.test.ts-snapshots/reference-sveltekit-chromium-linux.md @@ -80,7 +80,8 @@ The required fields are: The optional fields are: * `characteristics` (`string[]`) - A list of [characteristics](/fingerprints#built-in-characteristics) to be used to uniquely identify clients. -* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See [Load balancers & proxies](#load-balancers--proxies) below for an example. +* `proxies` (`string[]`) - A list of one or more trusted proxies. These addresses will be excluded when Arcjet is determining the client IP address. This is useful if you are behind a load balancer or proxy that sets the client IP address in a header. See “[Concepts: Client IP](/concepts/client-ip)” for more info. +* `trustedIpHeader` (`string`) - Name of (lowercase) HTTP request header that you trust (such as `x-fah-client-ip`). This value is _preferred_ over IP addresses provided by the framework and IP addresses found in other headers based on the platform, in both development and production. It can point to a regular IP (such as `x-client-ip`) or a list of IPs (such as `x-forwarded-for`). It can contain IPv4 or IPv6 addresses. Proxies are filtered out. See “[Concepts: Client IP](/concepts/client-ip)” for more info. * [TS](#tab-panel-XXX) * [JS](#tab-panel-XXX) @@ -194,32 +195,7 @@ index.js [Section titled “Load balancers & proxies”](#load-balancers--proxies) -If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. - -To fix this, most load balancers will set the `X-Forwarded-For` header with the real client IP address plus a list of proxies that the request has passed through. - -The problem with is that the `X-Forwarded-For` header can be spoofed by the client, so you should only trust it if you are sure that the load balancer is setting it correctly. See [the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) for more details. - -You can configure Arcjet to trust IP addresses in the `X-Forwarded-For` header by setting the `proxies` field in the configuration. This should be a list of the IP addresses or the CIDR range of your load balancers to be removed, so that the last IP address in the list is the real client IP address. - -#### Example - -[Section titled “Example”](#example) - -For example, if the load balancer is at `100.100.100.100` and the client IP address is `192.168.1.1`, the `X-Forwarded-For` header will be: - -``` -X-Forwarded-For: 192.168.1.1, 100.100.100.100 -``` - -You should set the `proxies` field to `["100.100.100.100"]` so Arcjet will use `192.168.1.1` as the client IP address. - -You can also specify CIDR ranges to match multiple IP addresses. - -``` -1import { env } from "$env/dynamic/private";2import arcjet from "@arcjet/sveltekit";3 -4const aj = arcjet({5 key: env.ARCJET_KEY!,6 rules: [],7 proxies: [8 "100.100.100.100", // A single IP9 "100.100.100.0/24", // A CIDR for the range10 ],11}); -``` +If your application is behind a load balancer, Arcjet will only see the IP address of the load balancer and not the real client IP address. You can configure Arcjet to trust particular IP addresses. See “[Concepts: Client IP](/concepts/client-ip)” for more info. Protect ------- diff --git a/tests/screenshot.test.ts-snapshots/screenshot-architecture-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-architecture-dark-chromium-linux.png index d8dad5b0..44cf850c 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-architecture-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-architecture-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-architecture-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-architecture-light-chromium-linux.png index 8aa5e637..50f5030f 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-architecture-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-architecture-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-best-practices-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-best-practices-dark-chromium-linux.png index c0ab47b7..b779379e 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-best-practices-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-best-practices-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-best-practices-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-best-practices-light-chromium-linux.png index 46e3e06e..23d54a63 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-best-practices-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-best-practices-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-dark-chromium-linux.png index 13c8e1d1..524144c8 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-light-chromium-linux.png index 0ad9df83..80374627 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-aikido-vs-arcjet-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-dark-chromium-linux.png index 28c52dcb..e2c5bdd1 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-light-chromium-linux.png index 48adf412..ff3954d3 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-comparisons-vercel-botid-vs-arcjet-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-dark-chromium-linux.png index 6a225570..cef69b20 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-light-chromium-linux.png index 7ab757dc..a55b31f0 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-dark-chromium-linux.png index e1e990b7..dad388ea 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-light-chromium-linux.png index 6d5d2a77..98a7ed48 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-dark-chromium-linux.png index 8ca006df..df69356e 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-light-chromium-linux.png index b8179ac0..5adec311 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-email-validation-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-examples-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-examples-dark-chromium-linux.png index f6a8092b..1ad3b7c6 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-examples-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-examples-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-examples-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-examples-light-chromium-linux.png index 6803841d..c3fff1a4 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-examples-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-examples-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-filters-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-filters-dark-chromium-linux.png index 2331aea8..b99ab698 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-filters-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-filters-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-filters-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-filters-light-chromium-linux.png index f9bb0ab0..f19c133a 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-filters-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-filters-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-dark-chromium-linux.png index 66123740..54661fca 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-light-chromium-linux.png index a6fe63f7..395cab77 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-filters-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-dark-chromium-linux.png index 64b10674..6786f0b2 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-light-chromium-linux.png index d8feba68..795461fd 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-filters-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-dark-chromium-linux.png index ce2828a5..9623f9d0 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-light-chromium-linux.png index bcb2d65c..c7593b4a 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-fingerprints-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-get-started-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-get-started-dark-chromium-linux.png index 64bd0f7d..a3078eeb 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-get-started-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-get-started-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-get-started-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-get-started-light-chromium-linux.png index 72b24df2..b0e827ad 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-get-started-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-get-started-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-home-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-home-dark-chromium-linux.png index c0d89129..9ad67595 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-home-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-home-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-home-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-home-light-chromium-linux.png index 93337b84..6e657896 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-home-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-home-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-inspect-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-inspect-dark-chromium-linux.png index 4188d902..8c0a1635 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-inspect-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-inspect-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-inspect-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-inspect-light-chromium-linux.png index 7113c250..9eafc9f5 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-inspect-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-inspect-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-dark-chromium-linux.png index c4633a66..0a102ed4 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-light-chromium-linux.png index a2b01d8a..94a0cd02 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-authjs-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-dark-chromium-linux.png index d6571805..37bfa5a1 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-light-chromium-linux.png index da702fb2..e2691422 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-better-auth-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-dark-chromium-linux.png index 6eae57c0..e56a01c5 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-light-chromium-linux.png index f94dd796..e412dbe6 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-clerk-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-dark-chromium-linux.png index 3a9b8f3d..25c75574 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-light-chromium-linux.png index 1ec16899..bb542160 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-langchain-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-dark-chromium-linux.png index 31be7859..e6b2be01 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-light-chromium-linux.png index f450a946..a8b160ba 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-nextauth-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-dark-chromium-linux.png index 9a924384..83f93da5 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-light-chromium-linux.png index 358dc2f6..36d9a247 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-integrations-openai-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-ip-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-ip-dark-chromium-linux.png index 78184916..3930b1ec 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-ip-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-ip-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-ip-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-ip-light-chromium-linux.png index b11ff62b..fd14853d 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-ip-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-ip-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-limitations-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-limitations-dark-chromium-linux.png index b5ba9d9c..0796adc1 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-limitations-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-limitations-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-limitations-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-limitations-light-chromium-linux.png index 681cdf15..bbf83ef7 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-limitations-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-limitations-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-dark-chromium-linux.png index 4f65fddf..3f73f524 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-light-chromium-linux.png index a561cec7..3e15817f 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-dark-chromium-linux.png index 41a62acc..996a2219 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-light-chromium-linux.png index 88ab93dd..f1c087c1 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-nosecone-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-privacy-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-privacy-dark-chromium-linux.png index a0362847..334b4329 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-privacy-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-privacy-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-privacy-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-privacy-light-chromium-linux.png index ba94a456..bb5b8559 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-privacy-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-privacy-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-dark-chromium-linux.png index 9d0e48d3..70b5038f 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-light-chromium-linux.png index bb973b53..975f7436 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-redact-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-dark-chromium-linux.png index 42010c7c..d68c87e9 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-light-chromium-linux.png index 3a731013..b08dd937 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-redact-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-dark-chromium-linux.png index 4b8519b0..14592ac4 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-light-chromium-linux.png index d7fbf03a..167694f2 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-astro-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-dark-chromium-linux.png index 72d2b5aa..ed6cffed 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-light-chromium-linux.png index 834e6276..8f3e01e4 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-bun-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-dark-chromium-linux.png index 87da9a56..247116c4 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-light-chromium-linux.png index 0fa810c8..7ab01290 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-deno-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-dark-chromium-linux.png index a05864ed..fef75cae 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-light-chromium-linux.png index a96d784a..9d95b3ed 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-fastify-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-dark-chromium-linux.png index bcd467e2..0bbf0d3e 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-light-chromium-linux.png index 64a1032e..5ab24966 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nestjs-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-dark-chromium-linux.png index 9cffafd5..040d9ec2 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-light-chromium-linux.png index 2da8ef86..65d99ed6 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nextjs-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-dark-chromium-linux.png index bb7091ab..1bcfa3b2 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-light-chromium-linux.png index 579641c9..9b6b71fc 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nodejs-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-dark-chromium-linux.png index 8f4660f0..fb6a0b3b 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-light-chromium-linux.png index 38e0f9df..41f6fdf0 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-nuxt-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-dark-chromium-linux.png index 00a9f1c2..541342c0 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-light-chromium-linux.png index 1dd0fcfa..a7f5abcb 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-react-router-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-dark-chromium-linux.png index 317f2569..d5f94a27 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-light-chromium-linux.png index f9b03ba0..76a16724 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-remix-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-dark-chromium-linux.png index 96778612..12c1ec97 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-light-chromium-linux.png index a8932699..13c89337 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-reference-sveltekit-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-regions-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-regions-dark-chromium-linux.png index fba01ea0..8e9328ed 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-regions-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-regions-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-regions-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-regions-light-chromium-linux.png index 6fe09e5e..9c7e7e6a 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-regions-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-regions-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-security-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-security-dark-chromium-linux.png index fa5b7d63..70feb621 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-security-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-security-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-security-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-security-light-chromium-linux.png index c26695bc..677ba6ab 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-security-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-security-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-dark-chromium-linux.png index be5ab224..92f29fe3 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-light-chromium-linux.png index 1be84dd1..faf76cbd 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-dark-chromium-linux.png index b72921b0..09f0ee8e 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-light-chromium-linux.png index 0315b0fe..6b5cd67c 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-dark-chromium-linux.png index 5a3652f3..a72aaf21 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-light-chromium-linux.png index 1bd332b2..1ba329f7 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-sensitive-info-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-shield-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-shield-dark-chromium-linux.png index e7c5eda2..2115eec0 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-shield-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-shield-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-shield-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-shield-light-chromium-linux.png index 1908de32..9a0f66f1 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-shield-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-shield-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-dark-chromium-linux.png index cfe64a76..9f09da4b 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-light-chromium-linux.png index 7ff0fd51..cc82cc37 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-shield-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-dark-chromium-linux.png index fd77047c..c9037322 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-light-chromium-linux.png index 276e5d6b..85382b87 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-shield-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-dark-chromium-linux.png index 1345e335..3f8e528d 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-light-chromium-linux.png index 8c72892b..6f1eba29 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-dark-chromium-linux.png index 8958bd0b..7a6e3912 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-light-chromium-linux.png index 90459f49..bbc97440 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-quick-start-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-dark-chromium-linux.png index 648ed11f..3443c214 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-light-chromium-linux.png index 12aa8953..12f3d60b 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-signup-protection-reference-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-support-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-support-dark-chromium-linux.png index a71b5235..e929ce11 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-support-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-support-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-support-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-support-light-chromium-linux.png index 0c25cee4..ecc0741b 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-support-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-support-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-testing-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-testing-dark-chromium-linux.png index 0efaad1b..f789169c 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-testing-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-testing-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-testing-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-testing-light-chromium-linux.png index e2c1987f..10ca0c3e 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-testing-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-testing-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-dark-chromium-linux.png index 8bbe56a6..fd3e4c59 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-light-chromium-linux.png index 00da00dd..07fd326e 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-troubleshooting-light-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-dark-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-dark-chromium-linux.png index d9cc307d..cacd0636 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-dark-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-dark-chromium-linux.png differ diff --git a/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-light-chromium-linux.png b/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-light-chromium-linux.png index 57a3694f..18e5e067 100644 Binary files a/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-light-chromium-linux.png and b/tests/screenshot.test.ts-snapshots/screenshot-upgrading-sdk-migration-light-chromium-linux.png differ