Skip to content

GeoLeaf Security Contract v2.0.0

Date : 21 mars 2026 Version : 2.0.0 — Audit sécurité GeoLeaf MapLibre GL JS

Ce document est la reference de securite pour la migration MapLibre. Chaque vecteur d'injection identifie, la methode de sanitisation utilisee et le fichier de test correspondant sont listes ci-dessous. Apres chaque sprint de migration, verifier que tous les vecteurs listes ont toujours un test qui passe.


1. Inventaire des vecteurs d'injection

1.1 Vecteurs DOM (injection HTML/SVG dans le DOM)

VecteurFichier sourceSanitisationFichier test
Popup POI (GeoJSON features)geojson/popup-tooltip.ts_escapeHtml() (textContent→innerHTML read)xss-injection-vectors.test.js, security.test.js
Tooltip POI (GeoJSON features)geojson/popup-tooltip.ts_escapeHtml()xss-injection-vectors.test.js
Labels GeoJSONlabels/label-renderer.tstextContent (safe)labels.test.js
Noms de couches (layer manager)layer-manager/section-renderer.tsDOMSecurity.setSafeHTML()layer-manager.test.js
Categories filtresui/filter-panel/*.tsDOMSecurity.setTextContent()filter-panel.test.js
Resultats rechercheui/content-builder/core.tsescapeHtml() par champcontent-builder.test.js
Icones toolbar mobileui/mobile-toolbar-pill.ts:258DOMSecurity.setSafeHTML() + whitelist SVGxss-injection-vectors.test.js
Labels selecteur themethemes/theme-selector-*.tstextContenttheme-selector.test.js
Barre recherche permalinkpermalink/permalink-manager.tselement.value (pas innerHTML)permalink-injection.test.js
Boutons delete POIpoi/renderers/field-renderers.tstextContentxss-prevention.test.js
Fleches navigationui/mobile-toolbar-pill.ts:271,301Constantes SVG hardcodeesN/A (safe by design)
Banniere iOS PWApwa/ios-banner.tsConstantes SVG + i18n hardcodesN/A (safe by design)

1.2 Vecteurs URL (injection via protocole ou parametres)

VecteurSanitisationFichier test
URLs POI (champs url, website, image, photo, icon)validateUrl() — whitelist protocole (http/https/data:image)security.test.js, xss-injection-vectors.test.js
Data URLs_validateDataUrl() — whitelist MIME (image/* uniquement)security.test.js
Permalink lat/lng/zoomvalidateNumber() + validateCoordinates()permalink-injection.test.js
Permalink layer IDsFiltrage string + cap 100 entreespermalink-injection.test.js
Permalink texte filtreTroncature a 200 caracteres (MAX_TEXT_LEN)permalink-injection.test.js
Permalink compact (base64)JSON.parse(atob()) + _validateRaw() re-validationpermalink-injection.test.js
Permalink ratingNumber() + validation > 0permalink-injection.test.js

1.3 Vecteurs prototype pollution

VecteurProtectionFichier test
Profil JSON config_safeAssign() bloque __proto__, constructor, prototypeprototype-pollution.test.js
Proprietes POIsanitizePoiProperties() + _safeAssign()prototype-pollution.test.js, security.test.js
Permalink compact base64JSON.parse() (safe) + _validateRaw() type checkspermalink-injection.test.js
GeoJSON feature propertiesnormalizePoiArray() via Object.create(null)prototype-pollution.test.js

2. API du module Security

Fonctions de sanitisation

FonctionEntreeGarantie sortieUsage
escapeHtml(str)String quelconqueCaracteres HTML (<, >, &, ", ') echappes en entitesContenu texte dans le DOM
escapeAttribute(str)String quelconqueMemes caracteres + ' echappesValeurs d'attributs HTML
sanitizePoiProperties(props)Objet POI brut (GeoJSON)Champs texte echappes, URLs validees, fonctions supprimeesDonnees POI externes
containsDangerousHtml(str)String quelconquetrue si patterns XSS detectesDetection/rejet rapide
stripHtml(html)String HTMLTexte brut sans aucun tagAffichage texte pur
sanitizeSvgContent(svg)String SVG bruteSVGElement sans <script>, <foreignObject>, handlers on*, javascript: hrefIcones SVG externes
parseHtmlSafely(html, tags)String HTML + whitelist tagsDocumentFragment avec uniquement les tags autorisesContenu riche controle
sanitizeHTML(el, html, opts)Element DOM + HTMLInjection sanitisee via parseHtmlSafelyWrapper principal
validateUrl(url, base, opts)String URLURL validee (protocole whiteliste) ou throwLiens, images, medias
validateCoordinates(lat, lng)NombresTuple [lat, lng] valide ou throwCoordonnees carte
validateNumber(val, min, max)Valeur quelconqueNombre fini dans [min, max] ou nullParametres numeriques

Fonctions DOM securisees

FonctionEntreeGarantieUsage
DOMSecurity.setTextContent(el, text)Element + texteAssignation via textContent (jamais innerHTML)Tout texte non-HTML
DOMSecurity.setSafeHTML(el, html, tags?)Element + HTML + whitelist optionnellePasse par Security.sanitizeHTML(), fallback textContentHTML controle
DOMSecurity.clearElement(el)ElementSuppression enfants via removeChild loopNettoyage DOM
DOMSecurity.createElement(tag, attrs, children)Tag + attributs + enfantsElement cree via DOM API safeCreation elements
DOMSecurity.createSVGIcon(w, h, path, opts)Dimensions + path dataSVGElement via createElementNS (pas innerHTML)Icones SVG internes

Protection CSRF

FonctionDescription
CSRFToken.init()Genere un token crypto-random (32 octets, base64url)
CSRFToken.getToken()Retourne le token courant, regenere si expire
CSRFToken.validateToken(token)Validation constante-time du token
CSRFToken.rotateToken()Rotation manuelle + event geoleaf:csrf:rotated
CSRFToken.addTokenToHeaders(opts)Ajoute X-CSRF-Token aux headers
CSRFToken.addTokenToForm(form)Ajoute <input type="hidden" name="csrf_token">
CSRFToken.setSecureCookie(name, val, opts)Cookie avec Secure, SameSite, HttpOnly

3. Patterns dangereux — resultat audit

PatternOccurrencesStatut
eval()0OK
new Function(0OK
setTimeout(string, ...)0OK
setInterval(string, ...)0OK
document.write0OK
insertAdjacentHTML0OK
outerHTML (ecriture)0OK (1 lecture dans label-renderer.ts — safe)
innerHTML (total)31 dans 14 fichiersTous safe — voir section 3.1

3.1 Classification innerHTML

  • Escape pattern (textContent→innerHTML read) : security/index.ts, poi/normalizers.ts, geojson/popup-tooltip.ts, renderers/abstract-renderer.ts — 5 occ.
  • DOMSecurity.setSafeHTML wrapper : utils/helpers/dom-helpers.ts, utils/general/dom-helpers.ts, ui/mobile-toolbar-pill.ts:258 — 16 occ.
  • Clearing (innerHTML = "") : ui/mobile-toolbar.ts, ui/mobile-toolbar-sheet.ts — 2 occ.
  • Constantes hardcodees (SVG/HTML entities) : pwa/ios-banner.ts, themes/theme-selector-primary.ts, ui/mobile-toolbar-pill.ts:271,301 — 7 occ.
  • Commentaire seul : ui/filter-panel/lazy-loader.ts — 1 occ.

4. Compatibilite CSP (Content Security Policy)

Directives minimales requises pour GeoLeaf + MapLibre GL JS v5 :

DirectiveValeurRaison
script-src'self'Zero eval/Function/inline scripts. Workers meme-origine.
style-src'self' 'unsafe-inline'element.style.* dynamique (15 occ. dans 6 fichiers) + MapLibre GL JS le requiert
img-src'self' data: https:Data URLs pour markers/icones, tuiles HTTPS
connect-src'self' https:Fetch GeoJSON, profils, URLs de tuiles
worker-src'self' blob:GeoJSON worker via blob URLs (worker-manager.ts)
font-src'self'Aucune fonte externe chargee par le core
default-src'self'Fallback securise

Points notables :

  • unsafe-eval non requis — confirme pour MapLibre GL JS v5 et GeoLeaf
  • unsafe-inline requis pour style-src uniquement — contrainte MapLibre GL JS (manipulation element.style)
  • Apres migration MapLibre : verifier si MapLibre GL exige des directives supplementaires (WebGL, workers)

5. Checklist migration MapLibre

A verifier apres chaque sprint de migration :

  • [ ] Popup rendering passe encore par escapeHtml ou equivalent MapLibre
  • [ ] Tooltip rendering passe encore par escapeHtml
  • [ ] Markers MapLibre GL ne contournent pas DOMSecurity
  • [ ] Labels MapLibre GL utilisent textContent (pas innerHTML)
  • [ ] Nouvelles surfaces d'injection MapLibre documentees dans ce contrat
  • [ ] sanitizeSvgContent couvre les icones MapLibre si format SVG
  • [ ] validateUrl couvre les URLs de tuiles MapLibre
  • [ ] CSP : verifier si MapLibre GL exige unsafe-eval ou unsafe-inline supplementaire
  • [ ] Prototype pollution : verifier les nouveaux points d'entree de configuration MapLibre
  • [ ] Tous les tests __tests__/security/ passent apres chaque module migre

6. Fichiers de test securite

FichierTestsCouverture
security/security.test.js52escapeHtml, escapeAttribute, validateUrl, sanitizePoiProperties
security/csrf-token.test.js23CSRFToken lifecycle complet
security/security-comprehensive.test.js~60Couverture etendue escapeHtml, coordinates
security/security-extended.test.js~50sanitizeSvgContent, validateNumber, parseHtmlSafely
security/security.esm.test.js~70Tests ESM de toutes les fonctions
security/prototype-pollution.test.js16_safeAssign, normalizePoiArray, GeoJSON properties
security/xss-prevention.test.js~20Patterns DOM (textContent vs innerHTML)
security/xss-injection-vectors.test.js~90Sprint 5 — 16 payloads OWASP × 10 vecteurs
security/permalink-injection.test.js~30Sprint 5 — Injection URL params + compact mode
security/file-validator.test.js~25Upload securise (taille, extension, MIME)
utils/dom-security.test.js24DOMSecurity wrapper complet

Total : ~440 tests securite

Released under the MIT License.