# DOM changes are cleaned up

- **Pattern:** `ab-001334` (`extension-permissions-security.content-script-isolation.dom-cleanup`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001334
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001334)

## Why it matters

When a Chrome extension is updated or disabled while the user has a tab open, the content script context is invalidated but any DOM elements it injected remain. Without cleanup logic, updating the extension leaves orphaned buttons, sidebars, or overlays on long-lived pages — a support and reliability failure that manifests as 'ghost UI' that does nothing when clicked. ISO 25010 reliability requirements apply: a component that cannot clean up its own side effects on context invalidation is not reliably bounded. In enterprise environments where tabs stay open for days, uncleaned DOM from invalidated extension contexts accumulates and causes user-visible breakage.

## Severity rationale

Low because orphaned DOM elements are a reliability failure rather than a security vulnerability, but they directly surface to users as broken UI after every extension update.

## Remediation

Connect a port in your content script and listen for `onDisconnect` to remove injected elements when the extension context is invalidated.

```javascript
// src/content.js
const port = chrome.runtime.connect();
port.onDisconnect.addListener(() => {
  host.remove(); // Clean up injected UI
});
```

Alternatively, assign a unique `data-extension-id` attribute to all injected elements and remove them all via `querySelectorAll` in a MutationObserver callback that detects context invalidation.

## Detection

- **ID:** `dom-cleanup`
- **Severity:** `low`
- **What to look for:** Search content scripts for cleanup handlers: `runtime.onDisconnect`, `disconnect` event listeners, `MutationObserver` teardown, or element removal logic. Count the number of injected elements vs cleanup handlers.
- **Pass criteria:** At least 1 cleanup mechanism exists to remove orphan UI elements when the extension is updated, disabled, or when the content script disconnects. Logic handles `runtime.onDisconnect` or equivalent.
- **Fail criteria:** No cleanup logic found in content scripts for injected UI.
- **Skip (N/A) when:** No UI injection in content scripts.
- **Detail on fail:** `"No cleanup logic for injected UI. Updates may leave 'ghost' buttons or duplicate UIs on long-lived pages."`
- **Remediation:** Listen for the `runtime.onDisconnect` event in your content script or use a MutationObserver pattern to detect if your extension context has been invalidated, and clean up your DOM elements.

  ```javascript
  // src/content.js
  const port = chrome.runtime.connect();
  port.onDisconnect.addListener(() => { host.remove(); });
  ```

---

## External references

- iso-25010 reliability.recoverability

Taxons: error-resilience

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