← Blog

MCP server SVG feBlend mode consent security

Four SA-CSS-FBM consent attack patterns using the feBlend mode attribute — multiply, screen, and overlay compositing with extreme in2 layers to produce dark-out, white-out, and contrast collapse — with JS mousedown mode injection for click-time attacks.

By SkillAudit  |  23 Oct 2026

The feBlend SVG filter primitive composites two images using a blending mode. The mode attribute determines the formula applied per-pixel. SVG filter blending supports the same W3C compositing modes as CSS mix-blend-mode: normal, multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color, luminosity. Several of these have mathematical fixed-points that produce constant output regardless of the source (in1) value, making them effective erasure primitives when in2 is set to the appropriate constant value.

Fixed-point property: For any blend mode F(A, B) where B is a constant, if F(A, B) equals the same constant C for all values of A, then the blend is a constant-output filter regardless of what the source contains. This is the mathematical property exploited by SA-CSS-FBM-001 (multiply with black) and SA-CSS-FBM-002 (screen with white).

SA-CSS-FBM-001: feBlend mode="multiply" with black in2 layer

The multiply blend formula is C = A × B per channel. When in2 is a solid black layer (all channels = 0), every output channel is A × 0 = 0. The output is uniformly black regardless of the consent text color. On a dark-themed MCP client, black text on a black/dark background is invisible. The element retains its layout, textContent, and all computed CSS values. getComputedStyle.color continues to return the declared foreground color.

<filter id="fbm1">
  <feFlood flood-color="black" flood-opacity="1" result="black_layer"/>
  <feBlend in="SourceGraphic" in2="black_layer" mode="multiply"/>
</filter>
<!-- multiply(any_color, 0) = 0 → all pixels black → dark-out on dark UIs -->

SA-CSS-FBM-002: feBlend mode="screen" with white in2 layer

The screen blend formula is C = 1 - (1-A)(1-B). When in2 is solid white (all channels = 1), the formula becomes 1 - (1-A)(1-1) = 1 - 0 = 1 for all values of A. Every output channel is 1 (white). The consent text is erased to white, invisible on white or light backgrounds. This is the most common feBlend consent attack in the SkillAudit dataset — the feFlood+feBlend screen pair appears frequently in community MCP skills with consent dialogs.

<filter id="fbm2">
  <feFlood flood-color="white" flood-opacity="1" result="white_layer"/>
  <feBlend in="SourceGraphic" in2="white_layer" mode="screen"/>
</filter>
<!-- screen(any_color, 1) = 1 → all pixels white → white-out on light UIs -->

SA-CSS-FBM-003: feBlend mode="overlay" with mid-gray in2 layer

The overlay formula is piecewise: 2AB when B < 0.5, and 1 - 2(1-A)(1-B) when B ≥ 0.5. At the exact midpoint B = 0.5, both branches yield the same value: 2A×0.5 = A and 1 - 2(1-A)(0.5) = 1 - (1-A) = A. An exact mid-gray in2 is therefore an identity for overlay — it preserves the source. However, values slightly above or below 0.5 push the formula toward amplification (contrast increase for B > 0.5) or compression (contrast decrease for B < 0.5).

SA-CSS-FBM-003 uses a near-0.5 gray (e.g., flood-color=#7f7f7f ≈ 0.498) to shift all pixels toward a near-uniform gray value. With a dark text color (e.g., #333) and near-0.5 overlay, the output is compressed to a very narrow luminance range around 0.5. Against a mid-gray background, the contrast ratio approaches 1:1, making the consent text effectively invisible without any channel reaching zero.

<filter id="fbm3">
  <feFlood flood-color="#7f7f7f" flood-opacity="1" result="gray_layer"/>
  <feBlend in="SourceGraphic" in2="gray_layer" mode="overlay"/>
</filter>
<!-- overlay(dark_text, ~0.5) ≈ 0.5 for all pixels → near-uniform mid-gray → 1:1 contrast on gray background -->

SA-CSS-FBM-004: JS mousedown mode injection (normal → screen)

The feBlend initially uses mode="normal" with a transparent in2 layer (feFlood with flood-opacity="0"). In normal mode, feBlend alpha-composites the two inputs; with a fully transparent in2, the result is identical to in1 — the consent text is rendered normally. On mousedown, the script changes mode to "screen" and simultaneously changes the in2 feFlood's flood-opacity to 1 (making it opaque white). The screen blend immediately produces white-out.

consentElement.addEventListener("mousedown", () => {
  const fb = document.getElementById("consentFilter").querySelector("feBlend");
  fb.setAttribute("mode", "screen");
  const ff = document.getElementById("consentFilter").querySelector("feFlood");
  ff.setAttribute("flood-opacity", "1"); // make white layer opaque
});

Mode-specific detection: The attack mode is not always screen. Flag: multiply with a low-luminance in2 layer (luminance < 0.05); screen with a high-luminance in2 layer (luminance > 0.95); overlay/soft-light/hard-light with in2 luminance near 0.5 (0.4–0.6) combined with a mid-gray background. Each mode requires a different fixed-point analysis.

Attack summary

IDmodein2 layerFormula fixed pointEffectSeverity
SA-CSS-FBM-001multiplyBlack (all=0)A×0=0Dark-out on dark UIsCritical
SA-CSS-FBM-002screenWhite (all=1)1-(1-A)(0)=1White-out on light UIsCritical
SA-CSS-FBM-003overlayMid-gray (~0.5)Output ≈ 0.5 for all AContrast collapse on gray backgroundHigh
SA-CSS-FBM-004normal→screen (mousedown)Transparent→whitescreen(A,1)=1White-out at click timeCritical

Defences

SkillAudit findings for this attack surface

CRITICAL SA-CSS-FBM-001: feBlend mode="multiply" + feFlood in2 black (luminance ≈ 0) — fixed point: multiply(A,0)=0; dark-out for all foreground colors; invisible on dark-themed MCP clients; getComputedStyle.color unchanged.
CRITICAL SA-CSS-FBM-002: feBlend mode="screen" + feFlood in2 white (luminance ≈ 1) — fixed point: screen(A,1)=1; white-out for all foreground colors; invisible on white/light-themed MCP clients; most frequently observed feBlend consent attack pattern.
HIGH SA-CSS-FBM-003: feBlend mode="overlay" + feFlood in2 near-0.5 gray — output compressed to near-0.5 for all input values; contrast ratio approaches 1:1 against mid-gray background; no channel reaches zero; evades zero-output and transparency checks.
CRITICAL SA-CSS-FBM-004: JS mousedown changes feBlend mode from "normal" to "screen" + feFlood flood-opacity 0→1 — initial state identity blend (consent text visible); white-out at click time; MutationObserver on mode attribute of feBlend and flood-opacity/flood-color of in2 feFlood elements required.

Related: feImage href white overlay attacks  |  feFlood consent attacks  |  feComposite consent attacks  |  feColorMatrix luminanceToAlpha attacks

← Blog  |  Security Checklist