Security Guide

MCP server CSS image-rendering security — avatar identity degradation, QR code readability attacks, performance DoS, SVG icon recognition failures

The CSS image-rendering property controls how the browser scales images when they are displayed at sizes other than their source dimensions. It is a rarely-audited property that an MCP server can exploit to degrade identity verification by pixelating avatar photos, deny users access to 2FA setup by breaking QR code readability, trigger GPU-intensive rendering on mobile devices, and make security icons unrecognizable at their typical display sizes.

The image-rendering property — algorithm model

The image-rendering property specifies which pixel interpolation algorithm the browser uses when upscaling or downscaling an image to fit its display dimensions. The key values are: auto (browser default, typically bilinear/bicubic for smooth upscaling), pixelated (nearest-neighbor — copies the nearest source pixel without blending, producing hard pixel edges and a blocky appearance at large scales), crisp-edges (browser-specific rounding algorithm intended for pixel art and diagrams — preserves sharp edges but does not guarantee nearest-neighbor at all scales), and high-quality (Chrome 110+, requests Lanczos or similar high-quality algorithm even at the cost of performance). The property applies to <img> elements, CSS background-image rendering, and border-image rendering.

Attack 1: image-rendering:pixelated on profile and avatar images

Profile photos and avatars are almost universally stored as thumbnails (64×64, 128×128 pixels) and displayed at 2× or 4× their stored dimensions by the application's layout. Under the default auto rendering, the browser applies bilinear or bicubic upscaling to produce a smooth (if slightly blurry) result. Under pixelated, nearest-neighbor scaling produces a blocky, heavily pixelated image at those scales. In team collaboration tools, support platforms, and social-feature-rich applications, users rely on avatar photos for identity recognition — identifying colleagues, customers, or message senders by their profile photo. Pixelated avatars impair this recognition:

/* MCP server: degrade avatar image quality across the application */

/* Common avatar selector patterns in web frameworks: */
img[class*="avatar"],
img[class*="profile-pic"],
img[class*="user-photo"],
img[alt*="avatar"],
.avatar > img,
.profile-image img,
[data-testid*="avatar"] img,
[data-component="avatar"] img {
  image-rendering: pixelated !important;
  /* Effect at typical avatar display sizes:
     64×64px source displayed at 128×128px → 2× nearest-neighbor
     Each source pixel is rendered as a 2×2 block of identical pixels.
     Facial features lose definition. Two similar-looking people become
     indistinguishable. The "recognise your colleague by their avatar"
     defence against impersonation attacks is undermined. */
}

/* More targeted: apply only during a specific interaction
   (e.g. when user is selecting a recipient for a file share): */
.recipient-search img,
.transfer-target img,
.permission-grant-dialog img {
  image-rendering: pixelated !important;
  /* Precisely targets the moments where identity verification matters most:
     when the user is choosing who to share data with, grant access to,
     or send a payment to. */
}

/* The attack is a social-engineering enabler:
   An attacker who has substituted their own avatar for a target's
   avatar (through another attack vector) is harder to detect
   when all avatars are pixelated. The pixelation also increases
   the probability that a user accepts a lookalike avatar as genuine. */

Identity verification surface: This attack does not steal data or escalate privileges directly. Its impact is as a social engineering enabler — it degrades the visual identity layer that users rely on to distinguish between people in a multi-user application. When combined with an avatar substitution or display name spoofing attack, pixelated avatars remove the last visual check users have.

Attack 2: image-rendering:crisp-edges on 2FA QR code images

Two-factor authentication enrollment typically displays a TOTP QR code that encodes the account's TOTP seed, issuer, and username as a single-display URL. QR codes have strict module boundary requirements: each dark and light module (square cell) must have clean, unambiguous boundaries for QR readers to correctly decode the pattern. The crisp-edges value applies a browser-dependent pixel rounding algorithm that, at certain non-integer display scales, introduces single-pixel boundary artifacts that shift module edges:

/* MCP server: degrade 2FA QR code rendering with crisp-edges */

/* Target the QR code image on the 2FA enrollment page */
img[alt*="QR"],
img[alt*="two-factor"],
img[alt*="authenticator"],
img[src*="qr"],
img[src*="totp"],
canvas.qr-code,
.two-factor-setup img,
.mfa-enrollment img {
  image-rendering: crisp-edges !important;
  -ms-interpolation-mode: nearest-neighbor !important; /* IE fallback */

  /* The crisp-edges algorithm is browser-defined and not guaranteed
     to be nearest-neighbor. In Chrome it historically mapped to
     a pixel rounding mode that produced subpixel artifacts at
     non-integer scale factors (e.g. 200×200 source at 210×210 display).

     For high-density QR codes (TOTP URLs including long hostnames,
     or QR codes encoded at error correction level H with significant
     overhead), the module pixel width may be as small as 2-3 display pixels.
     A 1-pixel shift on a 2-pixel module is a 50% error on that module —
     which for high-density codes may exceed the error correction capacity.

     Result: the QR code image appears nearly identical to the user
     but fails to scan. The 2FA enrollment process fails.
     The user must contact support, potentially weakening their account
     security timeline or abandoning 2FA setup entirely. */
}

/* Also applicable to QR codes used for:
   - Passwordless login (passkey enrollment QR)
   - Security key registration
   - Device pairing flows
   - Payment QR codes (different attack surface — incorrect amount confirmation) */

Security setup denial-of-service: 2FA QR codes are typically displayed once per enrollment session. A QR scan failure does not always regenerate the code automatically — some implementations require the user to restart enrollment. An MCP server can use crisp-edges as a precision DoS on the security setup flow, leaving users without 2FA protection on their accounts while believing setup failed due to a device or browser issue.

Attack 3: image-rendering:high-quality — GPU upscaling DoS on mobile

The high-quality value (Chrome 110+, maps to the highest available upscaling algorithm, typically Lanczos-3 or a similar multi-tap filter) requests that the browser perform maximum quality interpolation at the expense of GPU resources. For individual large images, this is the default user expectation. But when applied globally to all images on a page that contains many small decorative images, the GPU cost multiplies across every image simultaneously, causing rendering jank on resource-constrained devices:

/* MCP server: force GPU-intensive upscaling on all page images */

/* Global injection — all images use high-quality upscaling */
img, image, [style*="background-image"] {
  image-rendering: high-quality !important;
}

/* Why this causes a DoS on mobile:
   A typical dashboard or feed page may contain:
   - 20-50 user avatars (32×32 displayed at 64×64 or 128×128)
   - 10-20 product/content thumbnails (128×128 displayed at 256×256)
   - 5-10 decorative images (PNG icons, illustrations)
   Total: 35-80 images requiring high-quality GPU upscaling simultaneously.

   Bilinear upscaling cost:     O(n) per pixel — fast, GPU-trivial
   Lanczos-3 upscaling cost:    O(n * tap_count²) per pixel — 36× more operations
                                 than bilinear for a 6×6 kernel

   On a midrange Android device (2021-era SoC, 3-4GB RAM):
   - 50 avatars × 64×64 = 204,800 pixels to upscale
   - Lanczos-3: 204,800 × 36 = 7.4M operations per render frame
   - At 60fps refresh: 445M GPU operations/second for avatars alone
   - Combined with other page GPU work → frame budget exceeded → jank

   Effect on security: the user's device becomes sluggish, making
   interactions slow and increasing the probability of misclicks —
   a useful precondition for a clickjacking or UI redress attack. */

/* More targeted: force high-quality on a specific long-scroll feed
   that the user is actively reading — causes jank exactly during
   the content consumption phase: */
.feed-item img,
.timeline-card img,
.chat-message img {
  image-rendering: high-quality !important;
}

Attack 4: image-rendering:pixelated on SVG icon images

Modern UI frameworks commonly serve icon systems as SVG files referenced via <img src="icon.svg"> elements or as inline SVG elements, scaled from a base design size (typically 24×24) to display sizes ranging from 12×12 to 20×20. When image-rendering: pixelated is applied to an <img> rendering an SVG, the browser rasterizes the SVG at its intrinsic dimensions and then applies nearest-neighbor pixel doubling or halving to reach the display dimensions — identical in behavior to rasterized PNG icons:

/* MCP server: degrade SVG icon rendering to break icon recognition */

/* Common SVG icon patterns: */
img[src$=".svg"],
img[src*="/icons/"],
img[src*="/assets/icons"],
img[class*="icon"],
[class*="icon-img"] {
  image-rendering: pixelated !important;
  /* SVG rasterized at natural dimensions (24×24),
     then nearest-neighbor scaled to display size.

     At 16×16 display (downscale from 24×24):
     - Pixelated downscale: each display pixel takes value from nearest
       source pixel in a 1.5×1.5 source-pixel window.
     - Thin strokes (1-2px in 24×24 source) become 0-1px at 16×16.
     - Icons with thin stroke designs (many Material, Feather, Phosphor icons)
       lose their lines entirely or render with irregular stroke weights.

     Security-critical icons affected:
     - Lock icon (🔒 substitute): thin shackle becomes invisible → locked/unlocked
       state is indistinguishable
     - Warning triangle (⚠ substitute): thin outline disappears
     - Close/X icon: thin diagonal lines become diagonal blocky artifacts
     - Settings gear: thin gear teeth vanish → gear looks like a circle
     - Verified checkmark: thin stroke check disappears */
}

/* The attack on security affordances:
   Icons serve as at-a-glance security indicators. When icons become
   unrecognizable pixel blobs:
   1. Lock icons lose lock/unlock distinction → HTTPS/HTTP visual indicator broken
   2. Warning icons lose their warning shape → security alerts not noticed
   3. Close icons on security dialogs become unrecognizable → users cannot dismiss
   4. The cognitive load of squinting to decipher icons reduces attention to
      the underlying security content (the warning text, the lock state, etc.) */

/* Inline SVG is NOT affected by image-rendering on img elements.
   For inline SVG icons, use shape-rendering instead: */
svg[class*="icon"],
.icon > svg,
button > svg {
  /* shape-rendering:crispEdges applies to SVG rendering, not image rendering */
  shape-rendering: crispEdges !important;
  /* At small display sizes, crispEdges rounds coordinates to integer pixels,
     which at 16×16 for a 24×24 designed icon causes similar stroke loss. */
}
AttackPrerequisiteWhat it enablesSeverity
pixelated on avatar/profile imagesCSS injection; avatars stored as thumbnails displayed at 2× or moreFace recognition for identity verification impaired; social engineering / impersonation attacks harder to detectMEDIUM
crisp-edges on 2FA QR code imagesCSS injection; 2FA enrollment page with non-integer-scaled QR imageHigh-density QR codes fail to scan; 2FA setup denied; users left without MFA protectionHIGH
high-quality forced on all page imagesCSS injection; page has many images; mobile or low-powered devicesGPU-intensive upscaling on 50+ images causes rendering jank and performance DoS on mobileMEDIUM
pixelated on SVG icon imagesCSS injection; app uses SVG icons via img elementsSecurity-critical icons (lock, warning, close) become unrecognizable at small display sizes; security affordances brokenMEDIUM

Defences

SkillAudit findings for this attack surface

MEDIUMAvatar identity degradation via image-rendering:pixelated: MCP server injects image-rendering:pixelated on avatar/profile image selectors; nearest-neighbor upscaling makes profile photos blocky and impairs face recognition for identity verification
HIGH2FA QR code scan denial via crisp-edges: MCP server injects image-rendering:crisp-edges on 2FA enrollment QR code images; browser pixel rounding introduces module boundary artifacts that make high-density TOTP QR codes unscannable
MEDIUMMobile GPU performance DoS via high-quality: MCP server injects image-rendering:high-quality globally, forcing Lanczos-class upscaling on all images simultaneously; causes rendering jank on mobile devices with 50+ images on the page
MEDIUMSecurity icon recognition failure via pixelated on SVG: MCP server injects image-rendering:pixelated on img elements rendering SVG icon files; lock, warning, and close icons become unrecognizable pixel blobs at typical small display sizes

Related: CSS masking security covers image masking attacks that clip or hide portions of security-critical images. CSS filter security documents brightness(0) and blur attacks that completely hide or degrade image rendering.

← Blog  |  Security Checklist