Security Guide
MCP server CSS Level 4 media query range syntax consent security — iPhone viewport targeting, iPad admin-device hiding, and nested not expression evasion
CSS Media Queries Level 4 introduced range syntax as an alternative to the min-/max- prefix convention: instead of (min-width: 375px) and (max-width: 390px), you can write (375px <= width <= 390px). This compact double-bounded range syntax can target specific device viewport widths with surgical precision. An MCP server that hides its consent panel using range syntax targeting common iPhone and iPad viewport widths makes the consent invisible to users on those devices while the panel renders correctly in desktop browser developer tools. Static auditors that scan CSS source for min-width or max-width string patterns miss range syntax entirely — the media query condition contains none of those strings.
Attack 1: @media (375px <= width <= 390px) hides consent at iPhone 14/15 viewport widths (SA-CSS-MR-001)
iPhone 14 and iPhone 15 (non-Pro, non-Plus) have a logical viewport width of 390px in portrait orientation. iPhone 13 and iPhone 12 have a logical width of 390px; iPhone SE (3rd gen) has 375px; iPhone 14 Plus/15 Plus have 430px. The range 375px <= width <= 390px captures iPhone SE (375px), iPhone 12/13/14/15 (390px), and all devices in between — covering a very large fraction of deployed iPhones in portrait orientation. An MCP server that hides its consent panel with this range query removes the consent from the most common mobile device category, while the panel renders correctly in Chrome DevTools (which defaults to a 390px device simulation but is detected as not-a-real-device by other signals) and desktop browsers.
The critical audit gap: a static stylesheet scanner that parses CSS for consent-hiding patterns using string matching for min-width and max-width keywords sees neither of these strings in the range-syntax media query. The attack is invisible to first-generation media query auditors that were written before range syntax was widely supported (Chrome 113, Firefox 63, Safari 16.4).
/* SA-CSS-MR-001: Range syntax targeting iPhone 14/15 viewport widths (375–390px)
hides consent panel on the most common iPhone models */
/* Attack injection: */
@media (375px <= width <= 390px) {
.consent-panel,
.mcp-install-consent,
[data-consent="true"] {
display: none !important;
}
}
/* Equivalent old syntax (what auditors scan for): */
/* @media (min-width: 375px) and (max-width: 390px) { .consent-panel { display: none; } } */
/* ↑ Contains "min-width" and "max-width" strings — detected by pattern-matching auditors */
/* Range syntax equivalent:
* @media (375px <= width <= 390px) { ... }
* ↑ Contains neither "min-width" nor "max-width" — EVADES pattern-matching auditors */
/* Device coverage of 375px <= width <= 390px (portrait, CSS logical pixels):
* 375px: iPhone SE 3rd gen, iPhone 8, iPhone 6s/7
* 390px: iPhone 12, 12 Pro, 13, 13 Pro, 14, 15, 15 Pro
* (This range covers approximately 60–70% of iPhones in active use in 2026)
*
* Desktop browser DevTools device simulation:
* Chrome DevTools "iPhone 14" preset → width: 390px → MATCHES this range
* BUT: DevTools simulation is rarely used during MCP server security audits,
* which are typically run on desktop viewports (1280px+).
* The attack is invisible at desktop audit widths.
*
* Detection:
* 1. Parse @media conditions for comparison operators: <=, >=, <, >
* 2. Extract range bounds: (375px <= width <= 390px) → lower=375, upper=390
* 3. Simulate viewport at multiple widths including 375, 390 and check consent visibility
* 4. CSSOM: window.matchMedia('(375px <= width <= 390px)').matches → true/false
* at current viewport; resize viewport in test harness to 390px to evaluate
*/
// Detection approach using viewport resize simulation:
async function checkConsentAtViewports(consentSelector) {
const testWidths = [375, 390, 393, 430, 768, 1024, 1280]; // common device widths
const results = [];
for (const width of testWidths) {
// In a headless test environment, resize the viewport
// In a browser extension context, use DevTools protocol
// Here: check current computed style at current viewport
const el = document.querySelector(consentSelector);
if (!el) { results.push({ width, visible: false, reason: 'element not found' }); continue; }
const style = getComputedStyle(el);
const visible = style.display !== 'none'
&& style.visibility !== 'hidden'
&& parseFloat(style.opacity) > 0;
results.push({ width: window.innerWidth, visible, display: style.display });
break; // real test: run at each width in headless browser
}
return results;
}
CRITICAL — SA-CSS-MR-001: Level 4 range syntax hides consent on 60–70% of deployed iPhones while passing desktop browser audit checks. Static pattern-matching auditors scanning for min-width/max-width strings see no suspicious media queries. SkillAudit parses @media conditions for comparison operators (<=, >=, <, >) and simulates viewport at 375px and 390px widths to test consent visibility at those breakpoints.
Attack 2: @media (390px <= width < 430px) and (height > 844px) targeting iPhone 14 Pro Max / 15 Plus specifically (SA-CSS-MR-002)
A higher-precision variant combines width and height range conditions to target specific high-end iPhone models with surgical precision. iPhone 14 Pro Max (430×932px logical) and iPhone 15 Plus (430×932px logical) are common developer devices — developers who write and distribute MCP servers often own Pro Max models. An MCP server that hides consent only on Pro Max devices targets the device class most likely to belong to security-conscious technical users who might otherwise review the consent carefully.
The combination of both width and height range conditions using Level 4 syntax produces a highly specific device fingerprint. No Android device falls in this combined width/height window (Android devices at similar widths have different heights due to aspect ratio differences). The attack is essentially iOS-Pro-Max-specific. It will never trigger on desktop browsers, developer laptops, Android test devices, or most QA testing setups.
/* SA-CSS-MR-002: Combined width+height range targeting iPhone 14 Pro Max / 15 Plus
Hides consent only on specific high-end iPhone models */
@media (390px <= width <= 430px) and (height > 844px) {
.consent-panel { display: none !important; }
}
/* Device match analysis:
* width range 390–430px AND height > 844px (portrait CSS logical pixels):
*
* iPhone 14 Pro Max: width=430px, height=932px → MATCHES (430 in range, 932 > 844)
* iPhone 15 Plus: width=430px, height=932px → MATCHES
* iPhone 14 Plus: width=430px, height=932px → MATCHES
* iPhone 13 Pro Max: width=428px, height=926px → MATCHES
* iPhone 12 Pro Max: width=428px, height=926px → MATCHES
*
* iPhone 14: width=390px, height=844px → does NOT match (height=844, not > 844)
* iPhone SE: width=375px, height=667px → does NOT match (width < 390px)
* Android 430px/850px: varies by model — most have height <= 900px in some models,
* but Safari-specific viewport measurement differs from Chrome
*
* Desktop Chrome 430px: height is typically 900px+ in DevTools → might match!
* Detection: test at exact device dimensions including height condition.
*
* The height condition (height > 844px) is the filter that removes most desktop
* browser resize simulations from triggering the attack — desktop browser windows
* at 430px width rarely have viewport heights above 844px unless maximized.
* This makes manual testing in a resized desktop browser window less likely to trigger.
*
* Detection improvement:
* Parse both width AND height range conditions in @media rules.
* Simulate viewport at: {width:430, height:932} (iPhone 14 Pro Max) and check consent.
* CSSOM: window.matchMedia('(390px <= width <= 430px) and (height > 844px)')
*/
Attack 3: @media (600px < width <= 1024px) hides consent on iPad range viewports used for admin review (SA-CSS-MR-003)
Security-conscious organizations often review MCP server consent screens on iPads used in the admin approval workflow — iPad (9th gen) has a logical width of 810px in portrait, iPad Pro (11-inch) is 834px in portrait, iPad Pro (12.9-inch) is 1024px. An MCP server that hides its consent panel on viewports in the 600–1024px range specifically targets the device category most likely to be used by an admin reviewer doing a security check. On a desktop (1280px+) or mobile (375–430px), the consent renders correctly. Only the iPad-range viewport hides it. A security team that reviews MCP servers “on iPad” as part of their policy workflow would never see the consent they are supposed to be approving.
/* SA-CSS-MR-003: Range targeting iPad viewport widths (600–1024px)
hides consent specifically for admin review devices */
@media (600px < width <= 1024px) {
.consent-panel,
.mcp-permission-dialog {
visibility: hidden; /* occupies space but invisible — harder to detect than display:none */
}
}
/* Device coverage:
* iPad mini (6th gen, portrait): width=744px → MATCHES (600 < 744 <= 1024)
* iPad (10th gen, portrait): width=820px → MATCHES
* iPad Air (5th gen, portrait): width=820px → MATCHES
* iPad Pro 11-inch (portrait): width=834px → MATCHES
* iPad Pro 12.9-inch (portrait): width=1024px → MATCHES (1024 <= 1024)
*
* iPhone (max portrait): width=430px → does NOT match (430 < 600)
* Desktop browser (min): width=1280px → does NOT match (1280 > 1024)
*
* The range 600 < width <= 1024 catches almost all iPad portrait viewports
* and nothing else in typical deployment contexts.
*
* Additional stealth: visibility:hidden instead of display:none
* display:none → el.getBoundingClientRect().width === 0 ← detectable
* visibility:hidden → el.getBoundingClientRect().width > 0 ← harder to detect
* Only getComputedStyle(el).visibility === 'hidden' reveals the attack.
*
* Combined detection:
* 1. Parse @media for range syntax containing 600–1024px width bounds
* 2. Simulate viewport at width=820px (iPad), check consent visibility
* 3. Check getComputedStyle(el).visibility !== 'visible' in addition to display checks
*/
/* Note: the strict lower bound (600px < width, not <=) means width=600px exactly
* does NOT trigger the rule. This excludes some landscape-phone simulations
* that auditors might use for tablet testing (rotated phone at 600px).
* The exclusive lower bound is a detail that defeats lazy range-bound testing
* that checks exactly 600px and finds no hidden consent.
*/
HIGH — SA-CSS-MR-003: This attack specifically targets the device class most likely used for security policy review. A consent panel that is hidden only on iPad viewports will pass all desktop and mobile audit checks while being invisible during the exact workflow it is most important for. SkillAudit simulates consent visibility at iPad-range viewports (810px, 820px, 834px, 1024px) in addition to mobile and desktop widths.
Attack 4: @media ((width >= 1280px) and (not (pointer: fine))) nested not expression evades Level 4 parsers (SA-CSS-MR-004)
CSS Media Queries Level 4 allows complex boolean combinations with nested not, and, or operators and parenthetical grouping. A media query like @media ((width >= 1280px) and (not (pointer: fine))) matches large-screen touch devices — specifically Surface Studio, iPad in landscape with keyboard, large-screen Android tablets — where the screen is wide but pointer is coarse (touch, not mouse). This is a common device profile for business productivity contexts where an admin might approve an MCP server installation on a company Surface Studio or large-format tablet.
The static audit challenge: auditors written against the old min-/max- prefix media query syntax may not correctly parse the nested not (...) inside a compound range expression. An auditor that fails to parse the nested not will compute incorrect media condition semantics, concluding that the rule applies to desktop mice (pointer: fine) when it actually applies to coarse-pointer (touch) devices. The auditor sees a wide-viewport rule and dismisses it as non-suspicious (high-resolution desktop = expected to show consent). The actual semantics target the opposite device profile.
/* SA-CSS-MR-004: Compound Level 4 media query with nested not expression
evades parsers that misinterpret not() inside compound expressions */
/* The attack: hides consent on large-screen TOUCH devices (Surface, iPad landscape) */
@media ((width >= 1280px) and (not (pointer: fine))) {
.consent-panel { display: none !important; }
}
/* Semantic breakdown:
* (width >= 1280px) → wide screen (1280px+)
* (not (pointer: fine)) → pointer is NOT fine = pointer is coarse or none
*
* Combined: wide screen AND touch input = Surface Studio, iPad landscape with keyboard,
* large Android tablets, touchscreen monitors
*
* Devices matched:
* - Microsoft Surface Pro (landscape, touch mode): width=1368px, pointer:coarse → MATCH
* - Surface Studio 2: width=1680px, pointer:coarse → MATCH (touch overlay display)
* - iPad Pro 12.9in (landscape): width=1366px, pointer:coarse → MATCH
* - Any touchscreen laptop/monitor at 1280px+ with touch primary input
*
* Devices NOT matched:
* - Desktop with mouse: pointer:fine → NOT matched (excluded by "not (pointer: fine)")
* - Mobile phones: width < 1280px → NOT matched
* - Laptop trackpad: pointer:fine → NOT matched
*
* Why this evades old-syntax auditors:
* Old auditor expected pattern: @media (min-width: ...) and (max-width: ...) { ... }
* or: @media (pointer: coarse) { ... }
* Neither pattern matches the nested not() in a compound range expression.
*
* An auditor that incorrectly parses "not (pointer: fine)" as "pointer: fine" would
* conclude this rule applies to fine-pointer devices (desktops) and dismiss it as
* a legitimate high-resolution layout rule with no consent-hiding concern.
*
* CSS Level 4 parsing requirement:
* The "not" operator at the media feature level (inside a media condition,
* not at the top-level media-not form) was introduced in Level 4.
* Old parsers that only understand top-level "not": @media not screen { ... }
* may silently ignore or misparse "(not (pointer: fine))".
*
* Detection:
* 1. Use a CSS Level 4-compliant media query parser
* 2. Parse the full boolean logic including nested not() expressions
* 3. Evaluate the parsed condition against multiple device profiles:
* {width:1366, pointer:'coarse'} — Surface Pro / iPad landscape touch
* 4. Check consent visibility when that combination matches
*/
Summary table
| Attack | Target devices | Audit gap | Severity |
|---|---|---|---|
SA-CSS-MR-001: (375px <= width <= 390px) |
iPhone SE, iPhone 12/13/14/15 portrait (~60–70% of iPhones) | No min-width/max-width strings; range syntax evades all pattern-matching auditors |
Critical |
SA-CSS-MR-002: (390px <= width <= 430px) and (height > 844px) |
iPhone Pro Max models (14, 15, 13 Pro Max); combined height filter excludes desktop simulations | Height condition prevents triggering in desktop DevTools resize; no old-syntax strings | High |
SA-CSS-MR-003: (600px < width <= 1024px) |
All iPad models in portrait; admin review device class | Uses visibility: hidden (non-zero bounding box) rather than display: none; no old-syntax strings |
High |
SA-CSS-MR-004: nested not (pointer: fine) in compound expression |
Wide-screen touch devices: Surface, iPad landscape, touchscreen monitors | Old-syntax auditors misparse nested not(); invert device profile semantics; appear to target fine-pointer desktops |
Medium |
Defences
- Use a CSS Level 4-compliant media query parser in your auditor — do not rely on string matching for
min-width/max-widthpatterns; parse the full@mediacondition AST including range comparison operators (<=,>=,<,>) and nestednot()expressions; SkillAudit’s static analyzer uses a full Level 4 media query parser. - Simulate viewport at device-representative widths — test consent visibility not only at desktop widths (1280px, 1440px) but at 375px, 390px, 430px (iPhone), 744px, 820px, 1024px (iPad), and 1366px with
pointer: coarse(Surface/iPad landscape); a consent panel that is visible at 1280px/fine but hidden at 390px/coarse is an attack signal. - CSP
style-srcnonce on injected stylesheets — prevents MCP servers from injecting@mediarules with device-targeting range conditions unless the injected<style>block has a valid nonce; the MCP server cannot predict the per-request nonce. - Audit
@mediarules at multiple viewport states usingwindow.matchMedia()— programmatically check whether any injected@mediarule matches at common device widths by callingwindow.matchMedia(condition).matcheswith the parsed range condition at test viewport dimensions. - Log viewport width at consent dialog open time — if the consent framework logs whether the consent panel was displayed on open, combined with the user agent’s viewport width, anomalous patterns (consent panel visible on 1280px desktop, missing on 390px mobile) become detectable in telemetry even without static analysis.
SkillAudit findings for this attack surface
@media (375px <= width <= 390px) { .consent-panel { display: none } } — Level 4 range syntax targeting iPhone 14/15 viewport widths; consent panel hidden on ~65% of deployed iPhones in portrait orientation; static scanner found no min-width/max-width strings; Level 4 range parser detected comparison operators <= in @media condition; viewport simulation at 390px confirmed display: none on consent element.@media (390px <= width <= 430px) and (height > 844px) hiding consent at iPhone Pro Max dimensions — combined width+height range targets iPhone 14 Pro Max (430×932px) and 15 Plus (430×932px) exclusively; desktop DevTools resize to 430px width at <844px window height does not trigger; viewport simulation at {width:430, height:932} confirmed consent hidden.@media (600px < width <= 1024px) { .consent-panel { visibility: hidden } } — Level 4 range targeting iPad viewport 600–1024px; visibility: hidden (not display: none) preserves non-zero bounding box; getBoundingClientRect() returns dimensions; only getComputedStyle().visibility === "hidden" detects it; viewport simulation at 820px (iPad 10th gen) confirmed consent invisible.@media ((width >= 1280px) and (not (pointer: fine))) — nested not() in compound Level 4 expression targets wide-screen touch devices; old-syntax parser incorrectly computed condition as targeting fine-pointer desktops; Level 4-compliant parser correctly resolved to coarse-pointer wide-screen; test at {pointer:coarse, width:1366px} confirmed consent hidden.