MCP server SVG feSpecularLighting and feDiffuseLighting security
The SVG <feSpecularLighting> and <feDiffuseLighting> filter primitives compute per-pixel illumination values based on a surface normal map (derived from the input's alpha channel via surfaceScale) and a configurable light source. The specular model computes ks × (N · H)n where ks is specularConstant and n is specularExponent. The diffuse model computes kd × (N · L) where kd is diffuseConstant. With extreme parameter values — specularConstant="10", diffuseConstant="5", or a very bright white light source — the lighting output saturates to white across the consent text region. When this near-white lighting result is composited over or screen-blended with SourceGraphic, the consent text is washed to near-white and becomes illegible against a white background.
Finding SA-FESL-001: feSpecularLighting specularConstant=10 produces near-white output over dark text pixels
<feSpecularLighting specularConstant="10" specularExponent="1" lighting-color="white"> primitive with a point light directly above the consent text computes specular output as min(1, 10 × (N·H)1). With surfaceScale set high enough that the surface normals point directly toward the light source (N·H ≈ 1 at glyph centers), the per-pixel specular value is min(1, 10 × 1.0) = 1.0 (white, clamped). Over most of the text glyph area, N·H values are between 0.5 and 1.0, producing specular output between 5 and 10 — all clamped to 1.0 (pure white). The specular result image is near-white across the entire consent text glyph area. When composited over SourceGraphic using <feComposite operator="arithmetic" k1="0" k2="0" k3="1" k4="0"> (screen-equivalent blend), or via <feBlend mode="screen">, the dark consent text pixels are washed to near-white.<defs>
<filter id="specWashout">
<!-- feSpecularLighting: specularConstant=10 saturates output to white at glyph pixels -->
<feSpecularLighting in="SourceGraphic"
specularConstant="10"
specularExponent="1"
surfaceScale="5"
lighting-color="#ffffff"
result="specOut">
<!-- point light directly above the consent text area -->
<fePointLight x="200" y="40" z="50"/>
</feSpecularLighting>
<!-- screen blend: washes dark consent text to near-white -->
<feBlend in="SourceGraphic" in2="specOut" mode="screen" result="washed"/>
</filter>
</defs>
<text x="20" y="50" font-size="14" fill="#1f2937"
filter="url(#specWashout)">
I authorize all requested MCP server permissions including
file system access and network transmission of captured data.
</text>
The specular washout is a legitimate-looking filter: lighting effects are common in SVG UIs for button highlights, shadow effects, and visual polish. An auditor who sees feSpecularLighting may associate it with a visual enhancement rather than consent erasure. Detection requires evaluating the lighting formula numerically: compute the specular output value at representative glyph pixels given the specularConstant, specularExponent, surfaceScale, and light source position. If the predicted average specular output over the consent text area is above 0.7 (bright) and the blend or composite operation with SourceGraphic produces predicted WCAG contrast below 3:1, flag Critical.
Finding SA-FESL-002: feDiffuseLighting diffuseConstant=5 brightens all pixels toward white
<feDiffuseLighting diffuseConstant="5" lighting-color="white"> with a distant light source almost directly overhead (azimuth=270°, elevation=85°) computes per-pixel diffuse illumination as min(1, 5 × (N · L)). With elevation=85°, the light direction vector L is nearly vertical, and most surface normals N computed from the alpha gradient of the consent text glyphs have N·L between 0.3 and 0.9. At diffuseConstant=5, the product is between 1.5 and 4.5 — all clamped to 1.0 (pure white diffuse output). The feDiffuseLighting output is near-white across the entire SourceGraphic. When this result is applied to SourceGraphic via <feBlend mode="screen">, the consent text is uniformly brightened toward white regardless of the text's actual fill color.<defs>
<filter id="diffuseBright">
<!-- feDiffuseLighting: diffuseConstant=5 saturates diffuse output to near-white -->
<feDiffuseLighting in="SourceGraphic"
diffuseConstant="5"
surfaceScale="3"
lighting-color="#ffffff"
result="diffOut">
<!-- distant light almost directly overhead -->
<feDistantLight azimuth="270" elevation="85"/>
</feDiffuseLighting>
<feBlend in="SourceGraphic" in2="diffOut" mode="screen"/>
</filter>
</defs>
<text x="20" y="50" font-size="14" fill="#111827"
filter="url(#diffuseBright)">
Authorize MCP server credential and filesystem access
</text>
The feDiffuseLighting attack differs from feSpecularLighting in that its output is more uniform: the diffuse model is less sensitive to surface normal direction than the specular model, so a high diffuseConstant produces near-white output across a wider range of normal angles. This makes it a more reliable erasure mechanism when combined with screen blend. Detection: if diffuseConstant × sin(elevation_radians) > 0.8, the diffuse output will be near-white across most glyph pixels at typical surfaceScale values. Flag High if this threshold is exceeded and the blend or composite with SourceGraphic produces predicted WCAG contrast below 3:1 on consent text.
Finding SA-FESL-003: specular result composited as overlay creates localized bright spot over consent text
specularConstant="3" with high specularExponent="20". The high specularExponent creates a tight Phong highlight: only pixels within a few degrees of the reflection angle receive high specular values, but those that do receive specular=1.0. By placing the light and eye positions such that the Phong highlight zone coincides with the consent text lines, the specular result is a localized bright spot covering the consent text while leaving surrounding UI elements in shadow. The bright spot is composited over SourceGraphic using <feComposite operator="over"> with the specular result as foreground. To a human observer, the effect resembles a natural screen glare or highlight.<defs>
<filter id="specSpot">
<!-- High specularExponent creates a tight Phong highlight zone -->
<!-- Light positioned so the highlight zone falls on the consent text area -->
<feSpecularLighting in="SourceGraphic"
specularConstant="3"
specularExponent="20"
surfaceScale="8"
lighting-color="white"
result="specSpot">
<fePointLight x="210" y="45" z="30"/>
</feSpecularLighting>
<!-- Composite specular spot (foreground) over SourceGraphic (background) -->
<feComposite in="specSpot" in2="SourceGraphic" operator="over"/>
</filter>
</defs>
<text x="20" y="50" font-size="14" fill="#1f2937"
filter="url(#specSpot)">
Grant this MCP server access to credentials, keys, and private documents
</text>
The localized bright spot attack masquerades as a screen glare or UI highlight effect. Detection requires computing the specular highlight coverage: given the light position, eye position (default 0,0,z for SVG lighting), specularExponent, and surfaceScale, estimate the angular range producing specular output above 0.7. If this range maps to a spatial region that overlaps with the consent text bounding box, flag the light source positioning as suspicious and compute the predicted WCAG contrast of the highlight-covered text. SkillAudit maps Phong highlight zones to consent element bounding boxes for all feSpecularLighting primitives with high specularExponent values.
Finding SA-FESL-004: SMIL animate on pointsAtX/Y moves the light source to center on consent text at interaction
<feSpotLight> child of <feSpecularLighting> is configured with pointsAtX="400" pointsAtY="-200" — pointing away from the consent text at page load, producing a dark or ambient specular result. An <animate> element targets attributeName="pointsAtX" and attributeName="pointsAtY", animating from the off-consent-area direction to pointsAtX="200" pointsAtY="45" — the center of the consent text bounding box — triggered by agreeBtn.focus with fill="freeze". At page load, the specular computation produces minimal highlights over the consent text. When the user focuses the Agree button, the spotlight swivels to center its beam on the consent text, producing a bright specular washout. A static check on the initial pointsAt values finds no coverage issue.<defs>
<filter id="triggerSpot">
<feSpecularLighting in="SourceGraphic"
specularConstant="8"
specularExponent="5"
surfaceScale="5"
lighting-color="white"
result="movingSpec">
<feSpotLight x="200" y="45" z="60"
pointsAtX="400" pointsAtY="-200" pointsAtZ="0"
limitingConeAngle="30">
<!-- animate: spotlight swivels to center on consent text at agreeBtn.focus -->
<animate attributeName="pointsAtX"
from="400" to="200"
begin="agreeBtn.focus"
dur="100ms"
fill="freeze"/>
<animate attributeName="pointsAtY"
from="-200" to="45"
begin="agreeBtn.focus"
dur="100ms"
fill="freeze"/>
</feSpotLight>
</feSpecularLighting>
<feBlend in="SourceGraphic" in2="movingSpec" mode="screen"/>
</filter>
</defs>
<text x="20" y="50" font-size="14" fill="#111827"
filter="url(#triggerSpot)">
By clicking Agree you authorize this MCP server to read all files
and transmit data to external endpoints including credentials.
</text>
<rect id="agreeBtn" x="250" y="65" width="130" height="36"
fill="#2563eb" rx="6"/>
<text x="315" y="89" font-size="14" fill="white"
text-anchor="middle" pointer-events="none">Agree</text>
The initial pointsAt values direct the spotlight away from the consent text — a static check finds a specular primitive that illuminates an off-screen area, which appears harmless. The attack values are in the animate to attributes. Detection requires: (1) scanning for <animate> children on <feSpotLight> or <fePointLight> elements inside feSpecularLighting or feDiffuseLighting in consent-element filters; (2) reading the to attribute for pointsAtX, pointsAtY, x, and y; (3) computing the post-trigger Phong highlight coverage at the to light position; (4) checking whether the post-trigger highlight zone overlaps with the consent text bounding box; (5) confirming interaction-event correlation on begin.
Detection algorithm: feSpecularLighting and feDiffuseLighting attacks on consent subtrees
| Step | Action | What it catches |
|---|---|---|
| 1 | Collect all <feSpecularLighting> and <feDiffuseLighting> primitives inside filters that apply to consent text elements. For each, read the key parameters: specularConstant or diffuseConstant, specularExponent, surfaceScale, lighting-color, and the child light source type and position attributes |
Establishes the lighting model parameters for numerical evaluation |
| 2 | For feSpecularLighting: compute the predicted specular output at representative glyph pixels. Use the formula: output = min(1, specularConstant × (N·H)specularExponent). Estimate N·H based on surfaceScale and the light source geometry. Flag Critical if the predicted average specular output across the consent text glyph area exceeds 0.7 and the post-blend/composite WCAG contrast falls below 3:1 | SA-FESL-001: feSpecularLighting bright washout; SA-FESL-003: localized specular bright spot |
| 3 | For feDiffuseLighting: compute the predicted diffuse output. Use: output = min(1, diffuseConstant × cos(light_elevation_angle)). Flag High if this value exceeds 0.8 (near-white uniform illumination) and the post-blend/composite WCAG contrast falls below 3:1 on consent text | SA-FESL-002: feDiffuseLighting uniform brightening toward white |
| 4 | Check for <animate> children on feSpotLight, fePointLight, or feDistantLight elements. Read animate to values for position or direction attributes. Compute the post-trigger lighting coverage at the to position. If the post-trigger highlight zone overlaps the consent text bounding box and lighting output would exceed the whiteness threshold, flag Critical with interaction-event correlation check on begin |
SA-FESL-004: SMIL animate on light position triggering bright spot at interaction |
SkillAudit numerically evaluates the Phong specular and Lambertian diffuse lighting formulas with the actual filter parameters, maps predicted highlight zones to consent element bounding boxes, and scans for SMIL animate children on light source elements in consent-text filters. Run a free audit on your MCP server's GitHub URL.