# OG image URL is absolute and publicly accessible

- **Pattern:** `ab-001821` (`marketing-social-sharing.share-infrastructure.og-image-accessible`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001821
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001821)

## Why it matters

Social platform crawlers (Facebookbot, LinkedInBot, Twitterbot) do not follow browser URL resolution rules. A relative path like `/og-image.png` in an og:image tag is treated as an unresolvable reference — the crawler makes no attempt to prefix a base URL. Per ogp.me, og:image must be an absolute URL. Similarly, when og:image is constructed from an environment variable like `NEXT_PUBLIC_SITE_URL` that has no fallback, a missing env var in production results in `undefined/og-image.png` — a malformed URL that produces no image. Per CWE-706, using incorrect resource identifiers in safety-critical paths leads to silent failures. These failures are invisible in local development because browsers resolve relative paths correctly.

## Severity rationale

High because relative og:image paths and unguarded environment variable references cause crawlers to silently fail to load the image, producing card previews with no visual on production shares.

## Remediation

Fix relative og:image paths by prepending an absolute base URL with a fallback:

```ts
// WRONG:
images: [{ url: '/og-image.png', width: 1200, height: 630 }]

// RIGHT:
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://yoursite.com'
images: [{ url: `${baseUrl}/og-image.png`, width: 1200, height: 630 }]
```

For Next.js App Router routes that use `opengraph-image.tsx`, the framework generates absolute URLs automatically — no changes needed for those routes. Audit all `metadata.openGraph.images` entries in `src/app/` for relative paths and unguarded env var references.

## Detection

- **ID:** `og-image-accessible`
- **Severity:** `high`
- **What to look for:** Check all `og:image` URLs (in `metadata.openGraph.images` arrays, hardcoded image paths, or `ImageResponse`-generated URLs). Verify that: (1) The URL is absolute (starts with `https://`), not relative (starts with `/`). (2) The URL does not require authentication (no `/api/` prefix that might be behind middleware). (3) The URL is not conditionally constructed from environment variables that might be null in production (e.g., `${process.env.NEXT_PUBLIC_SITE_URL}/og.png` where the env var might not be set). Count every unique og:image URL referenced across the site. For each, classify as accessible (HTTP 200, correct content-type) or inaccessible.
- **Pass criteria:** All `og:image` URLs in the codebase are either absolute HTTPS URLs or constructed from environment variables that are reliably set in production. No OG image URL is a bare relative path. Report even on pass: "X of Y unique og:image URLs confirmed accessible with correct content-type." At least 1 implementation must be confirmed.
- **Fail criteria:** Any `og:image` URL is a relative path (e.g., `"/og-image.png"`), OR any OG image URL is constructed using an environment variable that appears to have no fallback value, OR any OG image path is under a route that might be protected by auth middleware.
- **Skip (N/A) when:** No OG image configuration found anywhere.
- **Cross-reference:** The `og-image-dimensions` check in Open Graph verifies the dimensions of the images this check confirms are loadable.
- **Detail on fail:** `"og:image is set to relative path '/og-image.png' — social crawlers cannot resolve relative URLs and will not display the image"` or `"OG image URL uses NEXT_PUBLIC_SITE_URL with no fallback — if env var is unset, image URL will be undefined"`
- **Remediation:** Social platform crawlers do not follow browser URL resolution rules. They need an absolute URL to fetch the image. Fix relative paths:

  ```ts
  // WRONG:
  images: [{ url: '/og-image.png', width: 1200, height: 630 }]

  // RIGHT:
  const baseUrl = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://yoursite.com'
  images: [{ url: `${baseUrl}/og-image.png`, width: 1200, height: 630 }]
  ```

  For Next.js App Router's built-in OG image routes (`opengraph-image.tsx`), the framework automatically generates absolute URLs — no additional configuration needed.

## External references

- external ogp.me — https://ogp.me/
- cwe CWE-706

Taxons: findability, reference-integrity

HTML version: https://auditbuffet.com/patterns/ab-001821
