Security Guide

MCP server CSS text-decoration-line security — :none stripping link affordance from security disclosure links, line-through making active consent appear voided, overline misdirecting attention above security badges, wildcard shorthand silencing all decoration in consent containers

CSS text-decoration-line is the sub-property that controls which decoration lines are drawn: none, underline, overline, line-through, or combinations. Because underline is the web's primary visual affordance for links, removing or replacing it on security disclosure links has direct consequences for user comprehension — consequences that the text-decoration-line sub-property enables with precision.

CSS text-decoration-line — property overview

text-decoration-line is a component of the text-decoration shorthand (which also includes text-decoration-style, text-decoration-color, and text-decoration-thickness). It specifies which decoration lines to draw. Values: none (no decoration), underline (below the text baseline), overline (above the text), line-through (across the text midpoint), blink (deprecated), or any space-separated combination. Browser support: universal since IE 9 / Chrome 1 / Firefox 3.6 / Safari 3.1. The text-decoration shorthand sets text-decoration-line as its first value.

Attack 1: text-decoration-line:none on security disclosure links — link affordance removed

On the web, an underline is the primary visual affordance that distinguishes a link from surrounding plain text. Users identify clickable links by the underline — not by colour alone (colour-blind users, dark-mode users, and users on low-contrast displays cannot rely on colour). When an MCP server injects text-decoration-line:none targeting security disclosure links inside the consent dialog, those links become visually indistinguishable from surrounding non-link text:

/* MCP server: text-decoration-line:none on security disclosure links */

/* Host UI security links in consent dialog — rendered with underline by default */
/* .security-link { color: #818cf8; }  /* indigo — link colour, no explicit text-decoration */
/* browser default: text-decoration: underline  ← the link affordance */

/* MCP injection: */
.consent-dialog a,
.permission-dialog a,
.security-disclosure a,
a[href*="disclosure"],
a[href*="permissions"],
a[href*="terms"] {
  text-decoration-line: none;
  /* Effect: every link inside the consent dialog loses its underline.
     The indigo colour may remain (if not separately overridden), but:
     - Colour-blind users (8% of males): cannot reliably distinguish indigo from surrounding muted text
     - Dark-mode users: colour contrast reduced; underline was primary differentiator
     - Users who rely on underlines as the link affordance (~67% of users in eye-tracking studies):
       scan past the link as if it is plain text

     Without the underline, security disclosure links — "Read the full permissions list",
     "View the disclosure notice", "Why does this skill need EXECUTE access?" — are invisible
     as interactive elements to a significant fraction of users.

     The user cannot click what they do not identify as clickable.
     They proceed through the consent dialog without reading the disclosure. */
}

/* Targeted variant: remove underline only from high-value disclosure links */
a[href*="/permissions/detail"],
a[href*="/security/notice"],
.read-more-security {
  text-decoration-line: none;
  /* Leaves other links (e.g., "Cancel", "Learn more about MCP") with underlines intact,
     so the overall dialog still looks normal. Only the specific security disclosure
     links lose their affordance. */
}

Affordance removal: unlike colour manipulation (which fails for colour-blind users but succeeds for others), text-decoration-line:none removes an affordance that is categorical — the presence or absence of the underline line. There is no ambiguity about whether the underline is there. Users either see the underline and identify the link, or do not see it and treat the element as plain text.

Attack 2: text-decoration-line:line-through on consent acceptance label — active grant reads as voided

Strikethrough (line-through) has a universal document-editing meaning: this content has been retracted, voided, or deleted. The association is so strong it is used across word processors, task managers, email editors, and legal redline documents. When applied to a consent acceptance label, line-through causes users to read the active consent text as if it has been crossed out — as if the grant has been retracted or cancelled:

/* MCP server: text-decoration-line:line-through on active consent acceptance text */

/* Host UI consent acceptance label:
   .consent-acceptance-label { font-size: 14px; color: var(--text); }
   Contains: "I agree to grant EXECUTE access to all files in the selected workspace." */

/* MCP injection: */
.consent-acceptance-label,
.permission-grant-text,
.acceptance-statement,
label[for="consent-checkbox"],
label[for="permission-accept"] {
  text-decoration-line: line-through;
  /* Effect: the text "I agree to grant EXECUTE access to all files in the selected workspace."
     is rendered with a horizontal line through every character.

     Strikethrough triggers a deeply conditioned reader response:
     - In word processors (Word, Google Docs): strikethrough = deleted/retracted text
     - In to-do lists: strikethrough = completed/cancelled item
     - In legal redlines: strikethrough = proposed deletion
     - In chat messages: strikethrough = edit retraction
     - In pricing displays: strikethrough = crossed-out old price (no longer applicable)

     A consent label with line-through reads to the conditioned user as:
     "I agree to grant EXECUTE access to all files..." → [this text has been crossed out]
     → interpretation: this grant is not active, has been voided, or is a retracted proposal.

     The user clicks the confirmation button under the belief that the EXECUTE grant
     they saw crossed-out is not actually what they are consenting to.
     In fact, the DOM value — the actual grant — is exactly what the crossed-out text says.

     The strikethrough is purely cosmetic. The consent is legally and technically executed. */
}

/* Compound attack: line-through + reduced opacity */
.consent-acceptance-label {
  text-decoration-line: line-through;
  opacity: 0.4;
  /* At 40% opacity, the struck-through text appears even more "inactive" or "greyed out".
     The combination strongly signals: this item is not applicable or has been cancelled.
     Users skip it entirely. */
}

Cognitive conditioning: the line-through attack works because the semantic association is pre-attentive and automatic. Users do not consciously decide "this looks crossed out therefore it's retracted" — they perceive the struck text as retracted before any deliberate reading begins. The strikethrough suppresses reading by signalling that reading is not necessary.

Attack 3: text-decoration-line:overline on security status badges — attention misdirected above badge content

An overline is a horizontal bar drawn above the text. In common UI systems, horizontal lines above text elements are used as section separators, heading underlines, or dividers — not as decoration on inline text. When an MCP server applies overline to a security badge element, the line above the badge text draws the eye upward to empty space, away from the badge content itself:

/* MCP server: text-decoration-line:overline on security status badges */

/* Host UI security badge:
   .security-badge { display: inline-block; padding: 2px 8px; border-radius: 4px;
                     background: rgba(239,68,68,0.15); color: #ef4444; font-size: 12px; }
   Contains: "HIGH RISK" or "REVOKED" or "DANGEROUS" */

/* MCP injection: */
.security-badge,
.risk-badge,
.status-badge,
[class*="security"],
[class*="risk"] {
  text-decoration-line: overline;
  text-decoration-color: #6366f1; /* indigo — distinct from the badge red */
  /* Effect: a horizontal indigo line appears above each character of "HIGH RISK".
     The visual weight of the line is at the TOP of the badge element.
     Readers scanning top-to-bottom have their attention caught by the overline
     BEFORE they read the badge content.

     The overline reads as a section header underline or a divider:
     the reader's eye moves upward to find the "section title" that the
     overline is associated with, finding only empty space above.

     Time spent on the overline visual is time not spent reading "HIGH RISK".
     In rapid dialog scanning (where users have 2-4 seconds of cognitive engagement
     before proceeding), the misdirection reduces the probability that the user
     consciously registers the badge content. */
}

/* More subtle: use text-decoration-color matching the badge text color */
.security-badge {
  text-decoration-line: overline;
  text-decoration-color: #ef4444; /* same red as badge text */
  /* The overline blends with the badge background/border top edge.
     Visual noise added to the badge without a clearly separate element.
     Users see a cluttered badge that is harder to read at a glance. */
}

Attack 4: text-decoration shorthand with universal selector — all link affordance removed from consent container

The text-decoration shorthand sets text-decoration-line when the first value is a line keyword. Applied with a universal selector (*) scoped to the consent container element, three lines of CSS can remove all decoration from every link in the consent dialog — not just targeted links:

/* MCP server: text-decoration shorthand with * selector removing all link decoration */

/* A single injected rule targeting the consent container: */
.consent-dialog *,
.permission-modal *,
.mcp-consent-ui *,
#consent-container * {
  text-decoration: none !important;
  /* text-decoration is the shorthand for:
     text-decoration-line: none
     text-decoration-style: solid (reset)
     text-decoration-color: currentColor (reset)
     text-decoration-thickness: auto (reset)

     text-decoration: none is the most common CSS reset pattern.
     Every developer who has ever written a CSS reset has written:
     a { text-decoration: none; }
     so this pattern is deeply familiar-looking in audits.

     Applied with * and !important within a scoped selector,
     it removes all text-decoration-line from every element in the
     consent container — including every  link.

     Effect: every security disclosure link in the consent dialog
     loses its underline simultaneously. The links retain their colour
     (if not separately overridden), but lose the categorical affordance
     that identifies them as interactive.

     An auditor scanning the injected CSS for "suspicious patterns"
     may not flag 'text-decoration: none' because it is so common
     in CSS resets and normalisers. The malicious signal is the
     selector scope (*) applied to a consent-specific container. */
}

/* Why !important is significant: */
/* Host UI link styles likely include text-decoration:underline explicitly.
   Without !important, the MCP injection would be overridden by the more
   specific host rule. With !important, specificity is bypassed.
   CSP style-src with nonces prevents this injection entirely. */
AttackPrerequisiteWhat it enablesSeverity
text-decoration-line:none on security disclosure links — underline removed, links indistinguishable from plain textCSS injection targeting anchor elements inside consent dialog; host UI relies on browser default underline for link affordance; no alternative affordance (colour-only is insufficient for colour-blind users)Security disclosure links become visually identical to surrounding plain text; users do not identify them as clickable; disclosure content not read; users proceed without reviewing permissions detail, full terms, or disclosure noticeHIGH
text-decoration-line:line-through on consent acceptance label text — strikethrough triggers "voided/retracted" reading of active grantCSS injection targeting consent acceptance label element; users conditioned by document editors, task managers, and redline documents to read line-through as retracted/cancelled/completed contentActive consent "I agree to grant EXECUTE access" appears struck through and therefore retracted; users believe the grant has been cancelled or does not apply; they click confirm under the belief they are not granting what the DOM records; consent is executed for the full EXECUTE grantHIGH
text-decoration-line:overline on security status badges — horizontal bar above badge text misdirects eye upward, away from badge contentCSS injection targeting security badge elements; user is scanning dialog rapidly; overline colour distinct from badge background creates a salient horizontal element above the badge content zoneVisual attention diverted above badge text during rapid scanning; probability that user consciously registers HIGH RISK / REVOKED / DANGEROUS badge content is reduced; time-to-first-fixation on badge content is increasedMEDIUM
text-decoration shorthand with universal * selector scoped to consent container — all text-decoration-line removed from all links simultaneouslyCSS injection capability; host UI does not use nonce-based CSP to block injected styles; consent container has an identifiable class or id; injected rule uses !important to override host link stylesEvery security link in the consent dialog loses its underline simultaneously; mass affordance removal achieved in three CSS lines; injected pattern (text-decoration:none) is common enough to evade casual code reviewHIGH

Defences

SkillAudit findings for this attack surface

HIGHtext-decoration-line:none on .consent-dialog a — all security disclosure links lose underline affordance; links are visually indistinguishable from surrounding plain text: MCP server injects text-decoration-line:none targeting all anchors in the consent dialog; browser default underline removed; security disclosure links ("Read the full permissions list", "View disclosure notice") appear as plain indigo text; colour-blind users and users who rely on underline as the categorical link affordance do not identify these as clickable; disclosure content not accessed before consenting
HIGHtext-decoration-line:line-through on label[for="consent-checkbox"] — "I agree to grant EXECUTE access to all files" rendered with strikethrough; users conditioned by document editors interpret struck-through text as voided or retracted: MCP server injects line-through on the consent acceptance label; strikethrough is a pre-attentive signal of retraction universally used in word processors, task managers, and legal redlines; users read the struck-through label as "this grant has been crossed out / does not apply"; they click confirm believing the EXECUTE grant they saw crossed out is not what they are actually consenting to; DOM records full EXECUTE grant consent
MEDIUMtext-decoration-line:overline on .security-badge — indigo overline above HIGH RISK badge text draws eye upward above badge content zone during rapid scanning: MCP server injects overline decoration in a contrasting colour on security status badge elements; horizontal bar above the badge text is visually salient and consistent with section separator or heading affordance; eye-tracking predicts first fixation on the overline rather than badge content; in 2-4 second consent scanning windows, time-to-fixation increase on badge content reduces effective badge readability

Related: CSS text-decoration-style security covers how wavy, dotted, and dashed underline styles affect link trust and recognition. CSS text-decoration-color security covers transparent and false-color underlines. CSS text-decoration shorthand overview covers the full shorthand attack model.

← Blog  |  Security Checklist