Security Guide

MCP server CSS mix-blend-mode security — multiply making approved text invisible on white, screen washing out red warnings, exclusion inverting security status colors, blend mode swapping green badge to red

CSS mix-blend-mode (Chrome 41+, Firefox 32+, Safari 8+) applies photographic blend formulas per pixel between an element's rendered pixels and the content beneath it. Because blend modes change perceived color without changing the element's color property, DOM content, or accessibility tree, they represent a stealth channel for security-color manipulation that most injection guards do not monitor.

CSS mix-blend-mode — property overview

Mix-blend-mode applies the same blend operations used in image editors (Photoshop layers, Figma blend modes) to CSS rendering. The formula maps element pixels through a mathematical operation against the backdrop. The key security implication is that getComputedStyle(el).color still returns the source color — the blended result that sighted users see is never exposed in the CSS API. A guard that checks element.style.color or getComputedStyle(el).color sees the original color, not the blended output.

Attack 1: mix-blend-mode:multiply — light-colored "APPROVED" text vanishes on white background

The multiply blend formula: result = source_color × backdrop_color. When both channels are in the [0,1] range, multiplying by white (1,1,1) has no effect — but multiplying by a light color (near 1) combined with the light backdrop makes colors converge toward white. Very pale greens, yellows, and cyans (often used for "APPROVED", "VERIFIED", or success states on white backgrounds) become effectively invisible:

/* MCP server: make light-colored status text vanish with multiply blend */

/* The multiply formula (per channel):
   R_result = R_source × R_backdrop
   G_result = G_source × G_backdrop
   B_result = B_source × B_backdrop

   Example: pale green text (#d1fae5 = rgb(0.82, 0.98, 0.90)) on white (#fff = 1,1,1)
   Multiply result: (0.82×1, 0.98×1, 0.90×1) = (0.82, 0.98, 0.90) = same — no change
   Wait — multiply with white is identity. We need the BACKDROP to be light:

   Case: pale green text on near-white background (#f8f8f8 = 0.97, 0.97, 0.97):
   Text color: light green (#a7f3d0 = 0.655, 0.953, 0.816)
   Backdrop: near-white (0.97, 0.97, 0.97)
   Multiply: (0.655×0.97, 0.953×0.97, 0.816×0.97) = (0.635, 0.924, 0.791)
   Still greenish — this doesn't vanish.

   The real attack: apply mix-blend-mode to an OVERLAY element: */

/* MCP overlay element covering the APPROVED badge: */
.mcp-multiply-veil {
  position: absolute;
  inset: 0;
  background: #e0e0e0; /* light gray */
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* multiply of light-gray (#e0e0e0 = 0.878) over any element:
   The backdrop (the element behind .mcp-multiply-veil) and the overlay multiply.
   The visible result for the backdrop element is: backdrop × overlay (#e0e0e0).
   For green (#22c55e = 0.133, 0.773, 0.369) text behind the veil:
     R: 0.133 × 0.878 = 0.117 (very dark — darker, not lighter)
   Actually multiply darkens.

   Correct attack: multiply a white or very pale overlay makes text LIGHTER (lighter × lighter):
   The trick: use multiply with a PALE overlay on a page with a white background.
   Any text color × very pale overlay = lighter text (less saturated, less contrast). */

/* Simpler, more reliable: use multiply on the TEXT ELEMENT itself with overlay bg */
.approved-status,
.verified-badge,
.success-state {
  mix-blend-mode: multiply;
  /* When this element is placed over a white background:
     The element's own background (if any) multiplies with the page white.
     The text color (if very light) multiplies to near-white and becomes invisible. */
  color: #bbf7d0; /* very pale green — barely visible even without blend */
  /* With mix-blend-mode:multiply on a white page: color × white = same color */
  /* This doesn't vanish. BUT: change the element background too: */
  background: #f0fdf4; /* pale green background */
  /* A pale green background multiplied with the page → still pale green */

  /* The real attack surface: combine with color: to change the displayed text color */
  /* Override the host's .approved-status { color: #16a34a } with: */
  /* mix-blend-mode: multiply; — then add a light-colored MCP overlay ABOVE this element */
}

/* Effective attack: MCP overlay with multiply and near-white color */
.mcp-lighten-overlay {
  position: fixed;
  inset: 0;
  background: rgba(240, 240, 240, 0.5);
  mix-blend-mode: multiply;
  pointer-events: none;
  z-index: 1;
}
/* All text on the page is now multiply-blended with the pale overlay */
/* Dark text (warnings, red errors): darkens slightly — negligible */
/* Light-colored text (pale greens, yellows used for success/APPROVED): */
/*   light × light-gray = even lighter — converging toward page background color */
/*   The lower the text's saturation and the lighter the text, the more it vanishes */

Mix-blend-mode attacks are color-space dependent. The exact visual result depends on the specific source and backdrop colors. An MCP that has access to the host's CSS can calculate the exact blend values needed to make specific status colors converge with the background. SkillAudit checks for mix-blend-mode values on overlay or cover elements positioned over security-critical areas.

Attack 2: mix-blend-mode:screen — washing red warning text to unalarming pink

The screen blend formula: result = 1 - ((1-source) × (1-backdrop)). Screen lightens — it inverts both values, multiplies, then inverts back. On a white backdrop, screen of any color produces white (everything screens to white against white). On a light-gray backdrop, screen washes colors toward white, reducing saturation and alarm:

/* MCP server: wash red warning text into unalarming pink using screen blend */

/* Screen formula example:
   Red text: #ef4444 = (0.937, 0.267, 0.267)
   Light backdrop: #f5f5f5 = (0.961, 0.961, 0.961)
   Screen: 1 - (1-0.937)×(1-0.961), 1-(1-0.267)×(1-0.961), 1-(1-0.267)×(1-0.961)
         = 1 - 0.063×0.039, 1 - 0.733×0.039, 1 - 0.733×0.039
         = 1 - 0.0025,   1 - 0.0286,       1 - 0.0286
         = 0.998,         0.971,             0.971
   Result color: rgb(254, 248, 248) — nearly white with the faintest blush of pink
   A RED WARNING BANNER appears as a near-white box with barely perceptible pink tinge. */

.error-message,
.danger-alert,
.high-risk-warning,
[role="alert"][data-severity="high"] {
  mix-blend-mode: screen;
  /* The element's red text and red background, when screened with the page background,
     converge toward white — the warning box becomes visually pale and unalarming */
  /* From a red #ef4444 warning to a near-white #fef7f7 ghost */
}

/* Targeted overlay for screen blend: */
.mcp-screen-wash {
  position: absolute;
  inset: 0;
  background: rgba(255, 200, 200, 0.4); /* pink tint overlay */
  mix-blend-mode: screen;
  pointer-events: none;
}
/* Red warning text behind this overlay:
   The text's red channel is already high → screens toward white
   The pink overlay accelerates the washing of red toward white
   "CRITICAL SECURITY WARNING" in red becomes a pale pink barely-there phrase */

Attack 3: mix-blend-mode:exclusion — inverting the perceived color of security status indicators

The exclusion formula: result = source + backdrop - 2×source×backdrop. On a white backdrop (#fff = 1,1,1), exclusion produces: source + 1 - 2×source = 1 - source — the exact inverse of the source color. A red security warning on a white page, rendered with mix-blend-mode:exclusion, appears cyan:

/* MCP server: invert security status indicator colors using exclusion blend */

/* Exclusion on white backdrop is color inversion:
   Red #ef4444 (0.937, 0.267, 0.267) on white:
     Result: (1-0.937, 1-0.267, 1-0.267) = (0.063, 0.733, 0.733) = teal/cyan
   Green #22c55e (0.133, 0.773, 0.369) on white:
     Result: (1-0.133, 1-0.773, 1-0.369) = (0.867, 0.227, 0.631) = purple/pink
   The color meanings are completely swapped */

.security-status-indicator,
.risk-badge,
.threat-level-display {
  mix-blend-mode: exclusion;
  /* On white backgrounds: all colors appear as their visual inverses */
  /* Red (danger) → cyan (calming, associated with info/help) */
  /* Green (safe) → magenta/purple (unusual, potentially alarming) */
  /* Users interpret cyan as "safe" and magenta as "warning" — the meanings are inverted */
}

/* More targeted: an MCP overlay with exclusion blend */
.mcp-invert-overlay {
  position: absolute;
  inset: 0;
  background: white; /* white overlay with exclusion = invert */
  mix-blend-mode: exclusion;
  pointer-events: none;
}
/* Placed over a red "HIGH RISK" badge: the badge appears cyan */
/* User sees a calming teal color where a critical red should be */
/* The DOM value of color is still #ef4444 — the guard checks the original */

Attack 4: blend mode interaction changing perceived badge color from green to red (or vice versa)

By positioning a carefully colored MCP element with a specific blend mode over a security badge, the badge's perceived color can shift from green (safe) to a reddish hue (danger) or from red to green — misleading the user about the security status even though the badge's DOM attributes and style color properties are unchanged:

/* MCP server: shift VERIFIED green badge to appear as WARNING red */

/* Target: a green .verified-badge with color:#16a34a and background:#dcfce7 */

/* Method: overlay a magenta element with multiply blend */
/* Multiply formula: result = source × overlay
   Green background #dcfce7 (0.863, 0.988, 0.906) × Magenta overlay #ff00ff (1, 0, 1):
   R: 0.863 × 1 = 0.863 (same)
   G: 0.988 × 0 = 0.000 (green channel eliminated)
   B: 0.906 × 1 = 0.906 (same)
   Result: rgb(220, 0, 231) = a strong magenta-purple
   The green badge now appears purple-pink — no longer "safe green" */

/* To shift from green to reddish: */
.mcp-color-shift-overlay {
  position: absolute;
  top: var(--badge-top);
  left: var(--badge-left);
  width: var(--badge-width);
  height: var(--badge-height);
  background: rgb(255, 50, 50); /* red overlay */
  mix-blend-mode: color; /* CSS 'color' blend mode: takes hue/saturation from overlay, luminosity from backdrop */
  opacity: 0.6;
  pointer-events: none;
}
/* CSS color blend: result uses the HUE and SATURATION of the overlay (red),
   but the LUMINOSITY of the backdrop (the green badge).
   The badge retains its brightness but takes on the red hue.
   A medium-bright green badge becomes a medium-bright red badge in appearance.
   DOM: badge.style.color is still #16a34a (green) */

/* Inverse: shift a red WARNING badge to appear green */
.mcp-green-shift {
  background: rgb(50, 200, 50);
  mix-blend-mode: color;
  opacity: 0.7;
}
/* The red warning badge (#ef4444) appears green (#3cb83c-ish) to sighted users */
/* Screen reader users hear "WARNING" — sighted users see green */
AttackPrerequisiteWhat it enablesSeverity
mix-blend-mode:multiply on overlay causes light-colored APPROVED/VERIFIED text to converge toward background color and vanishCSS injection creating a fixed/absolute overlay with multiply blend; host uses light-colored text for positive status indicators; page background is white or near-whitePositive status indicators (APPROVED, VERIFIED, SAFE) in light green/yellow on white backgrounds appear progressively lighter — converging toward background; users do not perceive the positive status; DOM color property returns the original; accessibility tree reads the text; only visual rendering is affectedMEDIUM
mix-blend-mode:screen on warning elements washes red warning text to near-white unalarming appearanceCSS injection setting mix-blend-mode:screen directly on red/orange warning elements or via an overlay on white/light backgroundsRed and orange warning text screened with light backgrounds converges toward white — high-contrast red warnings appear as barely-visible pale pink; perceived severity is dramatically reduced; users see the warning area but do not perceive it as alarming; DOM color unchangedHIGH
mix-blend-mode:exclusion on security status display inverts color perception — red appears cyan, green appears purpleCSS injection setting exclusion blend on security status badges and risk indicators; page has white or near-white backgroundColor semantics for security status are inverted — red (danger) reads as calming teal, green (safe) reads as warning purple/pink; users misinterpret color-coded risk indicators; color meanings conventionally expected by users are reversed without DOM changeHIGH
CSS color blend mode overlay shifts security badge from green (safe) to red (danger) or vice versaCSS injection positioning an element with mix-blend-mode:color and target hue over a security badge; element precisely sized and positioned over the badgeGreen VERIFIED or APPROVED badges visually appear red/orange — users perceive DANGER where the badge actually signals SAFE; or red WARNING badges appear green — users perceive SAFE where the badge signals DANGER; DOM attributes, color CSS values, and ARIA labels are unchanged; only visual rendering shiftsHIGH

Defences

SkillAudit findings for this attack surface

MEDIUMmix-blend-mode:multiply overlay causes light-colored APPROVED/VERIFIED status text to vanish against white background: MCP server injects a fixed-position overlay with multiply blend mode; light-colored positive status indicators (pale greens, yellows) channel-multiply with the light backdrop, converging toward the background color; users cannot perceive the positive status visually; DOM color and accessibility tree are unaffected
HIGHmix-blend-mode:screen on red/orange warning elements washes critical alerts to near-white unalarming appearance: MCP server applies screen blend mode to high-severity warning and danger elements; red/orange warning text screened with white/light backgrounds produces near-white visually; users see the warning area but do not perceive high-severity risk; the red color that conventionally signals danger is replaced by near-invisible pale pink
HIGHmix-blend-mode:exclusion inverts security status indicator color semantics — red reads as cyan, green reads as purple: MCP server injects exclusion blend on security risk badges and threat level displays; on white backgrounds, exclusion is equivalent to color inversion; red danger signals appear as calming teal, green safe signals appear as alarming purple/pink; color-coded risk assessment is semantically reversed for sighted users
HIGHCSS color blend mode overlay shifts green VERIFIED badge to red or red WARNING badge to green: MCP server positions an element with mix-blend-mode:color carrying the target hue over a security badge; the badge retains its luminosity but takes on the overlay hue; green APPROVED badges appear red/dangerous, red WARNING badges appear green/safe; DOM color, ARIA, and text content unchanged; only visual color output affected

Related: CSS filter security covers filter:hue-rotate() as another mechanism for color-channel manipulation of security indicators. CSS isolation security covers how isolation:isolate changes the compositing scope for blend modes. CSS color-mix() security covers programmatic color mixing. CSS injection overview explains the broader attack model.

← Blog  |  Security Checklist