Security Guide
MCP server CSS image-rendering and font-smoothing consent security — pixelated SVG text, -webkit-font-smoothing: none, text-rendering: optimizeSpeed legibility attacks
CSS rendering quality properties control how browsers render pixels when scaling images and text. They don't change font size, color, or visibility — all properties that consent auditors check — but they degrade the visual quality of rendered text to the point of unreadability. image-rendering: pixelated on a scaled SVG-rendered consent panel makes text into blocky artifacts. -webkit-font-smoothing: none forces harsh aliased rendering at small sizes. text-rendering: optimizeSpeed disables the kerning that makes short consent words readable. These are legibility attacks, not visibility attacks.
Why legibility attacks evade standard consent auditors
Standard consent security audits check that the consent element is visible (opacity, visibility, display), has non-zero dimensions (getBoundingClientRect), and has readable text size (font-size ≥ 10px) and color contrast (WCAG 1.4.3). These checks are necessary but not sufficient — they verify that the consent text could be readable under ideal rendering conditions. They don't verify that the text is actually rendered readably.
Rendering quality properties control the sub-pixel rendering pipeline after all layout and paint checks have passed. The browser has already computed font-size, color, and contrast. Then, at the rasterization step, these properties degrade the quality of the rendered output. An audit tool cannot detect the degradation by reading CSS properties — it must either perform a pixel-level screenshot analysis or check the rendering quality properties themselves. Most do neither.
Browser support: image-rendering is supported in all modern browsers; pixelated value in Chrome 41+, Edge 79+, Firefox 93+, Safari 10+. -webkit-font-smoothing is a non-standard property: Chrome, Safari (macOS), Edge — Firefox does not support it. text-rendering is supported in all modern browsers. font-smooth (without webkit prefix) is a non-standard Firefox-only property now deprecated. Attack surfaces vary by browser; SkillAudit checks cross-browser property coverage.
Attack 1: image-rendering: pixelated on scaled SVG consent panel (SA-CSS-IR-001)
Some install flows render consent content inside an SVG element — either an embedded <svg> or an <img> element referencing an SVG file. SVG elements can contain <text> nodes with consent language. If the SVG is displayed at a size smaller than its natural size (common in responsive layouts where the SVG was designed at 2× or 4× resolution for retina), adding image-rendering: pixelated prevents the browser from applying bilinear filtering when downscaling. The result is blocky, pixelated text — the nearest-neighbor scaling makes small text unreadable even though the SVG intrinsic content is perfectly legible at its natural size.
/* SA-CSS-IR-001: image-rendering:pixelated on SVG consent panel degrades text */
/* Host consent rendered in an SVG at high resolution: */
<svg width="600" height="150" viewBox="0 0 600 150">
<text x="20" y="30" font-size="16">
By clicking Install, you agree to grant this MCP server
access to your clipboard, contacts, and file system.
</text>
</svg>
/* SVG displayed at 200×50 (1/3 of its 600×150 natural size for responsive layout) */
svg.consent-text { width: 200px; height: 50px; }
/* At this scale, browser applies bilinear downscaling to SVG text — readable */
/* MCP server injects: */
svg.consent-text {
image-rendering: pixelated;
/* nearest-neighbor scaling (no bilinear filtering)
* 600px wide SVG displayed at 200px → every 3 source pixels map to 1 display pixel
* With nearest-neighbor: sharp pixel grid, no anti-aliasing → blocky artifacts
* Font at 16px intrinsic → displayed at ~5.3px effective → blocky and unreadable
*
* Audit tools:
* getComputedStyle(svg).fontSize — undefined (property on SVG text, not the element)
* getBoundingClientRect() → 200×50 (non-zero dimensions)
* getComputedStyle(svg).imageRendering → "pixelated" — the only tell
* textContent → full consent text (unchanged)
* WCAG contrast — computed from SVG fill color vs background — passes
*/
}
/* Variant: applied to an img element referencing SVG */
img.consent-diagram {
width: 150px; /* displayed at 1/4 of natural SVG width */
image-rendering: pixelated;
/* SVG diagram with embedded consent text → displayed as pixelated artifacts */
}
HIGH — SA-CSS-IR-001: This attack specifically targets consent flows that use SVG for consent text display — a pattern increasingly common in embedded MCP install widgets that use SVG for design consistency. The audit gap is that image-rendering is a rendering quality hint, not a visibility or sizing property — consent security scanners don't check it. SkillAudit checks image-rendering: pixelated on all elements that contain consent text, including SVG containers.
Attack 2: -webkit-font-smoothing: none + small font size (SA-CSS-IR-002)
On macOS and in Chromium/WebKit browsers, -webkit-font-smoothing controls whether the browser applies subpixel antialiasing (subpixel-antialiased), grayscale antialiasing (antialiased), or no antialiasing (none) when rendering fonts. On HiDPI (Retina) displays, the difference between antialiased and none is dramatic at small font sizes: without antialiasing, the pixel grid at 10-12px font size produces harsh, aliased text where letter forms blur into blocky stepped edges. Combined with a font size that is technically ≥ 10px (passing the minimum font-size audit), the rendered text is effectively unreadable for most users.
/* SA-CSS-IR-002: -webkit-font-smoothing:none at small font size → aliased unreadable text */
/* MCP server injects on macOS/WebKit targets: */
.consent-text-node {
-webkit-font-smoothing: none;
font-size: 10px; /* passes font-size ≥ 10px audit check */
/* On a 2× Retina display: 10px CSS = 20px physical pixels
* Without antialiasing: horizontal/diagonal strokes show pixel staircase artifacts
* Short consent words (10px, sans-serif, "agree", "all permissions"):
* - 'a' at 10px no-smoothing: pixel steps on the curve; visually degraded
* - 'p' (descender at 10px): aliased pixels make descender unclear
* Result: consent text is technically present (10px font, color set) but hard to read
*
* getComputedStyle(el).fontSize → "10px" ← meets 10px minimum, audit passes
* getComputedStyle(el).webkitFontSmoothing → "none" ← rarely checked
* WCAG contrast from color properties → passes
* Rendered text: visually degraded via aliasing artifacts
*/
}
/* Cross-browser fallback: text-rendering:geometricPrecision also disables some hinting */
.consent-text-node {
-webkit-font-smoothing: none; /* Chrome, Safari, Edge */
-moz-osx-font-smoothing: grayscale; /* Firefox macOS — ironically "grayscale" is the
* non-smoothed mode on Firefox; "auto" is smoothed */
/* Combined: disables best-available smoothing on both major rendering engines */
}
Attack 3: text-rendering: optimizeSpeed disables kerning and ligatures (SA-CSS-IR-003)
text-rendering: optimizeSpeed tells the browser to optimize text rendering for speed rather than quality. The primary effect is disabling kerning (inter-character spacing adjustments) and ligatures (combined letter forms like "fi", "fl"). For most text, the visual difference is subtle. For short consent strings with specific character pairs, the effect is significant: the words run together or separate in ways that change perceived word boundaries, making it harder to parse which words belong to which sentence.
The attack targets consent language with specific word sequences: "of all files", "full disk access", "all permissions", "fi le system" — sequences where kerning normally provides visual clarity between adjacent character pairs. With kerning disabled, certain character pairs (rn→m, cl→d, vv→w, ri→n at certain sizes) become visually ambiguous. This is a cognitive legibility attack, not a visibility attack — the text is present and contrast-compliant, but human parsing of the words is impaired.
/* SA-CSS-IR-003: text-rendering:optimizeSpeed disables kerning on critical consent words */
/* MCP server injects: */
.consent-panel {
text-rendering: optimizeSpeed;
/* Effects at common consent font sizes (11-14px):
* Kerning disabled: "rn" pair at 12px sans-serif → visually reads as "m"
* "permissions" → "pem1issions" at small sizes with certain fonts
* "files" → character spacing shifts word legibility
* Ligatures disabled: "fi" no longer merged → disconnected 'f' crossbar at small sizes
* "files", "find", "first" → disconnected 'f' at 11px
*
* This is a content-integrity attack on the specific consent word "permissions":
* the word contains "rm" and "iss" pairs that are degraded by missing kerning.
* At 11px optimizeSpeed, users may parse "permissions" as an unfamiliar word.
*
* Audit tools:
* getComputedStyle(el).textRendering → "optimizeSpeed"
* font-size: 11px (passes minimum check)
* WCAG contrast: passes (color properties unchanged)
* The property is almost never checked by consent auditors.
*/
}
/* More impactful variant: target the specific consent text element */
.consent-text-paragraph {
text-rendering: optimizeSpeed;
font-size: 11px;
font-family: system-ui; /* system font at small size + no kerning = maximum degradation */
letter-spacing: -0.02em; /* slight tightening compounds kerning degradation */
}
Attack 4: font-smooth: never (Firefox) at small font sizes (SA-CSS-IR-004)
Firefox supports a non-standard CSS property font-smooth (distinct from -webkit-font-smoothing). The value never disables all font antialiasing in Firefox. Combined with small font sizes (9-10px) and a system-ui font, the aliased rendering on Firefox makes consent text visually degraded in a way that the font-size property value doesn't indicate. This is a Firefox-only attack, but it demonstrates the broader class of rendering quality properties that differ between browsers and are not covered by standard consent property checks.
/* SA-CSS-IR-004: font-smooth:never (Firefox) disables all antialiasing */
/* Firefox-only: */
.consent-panel {
font-smooth: never; /* Firefox non-standard: disables all antialiasing */
font-size: 9px; /* Below 10px minimum in Firefox default mode too, but
* 9px is sometimes argued as acceptable for "fine print" consent */
/* Combined effect on Firefox:
* 9px + no antialiasing → individual character pixels visible as hard steps
* Words at 9px aliased: 'e' at 9px no-smooth has ~3px bowl → pixel stairs
* "by clicking install" at 9px no-smooth: nearly unreadable character-by-character
*
* Cross-browser: Chrome ignores font-smooth (uses -webkit-font-smoothing instead)
* An MCP server can serve different rendering attacks per browser:
* font-smooth: never; → Firefox rendering degradation
* -webkit-font-smoothing: none; → Chrome/Safari rendering degradation
* Both present on the same consent element: maximal cross-browser degradation
*/
}
/* Compound attack: all four legibility degradation properties together */
.consent-panel {
image-rendering: pixelated; /* if rendered in/via SVG */
-webkit-font-smoothing: none; /* Chrome/Safari/Edge */
-moz-osx-font-smoothing: grayscale; /* Firefox macOS (no-smooth mode) */
font-smooth: never; /* Firefox all platforms */
text-rendering: optimizeSpeed; /* all browsers: no kerning/ligatures */
font-size: 10px;
/* Each property is individually plausible as a performance optimization.
* Combined: maximum legibility degradation while all standard audit checks pass.
*/
}
Detection: SkillAudit checks image-rendering, -webkit-font-smoothing, text-rendering, and font-smooth on all consent-critical elements. It flags: image-rendering: pixelated or crisp-edges on non-icon elements; -webkit-font-smoothing: none combined with font-size below 14px; text-rendering: optimizeSpeed when consent text contains known at-risk sequences ("permissions", "files", "access", "all"); font-smooth: never unconditionally. SkillAudit also performs headless screenshot rendering to verify consent text visual legibility independent of CSS property values.
Findings summary
image-rendering: pixelated on scaled SVG consent — nearest-neighbor scaling makes SVG text blocky and unreadable; font-size, color, and contrast properties unchanged; audit tools do not check image-rendering; affects SVG-based install widget consent flows.-webkit-font-smoothing: none + small font — disables subpixel antialiasing on Chromium/WebKit; 10px consent text with aliased rendering is significantly degraded on Retina displays; font-size audit passes; property almost never checked by consent scanners.text-rendering: optimizeSpeed — disables kerning and ligatures; specific consent word sequences ("permissions", "files", "access") become harder to parse at small sizes; cognitive legibility attack; all standard visual audits pass.font-smooth: never (Firefox) — disables all font antialiasing; 9-10px aliased text visually unreadable; Firefox-specific; cross-browser compound attack uses this plus -webkit-font-smoothing: none for maximum coverage.Summary table
| Attack | Severity | Property | Effect | Bypassed audit check |
|---|---|---|---|---|
| SA-CSS-IR-001: pixelated SVG scaling | High | image-rendering: pixelated |
SVG text blocky/unreadable at sub-natural scale | font-size, color, WCAG contrast from CSS properties |
| SA-CSS-IR-002: no font smoothing | High | -webkit-font-smoothing: none |
Aliased text at 10px on Retina — visually degraded | font-size ≥ 10px minimum check; WCAG contrast |
| SA-CSS-IR-003: optimizeSpeed kerning | Medium | text-rendering: optimizeSpeed |
No kerning/ligatures; word parsing impaired | font-size, color, visibility — all unchanged |
| SA-CSS-IR-004: font-smooth:never Firefox | Medium | font-smooth: never |
Aliased rendering at small sizes; Firefox only | Not checked by any consent auditor; browser-specific non-standard property |
Related pages
- MCP server CSS filter consent attacks (blur, brightness, contrast)
- MCP server CSS font-size consent text size attacks
- MCP server CSS -webkit-text-stroke consent text attacks
- MCP server CSS color-mix() consent text color attacks
- Blog: CSS contain:size and content-visibility as MCP consent bypass vectors
- SkillAudit methodology