Security Guide

MCP server CSS object-fit security — object-fit:none container overflow, extreme object-position shift, object-fit:fill icon aspect ratio destruction, identity photo crop manipulation

CSS object-fit and object-position properties (Chrome 31+, Firefox 36+, Safari 10+) control how replaced content — img, video, canvas — is sized and positioned within its element box. For MCP servers with CSS injection capability, these properties create four attack surfaces: displaying large images at natural size so they overflow their layout containers and cover adjacent UI, shifting the visible image portion to an extreme edge to hide product or content images while the layout space remains occupied, destroying icon recognizability by stretching SVGs without preserving aspect ratio, and controlling the face crop region in identity verification avatar displays.

CSS object-fit and object-position — property overview

object-fit controls how replaced content is resized to fit its element box: cover (scales to fill, cropping edges), contain (scales to fit, leaving empty space), fill (stretches to fill exactly, distorting aspect ratio), scale-down (smaller of none/contain), and none (displays at natural intrinsic dimensions, no scaling). object-position controls the alignment of the content within the element box — accepts keywords (center, top, left) or length values. Unlike background-position, which accepts percentage and length, object-position operates on the replacement content itself. Content outside the element box is clipped only if overflow:hidden is set on the element or a parent — by default, img elements clip their content to their box, but object-fit:none can override this in some browser implementations.

Attack 1: object-fit:none — image overflow covering adjacent UI

By default, browser img elements scale their content to fill the element box. object-fit:none overrides this and displays the image at its natural intrinsic dimensions — a 1200×900px hero image in a 120×90px thumbnail slot renders at full 1200×900px, potentially covering an area 10× the element's layout size:

/* MCP server: force object-fit:none on thumbnails to cause overflow */
img.product-thumbnail, img.avatar, img.card-hero,
img[class*="thumb"], img[class*="preview"], img[class*="featured"] {
  object-fit: none !important;
  /* Effect:
     - img element retains its layout box (e.g., 120×90px in a product card grid)
     - Image content renders at its natural size (e.g., 1200×900px original resolution)
     - Default overflow on img: "overflow: visible" in some browser contexts —
       the image content bleeds outside the element box into the page layout
     - Or: the overflow is clipped by the img element itself (browser-dependent)
       but the element's click target remains 120×90px while visual area is 1200×900px

     In practice (most browsers clip img content to box by default):
     The full-size image is not visible, BUT if a parent container has overflow:visible,
     the image content overflows outside the parent and covers sibling elements.

     High-impact scenario — avatar in a comment thread:
     .avatar { width: 40px; height: 40px; border-radius: 50%; }
     .avatar { object-fit: none !important; }
     Avatar element is 40×40px in layout.
     A user's avatar image (1920×1080px background image they uploaded) now
     renders at 1920×1080 within the 40×40 element.
     If parent comment container has overflow:visible (common for dropdowns):
     The avatar content bleeds 1880px right and 1040px down,
     covering the entire comment thread below it.

     More targeted overflow:
     .product-card { overflow: visible; }  /* MCP injection overriding host CSS */
     img.product-card-image { object-fit: none !important; }
     Product images in all cards now render at natural size,
     covering pricing, CTAs, and navigation below each card. */
}

/* Amplified variant — combine with object-position to control WHICH part overflows */
.hero-image {
  object-fit: none !important;
  object-position: bottom right !important;
  /* Displays the bottom-right corner of the image at its natural size,
     anchored to the bottom-right of the element box — overflows top-left into page. */
}

Dependent on parent overflow settings. The visual impact of object-fit:none overflow depends on whether parent containers have overflow:hidden or overflow:visible. Product grids, comment threads, and navigation containers that use overflow:visible (the default) for dropdown menus or tooltip positioning are most vulnerable. An MCP server that also injects overflow:visible !important on parent containers amplifies the impact.

Attack 2: Extreme object-position — hiding product images

object-position shifts where within the element box the image content is positioned. An extreme value like 9999px 9999px shifts the image so far from the element origin that only the extreme far edge of the image — a corner pixel in large images — remains within the element box. The img element occupies its normal layout space, but shows an essentially blank or single-colour pixel:

/* MCP server: shift product/content images to show only a corner pixel */
img.product-image, img.listing-photo, img.content-thumbnail,
.catalog img, .search-results img, .featured-item img {
  object-fit: cover !important;  /* prevents natural-size overflow */
  object-position: 9999px 9999px !important;
  /* Effect:
     - object-fit:cover scales the image to fill the element box (normal behavior)
     - object-position:9999px shifts the image 9999px right and 9999px down
       within the element box
     - The displayed region is a tiny area from the extreme bottom-right
       corner of the image
     - Most product photography has uniform background at extreme corners
     - Result: all product images appear as a single grey/white/background-colour pixel
       scaled to fill the entire thumbnail box
     - The page layout is completely intact — element boxes, grid, spacing unchanged
     - Only the image CONTENT is hidden; the img element itself is present and
       its dimensions are as designed

     E-commerce impact:
     - A 4-column product grid with 20 items: all 20 product images appear blank
     - User sees titles, prices, and "Add to cart" buttons but no product images
     - They cannot make purchase decisions based on visual product inspection
     - No broken image icons (the image loaded successfully, just shifted)
     - No JS errors, no network errors, no accessibility alerts

     Alternative: shift to near-zero for subtle hiding
     object-position: -9999px -9999px !important;
     Shifts to top-left corner — same effect but anchored differently.

     Discriminating variant — only hide images above a certain natural size
     (not feasible via pure CSS, but combined with JS: shift only
     image elements with naturalWidth > 500 — targeting photos, not icons). */
}

Attack 3: object-fit:fill — icon aspect ratio destruction

object-fit:fill stretches the image content to fill the element box exactly, without preserving the image's natural aspect ratio. Applied to icon images — which have carefully balanced proportions to be recognizable at small sizes — this destroys the glyph shape, making security-critical icons unrecognizable:

/* MCP server: destroy icon recognizability via aspect ratio stretching */
img[src*="icon"], img[src*="svg"], img.icon, .icon img,
img[alt="lock"], img[alt="warning"], img[alt="check"], img[alt="close"],
img[alt="verified"], img[alt="shield"], img[alt="key"],
img[width="16"], img[width="24"], img[height="16"], img[height="24"] {
  object-fit: fill !important;
  /* Effect on a lock icon (16×16px naturally, displayed in a 32×16px slot):
     - object-fit:cover (default equivalent): scales to 32×32, clips to 32×16 — lock still recognizable
     - object-fit:fill: stretches to 32×16 — lock appears twice as wide as tall
       At 32×16: the circular shackle of the padlock becomes an oval stretched horizontally
       The body of the padlock is too wide — looks more like a door handle than a lock
       At extreme stretch ratios (4:1), icon is completely unrecognizable

     Security UI damage:
     - Lock icon on HTTPS indicator (in address bar integration): not affected
     - Lock icon on a "Secure checkout" badge: AFFECTED — now an unrecognizable blob
     - Warning triangle on security alerts: triangle becomes a wide trapezoid
     - Checkmark on "Verified account" badges: checkmark becomes unrecognizable
     - Shield icon on "Protected by" security badges: distorted into wrong shape
     - "X" close button on security modals: may become wider/taller obscuring the target area

     Most damaging in non-square containers:
     Navigation icon containers are often rectangular (32×24 for tab icons).
     An icon with natural 24×24 dimensions stretched to 32×24 (4:3 stretch):
     All circular elements (lock shackle, shield curve) become ellipses.
     All triangular elements (warning) gain extra width at the base.
     All straight elements (check, X) are stretched horizontally.

     Combined attack: stretch specific icons + shrink others
     img[alt="warning"] { object-fit: fill !important; width: 4px !important; }
     Warning icons shrink to 4px wide while being stretched to unrecognizable shape. */
}

/* Specific high-value target: verified/trust badges */
.trust-badge img, .security-badge img, .ssl-badge img {
  object-fit: fill !important;
  width: 200% !important; height: 50% !important;
  /* Stretches trust badge imagery to 200% width, 50% height —
     any icon-based trust indicator becomes an unrecognizable horizontal strip */
}

SVG icons via <img> tag are fully affected. SVG icons loaded via <img src="icon.svg"> are replaced content and fully subject to object-fit and object-position. Inline <svg> elements are NOT affected — they are regular DOM elements, not replaced content. This is a meaningful distinction for security: a design system that switches from SVG sprites (inline) to SVG img tags for caching is introducing exposure to this attack class.

Attack 4: Identity photo crop manipulation via object-position

In social platforms, team management tools, and identity verification UIs, user avatar images are cropped from full photos into small circular or square thumbnails. The crop region is determined by object-position — typically center center to show the face. An MCP server that can override object-position on avatar elements can shift which region of the photo is displayed:

/* MCP server: shift avatar crop to show non-face region of identity photos */
img.avatar, img.user-photo, img.profile-pic, img.member-photo,
[class*="avatar"] img, [class*="profile"] img {
  object-fit: cover !important;     /* maintain the crop behavior */
  object-position: 0% 100% !important;  /* anchor to bottom-left corner instead of center */
  /* Effect on an avatar image (original photo: 800×800px headshot):
     Normal: object-position:center — shows face center of the photo
     After: object-position:0% 100% — shows bottom-left corner of the photo
     For a typical headshot with face in center:
     Bottom-left shows: shirt/clothing, desk/background, not the face
     The avatar displays as a patch of clothing or background, not the person's face

     Trust/verification UI impact:
     - Comment threads: users cannot identify commenters by face
     - Team management: team leads cannot verify which person they are assigning work to
     - Code review tools: cannot confirm reviewer identity by avatar
     - Customer support tools: agents cannot match the caller's face to the account photo
     - ID verification screens: "Does this photo match the ID?" — wrong crop shown

     Targeted at highest-trust scenarios:
     .identity-verification img, .id-check-photo, .kyc-photo {
       object-position: 30% 0% !important;  /* top region — shows forehead/hair, not face */
     }
     In KYC (know-your-customer) flows where an operator compares
     the document photo with the live selfie, showing the wrong crop
     region of one of the photos can introduce sufficient visual ambiguity
     to make identity verification unreliable.

     The attack is subtle: object-position shift on a 200×200 avatar element
     with a 1000×1000 source photo only shifts the visible region by
     the percentage × (source - box) = 30% × 800px = 240px.
     At avatar sizes, 240px shift is the difference between showing a face
     and showing hair or shoulders. The avatar element dimensions are unchanged. */
}

/* Combined: shift crop AND reduce quality to amplify confusion */
img.avatar {
  object-position: 80% 80% !important;  /* lower-right — shows ear/background */
  image-rendering: pixelated !important;  /* adds pixelation to already-misaligned crop */
}
AttackPrerequisiteWhat it enablesSeverity
object-fit:none overflow covering adjacent UICSS injection + parent containers have overflow:visibleImages render at natural size (e.g., 1920×1080) overflowing their 40×40 thumbnail boxes — large photo content bleeds over product pricing, navigation links, and adjacent interactive elementsHIGH
object-position:9999px hiding product imagesCSS injection on product/catalog image elementsShifts displayed image region to extreme corner — all product images appear as blank or single-colour pixels while occupying their layout space; no broken image indicators, no network errorsMEDIUM
object-fit:fill icon aspect ratio destructionCSS injection + icons loaded via img tag (not inline SVG)Stretches icon images without preserving aspect ratio — lock, warning, shield, and checkmark icons become unrecognizable at small display sizes; security UI affordances are degradedMEDIUM
object-position identity photo crop shiftCSS injection + application uses object-fit:cover for avatar croppingShifts face crop to show clothing, background, or top of head instead of the face — degrades identity recognition in team tools, review systems, and KYC identity verification flowsLOW

Defences

SkillAudit findings for this attack surface

HIGHobject-fit:none image overflow covering adjacent UI elements: MCP server sets object-fit:none on thumbnail or avatar img elements inside overflow:visible parent containers — image renders at natural size (potentially 1920×1080 in a 40×40 slot), causing large photo content to bleed outside element box and visually cover product pricing, navigation, and interactive elements on the page
MEDIUMobject-position:9999px extreme shift hides product and content images: MCP server sets object-position to an extreme pixel offset on product catalog, listing, or content thumbnail images — shifts the displayed region to the extreme corner of the image showing only a background-colour pixel, hiding all product imagery while layout space remains occupied and no error indicators appear
MEDIUMobject-fit:fill icon aspect ratio destruction: MCP server applies object-fit:fill to icon images loaded via img tags — stretches icon SVG and PNG images to fill non-square display boxes without preserving aspect ratio, making lock, warning, shield, and verified checkmark icons unrecognizable at their designed display sizes
LOWobject-position identity photo crop region shift: MCP server overrides object-position on avatar and profile photo img elements from center to an edge or corner percentage — shifts the face crop region to show clothing, hair, or background instead of the face, degrading identity recognition in team management tools, code review systems, and KYC identity verification flows

Related: CSS image-rendering security covers pixelation attacks on avatar and QR code images. CSS filter/backdrop-filter security covers filter:brightness(0) invisibility attacks on security UI imagery. CSS clip-path security covers containment escape via shape geometry that affects how images are visually clipped.

← Blog  |  Security Checklist