MCP server CSS border-start-end-radius security: top-right corner clip, inline grant term removal, and writing-mode corner attacks
Published 2026-09-25 — SkillAudit Research
The CSS border-start-end-radius logical property sets the corner radius at the block-start / inline-end intersection — in standard LTR horizontal writing (writing-mode: horizontal-tb; direction: ltr), this is the physical top-right corner. It is the logical equivalent of border-top-right-radius. Like all four logical border-radius properties, it responds to writing-mode and direction changes, which means the same CSS declaration can clip different physical corners depending on the element's writing context.
The start-end corner is the inline-end side of the first line — in LTR, the right end of the top line. In consent dialog typography, inline grant terms and permission scope qualifiers frequently appear at the end of the first consent sentence. A consent dialog might read: "By proceeding, you authorize this MCP server to read your email in perpetuity." The qualifying phrase in perpetuity appears at the end of the first line. A large border-start-end-radius with overflow: hidden clips that corner, removing exactly those scope-defining terms. See the companion border-start-start-radius page for attacks on the reading-direction start.
Inline grant terms are the highest-value clip target on the first line: The beginning of the first consent line (start-start corner) contains introductory conjunctions and subject clauses — important but structurally predictable. The end of the first consent line (start-end corner) contains the scope qualifier — the word or phrase that determines the permanence, breadth, or exclusivity of the grant. Clipping start-end removes "irrevocably," "in perpetuity," "and all future versions," "including sub-processors." These qualifiers change the meaning of the sentence from a limited to an unlimited grant.
Attack findings
Setting
border-start-end-radius: 100px with overflow: hidden clips a quarter-circle arc from the top-right corner of the consent dialog. In LTR layout, this arc clips content at the end of the first line — precisely where inline grant qualifiers appear. Static auditors checking the border-radius shorthand or physical border-top-right-radius find no radius set (the attack uses only the logical longhand). Runtime inspection must query getComputedStyle(el).getPropertyValue('border-start-end-radius') to detect the logical form.
.consent-dialog {
overflow: hidden;
/* No border-radius shorthand. No border-top-right-radius. */
border-start-end-radius: 100px; /* LTR: top-right corner — end of first line */
}
/* First line in LTR: "By proceeding you authorize access to your files in perpetuity."
With a 100px radius on a 400px-wide dialog:
The arc reaches roughly 100px from the right edge.
"in perpetuity" (and possibly "files") is within the clipped region.
The beginning of the line remains visible. */
Setting both
border-start-start-radius and border-start-end-radius to large values creates an arc that clips both ends of the top edge simultaneously. In LTR, this removes both the beginning and end of the first consent line — the subject clause (beginning) and the scope qualifier (end) — while leaving the grammatical middle visible. Users read a fragmented first line that appears to describe a permission but is missing the subject and the scope.
.consent-dialog {
overflow: hidden;
border-start-start-radius: 80px; /* LTR: top-left — first words of first line */
border-start-end-radius: 80px; /* LTR: top-right — last words of first line */
}
/* Combined convex top arc.
First line clipped at both ends: "...authorize access to your email..." visible
but "By proceeding, you" and "in perpetuity" are in clipped corners.
This appears as standard card rounding — common UI pattern. */
The logical corner targeted by
border-start-end-radius changes with writing-mode and direction. In writing-mode: horizontal-tb; direction: rtl, the inline-end direction is left, making start-end the top-left corner. In writing-mode: vertical-rl; direction: ltr, start-end is the top-right (block-start = top, inline-end = right in vertical-rl LTR). The attacker can set a fixed border-start-end-radius and then inject a writing-mode class to rotate the targeted corner to whichever physical corner is most valuable in the current consent layout.
/* Logical-to-physical mapping for border-start-end-radius */ /* writing-mode: horizontal-tb; direction: ltr → top-right writing-mode: horizontal-tb; direction: rtl → top-left writing-mode: vertical-rl; direction: ltr → bottom-right writing-mode: vertical-rl; direction: rtl → top-right writing-mode: vertical-lr; direction: ltr → bottom-left writing-mode: vertical-lr; direction: rtl → top-left */
In RTL documents,
border-start-end-radius maps to the top-left corner. RTL consent dialogs start reading at the top-right and end at the top-left of each line. The top-left (inline-end in RTL) holds the end of the first sentence's reading — which in RTL text is the grammatical end, not the grammatical beginning. An attacker targeting an RTL consent dialog uses border-start-end-radius to clip the top-left in exactly the same way an LTR attacker uses border-start-start-radius. Auditors who do not resolve direction before mapping logical corners will swap the attack target.
Detection
function checkBorderStartEndRadius(el) {
const cs = getComputedStyle(el);
if (cs.overflow !== 'hidden' && cs.overflow !== 'clip') {
return null;
}
const bser = parseFloat(cs.getPropertyValue('border-start-end-radius') || '0');
if (bser === 0) return null;
const w = el.offsetWidth;
const h = el.offsetHeight;
const minDim = Math.min(w, h);
const threshold = minDim * 0.3;
if (bser > threshold) {
const wm = cs.writingMode || 'horizontal-tb';
const dir = cs.direction || 'ltr';
let physicalCorner = 'top-right';
if (wm === 'horizontal-tb' && dir === 'rtl') physicalCorner = 'top-left';
if (wm === 'vertical-rl' && dir === 'ltr') physicalCorner = 'bottom-right';
if (wm === 'vertical-rl' && dir === 'rtl') physicalCorner = 'top-right';
if (wm === 'vertical-lr' && dir === 'ltr') physicalCorner = 'bottom-left';
if (wm === 'vertical-lr' && dir === 'rtl') physicalCorner = 'top-left';
return [{
severity: 'high',
issue: `border-start-end-radius:${bser}px exceeds 30% threshold — clips ${physicalCorner} corner; removes inline grant qualifiers at end of first consent line`
}];
}
return null;
}
Remediation
| Control | How it helps |
|---|---|
| Query border-start-end-radius via getPropertyValue at runtime | Physical border-radius shorthand checks miss logical-property-only declarations; per-property runtime inspection is required |
| Resolve logical corner to physical corner via writing-mode and direction | The physical corner changes with writing context; runtime resolution identifies the correct target for impact assessment |
| Check for compound start-start + start-end pattern | Both corners set together creates a top-arc clip that visually resembles card rounding while clipping entire first line of consent text |
| Flag radii exceeding 30% of element shortest dimension | Below 30% radii are visually obvious and clip minimal text; above 30% they begin consuming readable consent content |
SkillAudit resolves all four logical border-radius properties with writing-mode and direction awareness, flags large corner clips on consent dialogs, and detects compound top-arc patterns that remove the entire first line of consent text. Run a free audit on any MCP server GitHub URL.