---
title: "Security"
description: "Learn about the security defaults and how to further harden your OG image endpoint."
canonical_url: "https://nuxtseo.com/docs/og-image/guides/security"
last_updated: "2026-05-20T20:35:27.113Z"
---

Nuxt OG Image ships with secure defaults. Image dimensions are clamped, renders are time limited, internal network requests are blocked, and user provided props are sanitized. No configuration is needed for these protections.

The primary security concern with runtime OG image generation is **denial of service**: without protection, anyone can craft arbitrary image generation requests to your `/_og/d/` endpoint, consuming server CPU and memory. URL signing prevents this by ensuring only your application can generate valid image URLs.

For full protection, we recommend combining URL signing with a **web application firewall** (WAF) or rate limiting on the `/_og/` path prefix. Services like [Cloudflare](https://cloudflare.com), AWS WAF, or your hosting provider's built-in rate limiting can add an additional layer of defense.

```bash [.env]
NUXT_OG_IMAGE_SECRET=<your-secret>
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    security: {
      strict: true,
    }
  }
})
```

The secret is automatically picked up from the `NUXT_OG_IMAGE_SECRET` environment variable.

## Strict Mode

Enabling `strict` mode applies all recommended security defaults in a single flag:

- **URL signing required**: `secret` must be set (rejects unsigned runtime requests with `403`)
- **Inline HTML disabled**: The deprecated `html` option is stripped entirely, preventing SSRF via inline HTML injection
- **Query string size limit**: `maxQueryParamSize` defaults to `2048` characters (instead of no limit)
- **Origin restriction**: `restrictRuntimeImagesToOrigin` defaults to `true`, locking runtime generation to your site config URL host

Any of these can still be overridden explicitly. Strict mode only changes the defaults.

The build will fail if `strict` is enabled without a `secret`. Generate one with:

```bash
npx nuxt-og-image generate-secret
```

## URL Signing

When a signing secret is configured, every OG image URL includes a cryptographic signature in the path. The server verifies this signature before rendering, rejecting any URL that has been tampered with or crafted manually.

This prevents unauthorized image generation requests that would otherwise consume server resources.

### Setup

1. Generate a secret:

```bash
npx nuxt-og-image generate-secret
```

1. Set the environment variable:

```bash [.env]
NUXT_OG_IMAGE_SECRET=<your-secret>
```

Alternatively, you can set the secret directly in your nuxt config:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    security: {
      secret: 'your-secret',
    }
  }
})
```

### How It Works

When a secret is configured:

- `defineOgImage()` appends a signature to the URL path: `/_og/d/w_1200,h_600,s_abc123def456.png`
- The server extracts and verifies the signature before processing the request
- Requests with missing or invalid signatures receive a `403` response
- All query parameter overrides are ignored (the signed path is the single source of truth)

The signature is deterministic: the same options with the same secret always produce the same URL. This means URLs are stable across server restarts and deployments as long as the secret does not change.

### Defense in Depth

URL signing works alongside the other security options (`maxDimension`, `maxQueryParamSize`, `renderTimeout`, `restrictRuntimeImagesToOrigin`) which continue to apply as defense-in-depth. When signing is active, query parameter overrides are ignored but the query string size limit still applies to reduce parsing overhead.

<note>

Dev mode and prerendering bypass signature verification. Signing only applies to runtime requests in production.

</note>

## Prerender Your Images

The most effective security measure is to **prerender your OG images at build time** using [Zero Runtime mode](/docs/og-image/guides/zero-runtime). Prerendered images are served as static files with no runtime rendering code in your production build.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    zeroRuntime: true
  }
})
```

When zero runtime is enabled:

- No server-side rendering code is included in your production build
- Images are generated once at build time and served as static assets
- The `/_og` endpoint is not available at runtime

If your OG images don't need to change dynamically after deployment, this is the recommended approach.

For sites that need a mix of static and dynamic images, you can prerender specific routes while keeping runtime generation available for others. See the [Zero Runtime guide](/docs/og-image/guides/zero-runtime) for configuration details.

## Dimension and Render Limits

Every request has its `width` and `height` clamped to `maxDimension` (default `2048` pixels). The Takumi renderer's `devicePixelRatio` is capped to `maxDpr` (default `2`).

If a render exceeds `renderTimeout` (default `15000ms`), it is aborted and the server returns a `408` status.

These are all enabled by default. You only need to configure them if you want different limits.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    security: {
      maxDimension: 2048,
      maxDpr: 2,
      renderTimeout: 15000,
    }
  }
})
```

## Query String Size Limit

OG image options can be passed via query parameters when URL signing is not enabled. You can set `maxQueryParamSize` to reject requests with oversized query strings.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    security: {
      maxQueryParamSize: 2048, // characters
    }
  }
})
```

Requests exceeding this limit receive a `400` response.

<note>

When URL signing is active, query parameter overrides are ignored, but this size limit still applies to reduce request parsing overhead.

</note>

If you find yourself passing large amounts of data through query parameters (titles, descriptions, full text), consider loading that data inside your OG image component instead. See the [Performance guide](/docs/og-image/guides/performance#reduce-url-size) for the recommended pattern.

## Restrict Runtime Images to Origin

When runtime image generation is enabled, anyone who knows the `/_og` endpoint pattern can request an image directly. The `restrictRuntimeImagesToOrigin` option limits runtime generation to requests whose `Host` header matches your configured site URL.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    security: {
      restrictRuntimeImagesToOrigin: true,
    }
  }
})
```

### How It Works

The module reads the `Host` header from each runtime request using h3's `getRequestHost` (with `X-Forwarded-Host` support for reverse proxies) and compares it against the host from your [Nuxt Site Config](https://nuxtseo.com/docs/site-config/getting-started/introduction) `url`. If the hosts don't match, the request receives a `403` response.

Because the `Host` header is mandatory in HTTP/1.1, this check works with all clients including social media crawlers. No `Origin` or `Referer` header is required.

### Allowing Additional Origins

To allow extra origins (e.g. a CDN or preview deployment), pass an array. Your site config origin is always included automatically.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    security: {
      restrictRuntimeImagesToOrigin: ['https://cdn.example.com', 'https://preview.example.com'],
    }
  }
})
```

We **disable this option by default** to avoid surprises for sites behind non-standard proxy setups. If your reverse proxy forwards the correct `Host` or `X-Forwarded-Host` header, you can safely enable it.

<note>

Prerendering and dev mode bypass the host check entirely.

</note>

## Debug Mode Warning

Enabling `ogImage.debug` in production exposes the `/_og/debug.json` endpoint. The module will log a warning at build time if debug is enabled outside of dev mode. Make sure to disable it before deploying.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  ogImage: {
    debug: false, // never enable in production
  }
})
```
