# Third-party scripts use async or defer

- **Pattern:** `ab-002431` (`security-headers-ii.supply-chain.third-party-async`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002431
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002431)

## Why it matters

Render-blocking third-party scripts couple your page's availability to an external CDN's response time and reliability. If the CDN is slow, your page hangs for every user. If the CDN is compromised or returns a 503, your page may fail to render entirely. Independently, synchronous script loading creates a timing window during which a slow or compromised CDN script executes before your application code, with full access to the page. CWE-829 (Inclusion of Functionality from Untrusted Control Sphere) applies. OWASP A08 flags synchronous third-party script loading as a supply chain risk that combines performance impact with security exposure.

## Severity rationale

Medium because render-blocking third-party scripts create both a reliability dependency on external CDN uptime and a security window where externally controlled code executes before application initialization.

## Remediation

Add `async` or `defer` to every `<script>` tag loading from an external domain. Use `async` for independent scripts that do not need DOM or other scripts; use `defer` for scripts that must execute after parsing or in a specific order.

```html
<!-- async: downloads in parallel, executes immediately when ready -->
<script async src="https://www.googletagmanager.com/gtag/js"></script>

<!-- defer: downloads in parallel, executes after HTML parsing -->
<script defer src="https://cdn.example.com/lib.js"></script>
```

In Next.js, use `<Script strategy='afterInteractive'>` or `strategy='lazyOnload'` from `next/script` for third-party scripts — these automatically handle async loading with framework-aware timing.

## Detection

- **ID:** `third-party-async`
- **Severity:** `medium`
- **What to look for:** Search all HTML templates, page components, and layout files for `<script>` tags loading from external domains. For each third-party script, check whether `async` or `defer` is present. Render-blocking third-party scripts are both a performance issue and a security risk — if the CDN is slow or compromised, your entire page hangs. Count all third-party script tags.
- **Pass criteria:** 100% of third-party scripts use `async` or `defer`. Report: "X of Y third-party scripts use async/defer."
- **Fail criteria:** Any third-party script tag lacks both `async` and `defer`.
- **Skip (N/A) when:** No third-party scripts loaded — all scripts are first-party or bundled.
- **Detail on fail:** `"X of Y third-party scripts are render-blocking (no async/defer) — page load depends on external CDN availability"` or `"Google Analytics script loaded without async attribute"`
- **Remediation:** Third-party scripts should never block page rendering. Add `async` (executes as soon as downloaded) or `defer` (executes after parsing):

  ```html
  <!-- async: executes immediately when downloaded -->
  <script async src="https://cdn.example.com/analytics.js"></script>

  <!-- defer: executes after HTML parsing, in order -->
  <script defer src="https://cdn.example.com/lib.js"></script>
  ```

  Use `async` for independent scripts (analytics, tracking). Use `defer` for scripts that depend on DOM or execution order.

## External references

- cwe CWE-829
- owasp A08

Taxons: supply-chain, performance

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