Index of every page on this site: llms.txt

Nuxt OG Image ships with secure defaults. The module clamps image dimensions, time limits renders, blocks internal network requests, and sanitizes user-provided props. These protections require no configuration.

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, AWS WAF, or your hosting provider's built-in rate limiting can add an additional layer of defense.

.env
NUXT_APP_SECRET=<your-secret>
nuxt.config.ts
export default defineNuxtConfig({
  ogImage: {
    security: {
      strict: true,
    }
  }
})

The secret is automatically picked up from the NUXT_APP_SECRET environment variable.

V7 also accepts NUXT_OG_IMAGE_SECRET when the application secret is empty, with a deprecation warning. Rename the old key to NUXT_APP_SECRET and keep its value unchanged. Existing v6 signatures still need refreshing because V7 derives a new signing key.

Strict Mode

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

  • URL signing required: Nuxt appSecret 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.

Strict mode requires signing. Set NUXT_APP_SECRET before prerendering strict pages or serving production requests. Generate one with:

npx nuxt-og-image generate-secret

URL Signing

OG image URLs are signed by default. Every URL includes a cryptographic signature in the path, and the server rejects any runtime request whose signature is missing or invalid with a 403. This prevents unauthorized image generation requests that would otherwise consume server resources.

Default: Nuxt application secret

The module derives its signing secret from Nuxt runtimeConfig.appSecret with the purpose nuxt-og-image:url-signing. Set NUXT_APP_SECRET to at least 32 characters in production. Nuxt generates and persists a development secret when none is configured. Builds never generate a secret. Normal static prerendering does not require one.

If the production secret is missing or shorter than 32 characters, the image endpoints fail closed. OG image requests then return 500, and pages still render. The server logs an error with the fix once per instance. If you prerender strict pages without a secret, those pages fail to prerender. If no renderer is installed, OG images are off and the module never reads the secret.

Use the same application secret across instances and deployments to keep signed URLs valid. If the application secret changes, existing signed URLs become invalid.

Disabling signing

To serve unsigned runtime URLs (not recommended), set secret to false:

nuxt.config.ts
export default defineNuxtConfig({
  ogImage: {
    security: {
      secret: false,
    }
  }
})
With signing disabled, an attacker can do more than trigger arbitrary renders: by supplying a cacheKey in the request they can poison the runtime cache, overwriting the cached image that your legitimate OG image URLs serve and spoofing the preview shown on social platforms. Only disable signing if the /_og/ endpoint is otherwise protected (a WAF, origin restriction) or your images are fully prerendered.

Setup (stable secret)

  1. Generate a secret:
npx nuxt-og-image generate-secret
  1. Set the environment variable:
.env
NUXT_APP_SECRET=<your-secret>

Alternatively, set Nuxt runtimeConfig.appSecret in your Nuxt configuration. Do not place a production secret in source control.

How It Works

With signing active:

  • 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.

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

Prerender Your Images

The most effective security measure is to prerender your OG images at build time using Zero Runtime mode. Prerendered images are served as static files with no runtime rendering code in your production build.

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

When you enable zero runtime:

  • Your production build includes no server-side rendering code
  • The build generates images once and serves them 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 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.

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.

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

Requests exceeding this limit receive a 400 response.

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

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 for the recommended pattern.

Restrict Runtime Images to Origin

When you enable runtime image generation, 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.

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 url. If the hosts don't match, the request receives a 403 response.

Because HTTP/1.1 requires the Host header, this check works with all clients including social media crawlers. The server does not need an Origin or Referer header.

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.

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.

Prerendering and dev mode bypass the host check entirely.

Debug Mode Warning

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

nuxt.config.ts
export default defineNuxtConfig({
  ogImage: {
    debug: false, // never enable in production
  }
})
Was this page helpful?