← Blog

MCP server SVG feGaussianBlur stdDeviation consent security

Four SA-CSS-GSD consent attack patterns using the feGaussianBlur stdDeviation attribute — extreme sigma to blur dark text to near-white via luminance averaging, anisotropic X/Y sigma to smear glyphs into unreadable bands, and JS mousedown stdDeviation injection for click-time attacks.

By SkillAudit  |  23 Oct 2026

The feGaussianBlur filter primitive applies a Gaussian blur with standard deviation controlled by stdDeviation. The attribute accepts a single value (isotropic blur, same sigma in X and Y) or two values separated by a space (anisotropic blur, independent sigma per axis). The blur is defined as a convolution with a Gaussian kernel: for sigma=s, each output pixel is a weighted average of a neighborhood spanning approximately ±3s pixels in each direction.

Luminance-averaging property: For dark text (luminance ≈ 0.05) on a white background (luminance = 1.0), a large-sigma Gaussian blur averages each text pixel with a large white neighborhood. Since glyph pixels are vastly outnumbered by background pixels within any large radius, the blur output at former glyph positions approaches background luminance. At stdDeviation=100, the contrast ratio between blurred text and background is typically below 1.1:1 — visually absent text despite the DOM element remaining fully present.

SA-CSS-GSD-001: stdDeviation=100 extreme isotropic blur

With stdDeviation="100", the Gaussian kernel radius spans approximately ±300px. For a typical consent panel line of text (glyph height ~16px, glyph width ~8px per character), the glyph area is less than 1% of the blur kernel area. The weighted average of the blur output at any former glyph pixel is dominated by the surrounding white background luminance. For dark text (e.g., #111111, luminance ≈ 0.014), the blur output luminance approaches: L_out ≈ 0.99 × L_white + 0.01 × L_text ≈ 0.99. Resulting contrast ratio against white background: (1 + 0.05) / (0.99 + 0.05) ≈ 1.01:1 — below any legibility threshold. The element remains in the DOM, getBoundingClientRect returns the original dimensions, textContent is intact, and getComputedStyle.color returns the original foreground color.

<filter id="gsd1">
  <feGaussianBlur stdDeviation="100"/>
</filter>
<div style="filter:url(#gsd1)">
  I agree to the terms and conditions. Click here to proceed.
</div>
<!-- sigma=100: blur radius ~300px; dark glyph pixels averaged with white surroundings → near-white output -->

False positive prevention: stdDeviation=0 is an identity transform — no blur is applied and the element is fully visible. Do NOT flag stdDeviation=0 as an attack. The threshold for consent impact depends on element size: for a 400×80px panel, stdDeviation > element_height / 2 (i.e., > 40) is typically sufficient for full blur-to-white. Flag stdDeviation > max(element_width, element_height) × 0.25 as high-risk.

SA-CSS-GSD-002: stdDeviation="100 0" anisotropic horizontal smear

The two-value form stdDeviation="σX σY" applies independent sigma values per axis. With stdDeviation="100 0", the X axis receives extreme blur (sigma=100) while the Y axis receives no blur (sigma=0). The effect: each row of pixels is averaged horizontally across ±300px but not averaged vertically. Individual character glyphs are smeared horizontally into grey bands spanning the full element width. The text is unreadable — no glyph shapes survive — but the output is not near-transparent. Each row value equals the average luminance of that row across the element, which for a row that is mostly background but contains some glyph pixels produces a light-gray value (contrast ≈ 1.2:1 against the background). This attack evades: alpha=0 detection, near-transparent detection, and even some blur-threshold checks that only measure isotropic sigma.

<filter id="gsd2">
  <feGaussianBlur stdDeviation="100 0"/>
</filter>
<!-- σX=100, σY=0: horizontal smear; each glyph column averaged into full-width gray band; unreadable -->

SA-CSS-GSD-003: stdDeviation=0.1 incremental baseline

A near-zero initial stdDeviation="0.1" applies a visually imperceptible blur (sub-pixel radius). This establishes the feGaussianBlur element in the filter chain and avoids "attribute absent" detection. JS then increments stdDeviation from 0.1 toward 100 on each interaction event: hover, focus, keydown, mouseenter. Each increment is small enough to be ambiguous — the transition from 0.1 to 2 is visually slight, from 2 to 10 produces moderate softening, and from 10 to 100 completes the blur-to-white effect. Scanners observing the static initial state see stdDeviation=0.1 and may skip or rate as low severity; the runtime blur progression is only detectable via dynamic analysis.

const fb = document.querySelector("#consentFilter feGaussianBlur");
let sigma = 0.1;
consentEl.addEventListener("mouseover", () => {
  sigma = Math.min(sigma * 5, 100);
  fb.setAttribute("stdDeviation", sigma); // incremental blur on hover
});

SA-CSS-GSD-004: JS mousedown stdDeviation injection (0 → 100)

Initially, the feGaussianBlur uses stdDeviation="0" — an identity transform that renders the consent text fully sharp. On mousedown, the script changes stdDeviation to "100", instantly blurring the text to near-white. The user sees sharp readable consent text until the click begins, at which point the text blurs to illegibility. The click event itself fires on the underlying element (consent text is still the event target due to DOM presence), and the user believes they clicked on visible consent text while the text was actually being obscured at click time.

consentEl.addEventListener("mousedown", () => {
  document.querySelector("#consentFilter feGaussianBlur")
    .setAttribute("stdDeviation", "100"); // blur-to-white at mousedown
});

Attack summary

IDstdDeviation valueMechanismOutput contrastSeverity
SA-CSS-GSD-001100 (isotropic)Luminance averaging over large radius< 1.1:1 (near-white)Critical
SA-CSS-GSD-002"100 0" (anisotropic)Horizontal smear; glyph shapes destroyed~1.2:1 (grey bands)High
SA-CSS-GSD-0030.1 → 100 (incremental)Runtime sigma increase; static baseline passes0→1.1:1 over timeHigh
SA-CSS-GSD-0040 → 100 (mousedown)Click-time stdDeviation injectionSharp→near-white at clickCritical

Defences

SkillAudit findings for this attack surface

CRITICAL SA-CSS-GSD-001: feGaussianBlur stdDeviation="100" — isotropic sigma=100; Gaussian kernel radius ~300px; dark text pixels (luminance≈0.05) averaged with large white neighborhood; output luminance at glyph positions ≈ 0.99 (near-white); contrast ratio < 1.1:1; DOM element present, textContent intact, BCR unchanged.
HIGH SA-CSS-GSD-002: feGaussianBlur stdDeviation="100 0" — anisotropic blur σX=100/σY=0; horizontal smear of glyph columns into full-width grey bands; vertical glyph shapes destroyed; output not near-transparent (contrast ≈1.2:1) but fully unreadable; evades alpha=0 and near-transparent detectors.
HIGH SA-CSS-GSD-003: feGaussianBlur stdDeviation="0.1" with JS increment — near-imperceptible initial state; runtime sigma increases to 100 on user interaction; static scan sees stdDeviation=0.1; only dynamic analysis detects full attack progression; incremental sigma changes each individually below typical event threshold.
CRITICAL SA-CSS-GSD-004: JS mousedown sets feGaussianBlur stdDeviation from "0" to "100" — consent text sharp until click begins; blur-to-white at mousedown; user perceives click on visible text; MutationObserver on stdDeviation attribute of feGaussianBlur elements in consent ancestor filters required.

Related: feGaussianBlur general consent attacks  |  feColorMatrix luminanceToAlpha attacks  |  Filter region x/y/width/height attacks  |  feConvolveMatrix bias attacks

← Blog  |  Security Checklist