Fix XSS in map popups by replacing setHTML with setDOMContent
- POI popup: use DOM API with textContent (auto-escapes) instead of template literal in setHTML - Listing popup: replace renderToString + setHTML with createRoot + setDOMContent for proper React lifecycle
This commit is contained in:
parent
0a9a83507e
commit
727dd537ef
1 changed files with 17 additions and 7 deletions
|
|
@ -3,7 +3,7 @@ import mapboxgl from "mapbox-gl";
|
|||
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||
import { useEffect, useRef, useMemo, useCallback } from "react";
|
||||
import { Crosshair } from "lucide-react";
|
||||
import { renderToString } from 'react-dom/server';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import "../assets/Map.css";
|
||||
import { Metric, type ParameterValues } from "./FilterPanel";
|
||||
import { PropertyCard } from "./PropertyCard";
|
||||
|
|
@ -253,11 +253,18 @@ export function Map(props: MapProps) {
|
|||
el.style.cssText = 'width:24px;height:24px;background:#ef4444;border:2px solid white;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,0.3);cursor:pointer;';
|
||||
el.title = poi.name;
|
||||
|
||||
const popupContent = document.createElement('div');
|
||||
popupContent.style.cssText = 'padding:4px 8px';
|
||||
const nameEl = document.createElement('strong');
|
||||
nameEl.textContent = poi.name;
|
||||
const addressEl = document.createElement('span');
|
||||
addressEl.style.cssText = 'color:#666;font-size:12px';
|
||||
addressEl.textContent = poi.address;
|
||||
popupContent.append(nameEl, document.createElement('br'), addressEl);
|
||||
|
||||
const marker = new mapboxgl.Marker({ element: el })
|
||||
.setLngLat([poi.longitude, poi.latitude])
|
||||
.setPopup(new mapboxgl.Popup({ offset: 12 }).setHTML(
|
||||
`<div style="padding:4px 8px"><strong>${poi.name}</strong><br/><span style="color:#666;font-size:12px">${poi.address}</span></div>`
|
||||
))
|
||||
.setPopup(new mapboxgl.Popup({ offset: 12 }).setDOMContent(popupContent))
|
||||
.addTo(mapRef.current);
|
||||
|
||||
poiMarkersRef.current.push(marker);
|
||||
|
|
@ -352,12 +359,15 @@ export function Map(props: MapProps) {
|
|||
|
||||
const properties = heatmapRef.current._tree.search(searchBounds);
|
||||
if (properties.length > 0) {
|
||||
const listingDialogPopup = getListingDialog(properties);
|
||||
new mapboxgl.Popup()
|
||||
const container = document.createElement('div');
|
||||
const root = createRoot(container);
|
||||
root.render(getListingDialog(properties));
|
||||
const popup = new mapboxgl.Popup()
|
||||
.setLngLat([longitude, latitude])
|
||||
.setHTML(renderToString(listingDialogPopup))
|
||||
.setDOMContent(container)
|
||||
.setMaxWidth("450px")
|
||||
.addTo(mapRef.current);
|
||||
popup.on('close', () => root.unmount());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue