CIBLE RésaLocale
DÉFAUTS INJECTÉS 10
GRAINE 42
RÉSEAU 127.0.0.1 SEUL

Enregistrement · découverte automatique de bugs

Blackbox

Il explore une application web avec Playwright, invente ses scénarios de test, les rejoue dans un environnement neuf, et ne garde que les bugs qui se reproduisent.

Piste 01 · le moteur

De la page d'accueil au test de régression.

01

Exploration

Liens, formulaires, trafic fetch/XHR, doc d'API.

explorer.py
02

Génération

54 scénarios activés selon les parcours trouvés.

generator.py
03

Exécution

Nouveau serveur, nouvelle base SQLite, à chaque fois.

executor.py
04

Oracles

Chaque verdict renvoie à un critère AC de la spec.

oracles.py
05

Confirmation

Rejeu : bug confirmé ou simple suspicion.

--replays
06

Régression

Un test pytest par bug confirmé.

regression.py

Piste 02 · isolation

Le moteur ne peut pas lire les réponses.

Survolez les dossiers interdits. Un hook d'audit Python, impossible à retirer, bloque tout accès, et toute connexion hors boucle locale.

blackbox/ne connaît que spec/ + targets/ + ce qu'il observe en HTTP
sut/code de l'application
reference/vérité terrain D01…D10
evaluation/seul lecteur de reference/
Internetsocket non-loopback
# blackbox/guard.py (principe)
def _audit(event, args):
    if event in ("open", "os.listdir", "import"):
        if touches(args, FORBIDDEN):
            raise IsolationViolation(args)
    if event == "socket.connect":
        if not is_loopback(args):
            raise IsolationViolation(args)

sys.addaudithook(_audit)
# + Playwright bloque tout hors localhost

Piste 03 · rejouez l'expérience

  PowerShell — blackbox
> python -m evaluation.experiment --id EXP-002 --seed 42
Appuyez sur « Lancer » pour rejouer le journal.
Défauts retrouvés : 0/10

Piste 04 · boîte noire relue · EXP-002

7 critères fixés avant le code. 7 atteints.

/10
défauts retrouvés
objectif ≥ 7/10
précision · 0 faux positif
objectif ≥ 0,90 · EXP-001 : 0,93
bugs confirmés, tests valides 27/27
objectif ≥ 90 %
min
durée totale
objectif < 15 min

Aussi atteints : 0 violation d'isolation, 60/60 scénarios avec statut final et raison, plan identique pour une même graine. Le protocole (docs/PROTOCOLE.md) a été commité en premier dans Git, avant toute ligne du moteur.

Piste 05 · le répertoire d'attaques

Penser comme un utilisateur pénible.

Valeurs limites · séjour de 0 nuitCapacité · une personne de tropDates passées · validation navigateur contournée Intervalles d'Allen · chevauchement englobantPrix · taxe avant remiseCodes promo · réutilisation Annulation · puis nouvelle réservationIDOR · annuler la réservation d'autruiInjection · XSS stockée dans la note Authentification · comptesEntrées malformées · date inexistante → 500Fuzz · Hypothesis

Dates relatives ($today+N), plan déterministe pour une graine donnée (empreinte SHA-256).

Piste 06 · la pièce à conviction

Chaque bug confirmé devient un test qui échoue.

  • Relance un serveur neuf et rejoue le scénario.
  • Échoue sur la version boguée, passe avec SUT_FIXES=all.
  • Docstring : constat, attendu, observé, étapes.
# exemple simplifié, inspiré de D07
def test_cancel_other_users_booking(server):
    """Constat : un compte annule la réservation d'autrui.
    Attendu  : AC-09, 403 et réservation intacte.
    Observé  : 200, réservation annulée.
    Étapes   : alice réserve → bob POST /cancel/<id>"""
    alice, bob = server.actor("alice"), server.actor("bob")
    booking = alice.book(start="$today+3", nights=2)
    r = bob.post(f"/cancel/{booking.id}")
    assert r.status == 403
    assert alice.get(booking).status == "active"

Fin d'enregistrement

Un bug n'existe que s'il se reproduit.

Python · Playwright · pytest · Hypothesis · Flask + SQLite pour la cible de démonstration