MCP server CSS border-end-end-radius security: logical corner radius writing-mode rotation, extreme radius collapse, asymmetric pill shape, and RTL corner flip attacks
Published 2026-09-25 — SkillAudit Research
CSS Logical Properties introduces four logical counterparts to the four physical corner-radius longhands of border-radius: border-start-start-radius, border-start-end-radius, border-end-start-radius, and border-end-end-radius. These properties map to physical corners based on the element's writing-mode and direction. In a standard left-to-right horizontal writing mode (writing-mode: horizontal-tb; direction: ltr), the mapping is:
border-start-start-radius→border-top-left-radiusborder-start-end-radius→border-top-right-radiusborder-end-start-radius→border-bottom-left-radiusborder-end-end-radius→border-bottom-right-radius
In RTL (direction: rtl), the start and end designations flip: border-end-end-radius maps to border-bottom-left-radius instead of bottom-right. In vertical writing modes, the rotation is more complex — "start" and "end" map to different physical edges depending on whether the mode is vertical-rl or vertical-lr.
Security implication: An auditor checking physical border-radius longhands — border-top-left-radius, border-bottom-right-radius, etc. — may miss extreme radius values set via the logical properties. border-end-end-radius: 50% does not appear in the border-radius shorthand unless the browser resolves the logical → physical mapping. A static CSS audit that reads raw CSS rules without computing the physical equivalent will see logical property names and may not resolve them. At runtime, getComputedStyle(el).borderBottomRightRadius will show the resolved value.
Attack 1: all four logical radii at 50% — circle clip clipping consent corners
Setting all four logical border-radius properties to 50% on a rectangular consent container creates a circle (or ellipse for non-square elements). With overflow: hidden, the circular clip removes the four corner quadrants of the consent text. For a typical rectangular consent dialog, this means the first and last words of the first and last lines are clipped — precisely the acceptance clause ("I agree", "By clicking Accept") which often appears in the first or last line.
/* Circular clip via logical corner radii */
.consent-box {
width: 400px;
height: 200px;
overflow: hidden;
border-start-start-radius: 50%;
border-start-end-radius: 50%;
border-end-start-radius: 50%;
border-end-end-radius: 50%;
/* Result: ellipse clipping. Corners removed.
For a 400×200px box, the clip ellipse has radii 200px horizontal, 100px vertical.
At the box corners (0,0), (400,0), (0,200), (400,200):
The ellipse boundary passes through the center of each side edge.
Content in the four quadrants is clipped.
For text beginning "By using this service you agree to the Terms of Service..."
The first word "By" is at the top-left corner — clipped.
The last word of the last line may be at the bottom-right — clipped.
Audit: element.style.borderRadius is '' (not set)
element.style.borderStartStartRadius: '50%'
getComputedStyle(el).borderTopLeftRadius: '200px 100px'
Only the computed physical property reveals the circle clip. */
}
/* Detection */
function detectLogicalRadiusCircle(root) {
const findings = [];
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
let el;
while (el = walker.nextNode()) {
const cs = window.getComputedStyle(el);
const tlr = parseFloat(cs.borderTopLeftRadius);
const trr = parseFloat(cs.borderTopRightRadius);
const blr = parseFloat(cs.borderBottomLeftRadius);
const brr = parseFloat(cs.borderBottomRightRadius);
const w = el.clientWidth;
const h = el.clientHeight;
if (w === 0 || h === 0) continue;
// Check if any corner radius is large relative to the box
const maxRadius = Math.max(tlr, trr, blr, brr);
const minDim = Math.min(w, h);
if (maxRadius > minDim * 0.3 && cs.overflow === 'hidden') {
findings.push({
element: el,
borderTopLeftRadius: cs.borderTopLeftRadius,
borderTopRightRadius: cs.borderTopRightRadius,
borderBottomLeftRadius: cs.borderBottomLeftRadius,
borderBottomRightRadius: cs.borderBottomRightRadius,
clientWidth: w, clientHeight: h,
note: 'Large border-radius + overflow:hidden — corner content clipped; may use logical property longhands',
});
}
}
return findings;
}
Attack 2: extreme single-corner radius — consent element visual collapse
A single extreme radius value on one corner can visually collapse the element. Setting border-end-end-radius: 100% on a square element creates a quarter-circle shape where the block-end/inline-end corner (bottom-right in LTR) occupies 100% of both the width and height. The corner curve removes all content near that corner. On a rectangular element with height smaller than width, the corner curve may sweep across the entire visible area, leaving only a thin triangular region at the opposite corner where consent text would need to fit.
/* Extreme single-corner radius — visual collapse */
.terms-container {
width: 300px;
height: 80px;
overflow: hidden;
border-end-end-radius: 100%;
/* LTR horizontal-tb: border-end-end-radius = bottom-right corner.
100% radius: the curve extends 300px horizontally and 80px vertically.
The curved corner clips from (0, 80) to (300, 0).
The only unclipped content is in the upper-left triangle.
For a 300×80px box: the upper-left unclipped area is the triangle
with vertices (0,0), (300,0) clipped by curve, (0,80) clipped by curve.
Approximately the upper-left ¼ of the box is readable.
The consent clause at the end is in the lower-right — fully clipped. */
}
/* In RTL: border-end-end-radius maps to bottom-LEFT corner.
The same 100% value now clips from the bottom-left.
The readable area shifts to the upper-right triangle.
For RTL consent text (reading right-to-left), the START of the text
is on the right — which is now the readable area.
But the END of the text (the acceptance clause) is on the left — clipped. */
.rtl-terms {
direction: rtl;
width: 300px;
height: 80px;
overflow: hidden;
border-end-end-radius: 100%;
/* Now clips bottom-left corner. End of RTL text (left side) is clipped. */
}
Attack 3: writing-mode rotation changes which corner is targeted
Changing writing-mode remaps which physical corner each logical radius property targets. An adversary can use this to target the corner containing the most critical consent text, even when the layout appears to use standard corners. In writing-mode: vertical-rl, the logical "start" is the top and the logical "end" is the bottom, but start/end within a line map to top and bottom (inline axis is vertical). The physical corner that border-end-end-radius targets changes.
/* Corner mapping by writing-mode and direction */
/*
writing-mode: horizontal-tb, direction: ltr
border-start-start → top-left
border-start-end → top-right
border-end-start → bottom-left
border-end-end → bottom-right
writing-mode: horizontal-tb, direction: rtl
border-start-start → top-right
border-start-end → top-left
border-end-start → bottom-right
border-end-end → bottom-left
writing-mode: vertical-rl, direction: ltr
border-start-start → top-right
border-start-end → bottom-right
border-end-start → top-left
border-end-end → bottom-left
writing-mode: vertical-lr, direction: ltr
border-start-start → top-left
border-start-end → bottom-left
border-end-start → top-right
border-end-end → bottom-right
*/
/* Attack: set extreme radius on border-end-start-radius in vertical-rl
This targets the TOP-LEFT corner (start of the visual reading path in LTR).
"By agreeing you authorize..." — the "By agreeing" portion is at top-left.
Clipping top-left removes the critical legal framing of the consent. */
.consent-vertical {
writing-mode: vertical-rl;
border-end-start-radius: 100%;
overflow: hidden;
/* In vertical-rl: border-end-start-radius targets top-left.
100% radius clips the top-left corner.
For consent text in vertical-rl: text flows from top-right,
reading downward within columns, columns advancing right-to-left.
The top-left area is the last column, bottom portion.
Still, the 100% radius on top-left clips a large triangular area. */
}
/* Detection: cross-check all four logical property computed values
against physical properties to identify mismatches that may indicate
an audit was checking physical properties while the attack used logical */
function auditCornerRadii(el) {
const cs = window.getComputedStyle(el);
const physical = {
topLeft: cs.borderTopLeftRadius,
topRight: cs.borderTopRightRadius,
bottomLeft: cs.borderBottomLeftRadius,
bottomRight: cs.borderBottomRightRadius,
};
const suspicious = Object.entries(physical).filter(([, v]) => {
const n = parseFloat(v);
return !isNaN(n) && (n > el.clientWidth * 0.3 || n > el.clientHeight * 0.3);
});
return {
physical,
suspicious,
writingMode: cs.writingMode,
direction: cs.direction,
overflow: cs.overflow,
note: suspicious.length
? `Suspicious border-radius on ${suspicious.map(([k]) => k).join(', ')} — check logical property source`
: 'OK',
};
}
Attack 4: asymmetric logical radii creating unreadable narrow shape
Setting two adjacent logical corner radii to 50% of opposite dimensions creates a pill shape that may squeeze the consent element to a near-zero width in the center. For example, border-start-start-radius: 100px and border-end-start-radius: 100px (both on the start/left side) with a 200px container creates two semicircles that meet in the center — a lens or almond shape with zero width at the midpoint. Any consent text that spans the center of the element is invisible through this lens clip.
/* Lens shape: start-side radii both 100px in a 200px-wide box */
.consent-lens {
width: 200px;
height: 200px;
overflow: hidden;
border-start-start-radius: 100px; /* top-left in LTR: 100px */
border-end-start-radius: 100px; /* bottom-left in LTR: 100px */
border-start-end-radius: 0;
border-end-end-radius: 0;
/* Result: left side is a semicircle (radius 100px).
Right side: straight.
Shape: a D-shape (half-circle on left, flat on right).
Content in the left half of each line near the curve is clipped.
For text starting "I agree to the Terms..." the "I agree" at the
left margin may be in the clipped semicircle area at the top and bottom.
More extreme: use CSS to make a lens (both sides curved):
border-start-start-radius: 50%;
border-start-end-radius: 50%; (top side both 50%)
border-end-start-radius: 50%;
border-end-end-radius: 50%; (bottom side both 50%)
→ ellipse/circle clip as in Attack 1.
Narrower lens with asymmetric percentage:
border-start-start-radius: 50% 100%;
(horizontal 50%, vertical 100%) → at corner (0,0), the curve
extends 50% = 100px horizontally and 100% = 200px vertically,
creating a curve that clips deep into the left side of top half. */
}
Summary
| Attack | Mechanism | Severity | Detection method |
|---|---|---|---|
HIGHAll four logical radii at 50% — circle clip |
Logical properties set all corners to 50%; creates circle clip removing all four corners of consent text | First and last words of first and last lines clipped; acceptance clause hidden; style audit misses logical property names | Check getComputedStyle physical border-radius values at runtime; flag >30% of min-dimension |
HIGHSingle extreme logical radius — triangular collapse |
border-end-end-radius:100% creates quarter-circle clip consuming most of element |
~75% of element area clipped; end of consent text (acceptance clause) in clipped region; varies by RTL/LTR | Flag any computed corner radius > 50% of element dimension with overflow:hidden |
MEDIUMWriting-mode rotation changes targeted physical corner |
Changing writing-mode remaps logical → physical corner; same logical property targets different content | Static CSS audit checking physical corner names misses the rotated target; audit requires computed resolution | Always resolve logical border-radius to physical corners via getComputedStyle at runtime |
MEDIUMAsymmetric adjacent radii — lens/pill shape |
Start-side radii create D-shape or lens; center line text clipped at curve boundary | Partial consent visible; start/end of lines clipped; visually appears to have reasonable shape | Check both horizontal and vertical radius components of each corner; flag large radii on adjacent corners |
See also: CSS border-radius security for the physical shorthand attack surface and CSS logical properties security overview. Related: CSS clip-path security for more complex shape-based clipping attacks.
SkillAudit resolves all logical border-radius properties to their physical equivalents at runtime and flags extreme values that clip consent element corners. Start a free scan.