← RETOUR À L'INDEX
/tutoriels/ infrastructure / audit-pré-publication-portfolio-astro-+-cloudflare.md

Audit pré-publication portfolio Astro + Cloudflare

Checklist complète avant de mettre en ligne un site Astro sur Cloudflare Pages : agent-readiness, sécurité HTTP, supply chain, exposition PII, SEO, a11y.

CAT · INFRA LECTURE · 6 min PUBLIÉ · 2026-05-15

[TUTO-15] Audit pré-publication portfolio Astro + Cloudflare

Objectif

Passer une grille d’audit en 6 catégories avant de mettre un site public en ligne. L’ordre est délibéré : les audits bloquants (PII, sécurité, supply chain) passent avant les audits de confort (agent readiness, SEO, performance). Un seul point 🔴 non validé = ne pas mettre en ligne.

Prérequis

  • Site Astro avec pnpm, déployé sur Cloudflare Pages via Cloudflare Tunnel
  • Domaine DNS géré par Cloudflare
  • exiftool installé (sudo apt install libimage-exiftool-perl)

Étape 1 — Exposition PII et données personnelles 🔴 Bloquant

Scanner le repo git en entier (historique compris) :

# Emails, tokens, clés dans l'historique git
git log --all --full-history -- . | xargs git show --stat 2>/dev/null | head -50
git log -p --all | grep -iE "(email|@gmail|@proton|token|secret|ghp_|sk-)" | head -20

# EXIF des images livrées
find public/ -name "*.jpg" -o -name "*.png" -o -name "*.webp" \
  | xargs exiftool -Author -Creator -Comment -GPS 2>/dev/null | grep -v "^$"

# Emails en clair dans le HTML généré
grep -rn "@" dist/ --include="*.html" | grep -v "node_modules"

⚠️ Sécurité : un email en clair dans le HTML est scrappable par n’importe quel bot. C’est acceptable pour un portfolio de contact — c’est un risque spam conscient, pas une fuite. En revanche un token ou une clé API dans le HTML ou dans le git log = rotation immédiate avant toute mise en ligne.

Checklist ☑ :

  • git log -p → aucun secret dans l’historique
  • EXIF images → aucune donnée GPS ou identifiant personnel
  • Décision documentée sur les emails en clair (intentionnel ou encodé)

Étape 2 — Sécurité HTTP 🔴 Bloquant

Vérifier les headers de réponse (avec le site déjà déployé sur Cloudflare Pages) :

TARGET="https://ton-domaine.fr"

# Headers de sécurité
curl -sI "$TARGET" | grep -iE \
  "(content-security|x-frame|x-content-type|strict-transport|permissions-policy|referrer)"

# Vérification avec securityheaders.com
curl -s "https://securityheaders.com/?q=${TARGET}&followRedirects=on" \
  | grep -oE 'grade-[A-F+]' | head -1

Vérifier dans public/_headers (Cloudflare Pages) que ces directives sont présentes :

  • Content-Security-Policy — inclure script-src restrictif
  • X-Frame-Options: DENY
  • X-Content-Type-Options: nosniff
  • Strict-Transport-Security: max-age=31536000; includeSubDomains
  • Permissions-Policy: camera=(), microphone=(), geolocation=()

⚠️ Sécurité : si un script tiers est chargé (ex: Cloudflare Insights Beacon), son domaine doit apparaître dans script-src. Un script externe hors CSP est silencieusement bloqué mais aucune alerte n’est générée — piège classique. Challenge : est-ce que les analytics Cloudflare sont vraiment nécessaires si le dashboard Tunnel donne déjà les métriques de trafic ?

Vérifier l’exposition de l’IP origin Hetzner :

# L'IP Hetzner ne doit JAMAIS apparaître dans les headers Cloudflare
curl -sI "$TARGET" | grep -iE "(server|via|x-powered|cf-ray)"

# Vérification DNS : seul Cloudflare doit être résolvable
dig +short ton-domaine.fr
# Attendu : IPs Cloudflare (104.x.x.x ou 172.x.x.x) — jamais l'IP Hetzner directe

⚠️ Sécurité : si vault.ton-domaine.fr et ton portfolio partagent le même VPS Hetzner, une fuite d’IP origin sur le portfolio expose aussi l’endpoint MCP du vault. Ces deux sous-domaines partagent la même surface d’attaque — auditer ensemble.

Checklist ☑ :

  • securityheaders.com → grade A ou A+
  • IP Hetzner absente des headers et DNS public
  • Script tiers (Beacon CF) : décision intentionnelle documentée

Étape 3 — Supply chain et dépendances 🔴 Bloquant

# Audit des vulnérabilités (pnpm, pas npm audit)
pnpm audit --audit-level moderate

# Scripts tiers chargés depuis CDN externes dans le HTML généré
grep -rn 'src="https://' dist/ --include="*.html" | grep -v "cloudflare\|fonts.googleapis"

# Vérifier que les versions sont fixées (pas de ^ ou ~ sur les dépendances critiques)
cat package.json | jq '.dependencies, .devDependencies' | grep -E '"\^|"~'

⚠️ Sécurité : chaque dépendance avec ^ peut être mise à jour automatiquement par pnpm install vers une version mineure qui peut introduire du code malveillant (supply chain attack). Pour un portfolio statique public, c’est un risque modéré mais documenté. Pinner les versions critiques.

Checklist ☑ :

  • pnpm audit → 0 vulnérabilités high/critical
  • Scripts CDN tiers identifiés et justifiés

Étape 4 — Agent readiness 🟠

TARGET="https://ton-domaine.fr"

# robots.txt
curl -s "$TARGET/robots.txt"
# Attendu : User-agent: *, Sitemap: https://...

# sitemap.xml
curl -sI "$TARGET/sitemap.xml" | grep "HTTP/"
# Attendu : HTTP/2 200

# llms.txt
curl -sI "$TARGET/llms.txt" | grep "HTTP/"
# Attendu : HTTP/2 200 (à créer si absent)

# Vérification complète → lancer isitagentready.com après déploiement

Créer public/llms.txt si absent. Format minimal :

# [Prénom Nom] — Portfolio
> Portfolio professionnel d'architecte solutions.

## Sections
- /tutos/ : tutoriels techniques open source
- /about/ : profil et expérience

## Contact
- Email : [email]
- GitHub : [url]

⚠️ llms.txt n’est pas un standard officiel mais devient un signal fort pour les agents qui crawlent le web. Le négliger n’est pas bloquant mais c’est une occasion manquée si le portfolio cible une audience tech.

Checklist ☑ :

  • robots.txt : présent, Sitemap référencé
  • sitemap.xml : présent et valide
  • llms.txt : présent
  • isitagentready.com passé après déploiement

Étape 5 — SEO 🟡

# Balises meta dans les pages HTML générées
grep -n "og:title\|og:description\|og:image\|twitter:card" dist/index.html

# Alt text sur les images
grep -n '<img' dist/index.html | grep -v 'alt="'
# Attendu : 0 résultat (toutes les images ont un alt)

# Canonical URLs
grep "canonical" dist/index.html

Checklist ☑ :

  • Open Graph : title, description, image présents
  • <img> sans alt : 0 occurrence
  • Canonical URL défini

Étape 6 — Performance 🟡

Après déploiement uniquement :

# PageSpeed Insights API (ou manuellement sur web.dev/measure)
curl "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://ton-domaine.fr&strategy=mobile" \
  | jq '.lighthouseResult.categories | {perf: .performance.score, a11y: .accessibility.score}'

Checklist ☑ :

  • Score performance mobile > 90
  • Score a11y > 90

Étape 7 — Ordre d’exécution recommandé

OrdreÉtapeBloquant ?
1PII et historique git🔴 Oui
2Sécurité HTTP + IP origin🔴 Oui
3Supply chain pnpm🔴 Oui
4Agent readiness🟠 Avant live
5SEO🟡 Post-live OK
6Performance🟡 Post-live OK

Un seul point 🔴 non validé = ne pas mettre en ligne.


Dépannage

ProblèmeVérification
pnpm audit retourne des erreurs réseauVérifier le proxy ou utiliser pnpm audit --no-optional
securityheaders.com ne charge pas les headersTester avec curl -sI directement
dig retourne l’IP HetznerLe proxy Cloudflare n’est pas activé (orange cloud dans DNS)
exiftool non disponiblesudo apt install libimage-exiftool-perl

Références

VR · 2026-05-15 · vraffin.dev FIN DU DOCUMENT