CommunityRédaction et éditiongithub.com

trailofbits/validation-post-correctif

Valide les correctifs de sécurité avec des preuves reproductibles de la version de base par rapport à la version corrigée, y compris les exploits originaux, les variantes de cause racine, la préservation du comportement, les régressions et les nouvelles défaillances de sécurité introduites.

Qu'est-ce que validation-post-correctif ?

Cette compétence (skill) pour agents IA, comme Claude Code, Cursor ou Codex, permet de valider rigoureusement un correctif de sécurité après sa création, mais avant son acceptation ou son intégration. Elle génère un plan de validation structuré qui exécute une série de vérifications (exploit, variante, comportement, régression, sécurité, suite de tests) sur les versions vulnérable et corrigée du code. Le processus produit un rapport détaillé avec des preuves d'exécution, identifiant les échecs reproductibles, les lacunes de couverture et les cas où le correctif pourrait être incomplet ou introduire de nouveaux problèmes. L'agent utilise un exécuteur Python isolé qui garantit la reproductibilité en épinglant les commits, en randomisant l'ordre d'exécution et en empêchant les vérifications de détecter quelle version est testée. Cette approche est utilisée pour valider les correctifs humains ou générés par IA, dans n'importe quel langage, en se concentrant sur les invariants de sécurité et en exigeant que chaque vérification prouve son exécution réelle via un marqueur spécifique.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/trailofbits/skills/tree/main/plugins/post-patch-validation/skills/post-patch-validation

Installed? Explore more Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Validation post-correctif

Valider un correctif de sécurité par rapport au bogue signalé et au code environnant qu'il affecte. Fournissez à l'auteur du correctif des échecs reproductibles à corriger et identifiez ce qui nécessite encore des tests. Appliquez les mêmes vérifications aux correctifs humains et aux correctifs générés par des agents. Le diff, l'auteur, l'implémentation en amont et la preuve de concept originale ne peuvent à eux seuls établir la correction.

Quand l'utiliser

  • Un correctif de sécurité, un commit de correction, un fichier de correctif ou une pull request existe déjà.
  • Un correctif généré par une IA nécessite une validation avant une relecture humaine ou une fusion.
  • Un correctif peut couvrir un chemin d'exploitation tout en ignorant des variantes de la même cause racine.
  • Un correctif de sécurité peut altérer un comportement légitime ou introduire une nouvelle vulnérabilité.
  • Un auteur de correctif a besoin d'échecs concrets et de lacunes de couverture avant une autre révision.

Quand NE PAS l'utiliser

  • Aucun correctif n'existe encore ; utilisez d'abord la découverte de vulnérabilité ou l'implémentation du correctif.
  • La tâche consiste à examiner une constatation d'audit par rapport à un rapport sans exécuter de preuves de correctif.
  • La tâche consiste uniquement à convertir une constatation en un test permanent du projet.
  • La cible est distante ou en production. Cette compétence exécute uniquement du code local et des tests.
  • L'utilisateur n'a pas autorisé l'exécution du code ou de la suite de tests du dépôt.

Démarrage rapide

  1. Épinglez la base vulnérable et l'entrée corrigée. Préférez les commits immuables. Pour un travail non commité, créez d'abord un fichier de correctif binaire ; ne validez pas dans l'arbre de travail de l'utilisateur.

  2. Échafaudez un plan épinglé :

    uv run {baseDir}/scripts/post_patch_validation.py scaffold \
      --repo . \
      --base-ref <ref-vulnérable> \
      --patched-ref <ref-corrigée> \
      --finding-id <id-stable> \
      --finding-summary "<cause racine et impact>" \
      --evidence-level runtime \
      --output post-patch-validation/plan.json
    

    Utilisez --patch-file <chemin> au lieu de --patched-ref pour un artefact de correctif. Choisissez le niveau de preuve le plus élevé honnête : source pour les invariants source/correctif uniquement, build lorsque le code cible est compilé ou analysé mais que le comportement signalé n'est pas exécuté, ou runtime lorsque les vérifications exécutent le comportement signalé et ses assertions de sécurité.

  3. Inspectez la constatation, le diff, les appelants, les chemins frères, les chemins de nettoyage/d'erreur et les tests existants. Remplissez checks dans le plan généré. Exécutez print-schema pour le schéma structurel :

    uv run {baseDir}/scripts/post_patch_validation.py print-schema
    
  4. Exécutez validate-plan pour la validation complète, y compris la couverture, les restrictions de commande et les entrées épinglées, avant d'exécuter le code :

    uv run {baseDir}/scripts/post_patch_validation.py validate-plan \
      --plan post-patch-validation/plan.json
    
  5. Exécutez le plan de preuve :

    uv run {baseDir}/scripts/post_patch_validation.py run \
      --plan post-patch-validation/plan.json \
      --output post-patch-validation/results
    
  6. Rapportez result.json, report.md, le niveau de preuve et l'assessment complet. Renvoyez chaque constatation à l'auteur du correctif avec son ID de vérification, son assertion et les journaux sauvegardés. Identifiez chaque lacune de validation séparément, y compris les lacunes qui coexistent avec des constatations valides. Après que l'auteur a révisé le correctif, épinglez les nouvelles entrées et sauvegardez une nouvelle exécution de validation. Conservez les preuves antérieures. Les vérifications fournies qui réussissent nécessitent toujours une relecture humaine avant acceptation.

Contrat de preuve

L'exécuteur rejette les plans incomplets. Fournissez au moins une vérification de chaque type :

TypeObservation requise
controlLe harnais inoffensif réussit sur la base et le correctif
exploitL'assertion de sécurité d'origine échoue sur la base et réussit sur le correctif
variantUne variante distincte de la cause racine échoue sur la base et réussit sur le correctif
behaviorLe comportement non affecté réussit avec une sortie sélectionnée identique octet par octet
regressionLa vérification de régression non ciblée réussit sur les deux révisions
securityLa vérification de vulnérabilité adjacente/nouvelle réussit sur la base et le correctif
suiteLa suite de tests existante, le désinfectant ou la campagne de fuzzing déterministe réussit sur le correctif

Les commandes sont des tableaux argv, jamais des chaînes shell. Placez la configuration complexe dans un script vérifié ou un artefact de plan et invoquez-le avec {plan_dir}. L'exécuteur fixe les entrées de locale/fuseau horaire/graine de hachage, exécute les vérifications dans l'ordre lexical des ID, enregistre la sortie standard/erreur brute et ne modifie jamais l'arbre de travail d'origine. Le timeout_seconds de chaque vérification est par défaut de 300 et accepte des entiers de 1 à 3600. Dépasser le délai d'attente laisse une lacune de validation. Un délai d'attente seul n'établit pas une régression. Chaque plan contient également un tableau submodules trié ([] quand il n'y en a pas). L'échafaudage déduit les Gitlinks affectés à partir de l'inventaire des fichiers modifiés. L'exécuteur initialise ces commits épinglés à partir des objets de module Git existants du dépôt source, jamais à partir des URL réseau .gitmodules ; initialisez ou récupérez-les dans le dépôt source avant la validation.

Les vérifications d'exploit et de variante doivent prouver qu'elles ont été exécutées

Un code de sortie non nul ne signifie pas que la vulnérabilité a été reproduite. Une erreur d'importation, une construction échouée, une dépendance manquante et une assertion de sécurité échouée se terminent tous par un code non nul et sont indistinguables pour l'exécuteur. Chaque vérification exploit et variant doit imprimer et vider PPV_REACHED immédiatement avant d'évaluer son assertion, sur les deux révisions :

"argv": ["python3", "-c", "import app; value = app.render('<'); print('PPV_REACHED', flush=True); assert value == '&lt;'"]

Le jeton est également dans l'environnement en tant que PPV_REACHED_MARKER. Il doit atterrir sur la sortie standard, sur sa propre ligne. La sortie d'erreur n'est pas analysée, car une trace d'erreur SyntaxError de Python fait écho à la source incriminée et satisferait autrement la vérification pour un harnais qui n'a rien exécuté. Une exécution sans cela laisse une lacune marker_missing. Les constatations indépendantes d'autres vérifications restent dans le résultat. Videz explicitement : un harnais dont la charge utile plante ou appelle _exit perd la sortie mise en mémoire tampon et renonce à ses propres preuves.

Ces vérifications s'exécutent également en aveugle par rapport au côté. {side} n'est pas développé pour elles, PPV_SIDE est absent de leur environnement, le répertoire de vérification est nommé aléatoirement et le validateur de plan rejette toute vérification exploit ou variant dont argv ou env mentionne l'un ou l'autre. Une assertion qui peut voir sur quelle révision elle se trouve peut affirmer cela au lieu du code, ce qui est le moyen le moins cher possible de simuler une reproduction suivie d'un correctif.

Environnement

Les vérifications s'exécutent sous un environnement minimal fixe : PATH, HOME et une poignée de clés temporaires/utilisateur, plus LANG/LC_ALL=C, TZ=UTC, PYTHONHASHSEED=0, NO_COLOR, TERM=dumb. Tout le reste dans l'environnement de l'appelant est supprimé. Les chaînes d'outils qui ont besoin de plus l'obtiennent explicitement :

uv run {baseDir}/scripts/post_patch_validation.py run \
  --plan post-patch-validation/plan.json \
  --output post-patch-validation/results \
  --allow-env JAVA_HOME --allow-env CARGO_HOME

Les noms et valeurs transmis sont enregistrés dans result.json. Une variable demandée qui n'est pas définie est une erreur, pas une chaîne vide. Deux classes sont refusées catégoriquement : les noms qui ressemblent à des informations d'identification (*SECRET*, *TOKEN*, *API_KEY*, …), car la valeur serait écrite dans le résultat ; et les noms qui modifient ce qui s'exécute (LD_PRELOAD, BASH_ENV, NODE_OPTIONS, GIT_SSH_COMMAND, …), car ces variables peuvent modifier le code qui s'exécute. Les variables fixes de l'exécuteur et chaque nom PPV_* sont également réservés et ne peuvent pas être transmis.

Les espaces réservés développés dans argv et les valeurs env par vérification : {checkout} (la révision en cours de test), {plan_dir} (une copie isolée des artefacts du plan pour cette seule invocation), {scratch} (un répertoire opaque frais pour cette seule invocation de vérification) et {side} (base ou patched, et non disponible pour les vérifications exploit/variant). Les mêmes valeurs arrivent sous les noms PPV_CHECKOUT, PPV_PLAN_DIR, PPV_SCRATCH, PPV_SIDE et PPV_CASE_ID. Écrivez uniquement sous {scratch} ; le chemin du répertoire de preuves n'est pas passé aux vérifications. Les invocations de base et corrigées ne partagent pas les racines de travail, de plan ou de scratch gérées par l'exécuteur. Après la sortie de chaque invocation, son arbre scratch est archivé sous le chemin déterministe results/scratch/<id-de-vérification-et-côté>, sa copie de plan privée est supprimée et chaque élément argv lisible qui résout un fichier est haché dans argv_files. Les fichiers à l'intérieur des racines de plan ou de vérification isolées sont en outre conservés sous results/helpers/<sha256> jusqu'à 16 Mio ; l'enregistrement explique pourquoi tout autre fichier n'a pas été archivé. Utilisez un répertoire dédié pour plan.json : ses fichiers et répertoires frères sont copiés dans {plan_dir} de chaque invocation. Gardez le code d'assistance sous le répertoire checks/ de ce répertoire ou vérifié dans le dépôt cible afin que ses octets soient examinables. Le plan machine contenant les épingles de commit, le répertoire de sortie actuel et les arbres de résultats antérieurs détectés sont exclus ; les liens symboliques sont rejetés. L'instantané propre ne reste que dans la mémoire de l'exécuteur, et les côtés exploit/variant s'exécutent dans un ordre aléatoire tandis que les noms de fichiers de preuve restent déterministes. La sortie standard/erreur utilise des descripteurs de capture anonymes ou nommés aléatoirement et sont copiés vers les fichiers de preuve nommés uniquement après la fin du processus fils, de sorte que l'inspection du descripteur de fichier ne peut pas divulguer l'étiquette du côté.

Cet isolement n'est pas un bac à sable hôte : les vérifications s'exécutent avec les privilèges de l'appelant et un assistant malveillant pourrait utiliser un état externe arbitraire ou déduire délibérément la révision à partir de la source ou des métadonnées Git. Inspectez les artefacts d'assistance adressés par contenu et utilisez un bac à sable OS/conteneur lorsque le code de vérification lui-même n'est pas fiable.

Les arbres de travail de validation actifs sont verrouillés par Git avec des jetons de propriétaire aléatoires soutenus par des verrous de fichiers noyau, de sorte qu'un autre validateur simultané ne peut pas les élaguer et la réutilisation du PID ne peut pas usurper un propriétaire. Si l'exécuteur est tué de force, l'exécution suivante déverrouille les enregistrements de propriétaires obsolètes. Pour une récupération manuelle, inspectez git worktree list, puis utilisez git worktree unlock <chemin> et git worktree remove --force <chemin> (ou git worktree prune après la suppression du chemin).

Lisez evidence-model.md lors de la conception de la couverture, de la sélection des variantes ou de l'interprétation des constatations et des lacunes de validation. Ne le lisez pas pour une exécution CLI de routine.

Règles de couverture

  • Dérivez les variantes de la cause racine, pas des mutations cosmétiques de la charge utile d'origine.
  • Énumérez les sites d'appel frères, les rappels/sorties alternatifs, les chemins d'erreur, le démontage, la propriété, la sérialisation et les valeurs limites touchés par le correctif.
  • Faites en sorte que chaque test d'exploit ou de variante affirme le comportement sûr. Il doit échouer sur la base vulnérable ; un test qui réussit sur les deux révisions ne prouve rien concernant la correction. Lisez la sortie d'erreur du côté de base et confirmez que l'échec est l'assertion que vous avez écrite, pas un harnais qui n'est jamais arrivé là.
  • Limitez les assertions d'exploit et de variante à l'invariant de sécurité. Testez la vivacité, les types/messages d'erreur exacts, le timing et la compatibilité séparément en tant que vérifications behavior ou regression ; sinon, un changement de contrat sans rapport peut se faire passer pour une preuve que la vulnérabilité persiste.
  • Gardez le harnais control inoffensif et faites-lui exercer le composant modifié. Il établit que le harnais fonctionne sur les deux révisions. Les contrôles échoués laissent des lacunes et empêchent d'attribuer d'autres échecs au correctif. Les observations brutes restent disponibles pour examen.
  • Utilisez behavior uniquement pour un comportement qui doit rester inchangé. La comparaison exacte de la sortie est délibérée ; déplacez les valeurs instables derrière un harnais de test déterministe au lieu de les normaliser dans la prose.
  • Faites en sorte que les vérifications security réussissent sur la base vulnérable avant de traiter un échec corrigé comme nouvellement introduit. Une base de référence échouée laisse l'attribution non résolue.
  • Ne modifiez pas le correctif pendant la validation. Renvoyez les échecs à l'auteur du correctif et commencez une nouvelle exécution fraîchement épinglée.

Lecture du résultat

Le schéma result.json 2.0 contient une assessment avec status, findings, gaps et human_review_required. Le statut est complete lorsque toutes les vérifications requises ont produit des preuves utilisables, même si certaines vérifications ont trouvé des échecs. Le statut est incomplete lorsqu'il reste une lacune. Les constatations nomment l'ID de vérification, le type de vérification et l'attente échouée. Les lacunes nomment l'ID de vérification et la preuve manquante, avec un ID de vérification nul pour les problèmes au niveau de l'exécution tels que les échecs de nettoyage.

Les vérifications de suite s'exécutent d'abord sur la révision corrigée. Un échec terminé déclenche la même vérification sur la base de référence. Si la base de référence réussit, signalez l'échec après le correctif. Si les deux échouent, conservez les deux journaux et signalez que l'attribution n'est pas résolue. Ne supposez pas que des codes de sortie correspondants signifient le même échec.

L'exécuteur se termine avec le code 0 pour les vérifications complètes sans constatation, 1 pour les vérifications complètes avec constatation, 10 pour une validation incomplète et 64 pour des entrées invalides. Lisez l'artefact même après le code de sortie 10 : il peut contenir des constatations valides accompagnées de lacunes. Les preuves source ou de construction ne peuvent pas établir un comportement d'exécution. Indiquez le niveau de preuve à côté de tout résultat réussi.

Workflow dynamique Claude

Claude Code expose le workflow intégré sous le nom /post-patch-validation:validate-patch. Pour passer des entrées structurées via l'outil Workflow, utilisez le nom sans barre oblique initiale :

Workflow({
  name: 'post-patch-validation:validate-patch',
  args: {
    finding: '<texte de constatation ou chemin local>',
    baseRef: '<ref-vulnérable>',
    patchRef: '<ref-corrigée>',
    workdir: 'post-patch-validation',
  },
})

Utilisez patchFile au lieu de patchRef le cas échéant. Le workflow utilise des lentilles de couverture fixes pour proposer des vérifications et un exécuteur fixe pour exécuter cette compétence. Les agents peuvent rédiger des artefacts de test. L'exécuteur Python enregistre les constatations et les lacunes, et les réviseurs signalent séparément les problèmes de couverture ou de preuve. NEEDS_REPAIR renvoie les échecs valides même lorsque d'autres vérifications ont laissé des lacunes. BLOCKED signifie que la preuve est incomplète sans un échec valide. Les vérifications réussies avancent vers READY_FOR_HUMAN_REVIEW uniquement après que les deux examens de preuve ont approuvé, sinon REVIEW_REQUIRED. Le workflow ne peut pas poser de questions après le lancement, alors transmettez toutes les entrées dès le départ.

Rationalisations à rejeter

RationalisationRéponse requise
"Le correctif semble correct"Spécifiez quelle assertion pourrait échouer sur la base vulnérable ; nous ne validons pas les correctifs en fonction de leur apparence."
"Les tests de la suite existante passent"Les tests de la suite n'exercent pas le cas de sécurité signalé ; prouvez-le avec un exploit ou une variante qui échoue sur la base."
"Ce n'est pas le bon endroit pour corriger"Proposez l'endroit ; validez-le après avoir implémenté le correctif à cet endroit."
"Un réviseur humain a déjà approuvé"La relecture humaine est orthogonale à la preuve d'exécution ; validez d'abord, puis soumettez pour relecture."
"La vulnérabilité n'est pas exploitable"Spécifiez l'invariant de sécurité violé et prouvez qu'il est rétabli par le correctif."
"Le test échoue pour une raison non liée"Isolez l'assertion de sécurité ; si elle ne peut pas être isolée, signalez la lacune et la raison."
"Nous avons un autre système de validation"Chaque système a des hypothèses de couverture différentes ; exécutez les deux et comparez les lacunes."

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

trailofbits/address-sanitizer

AddressSanitizer detects memory errors during fuzzing. Use when fuzzing C/C++ code to find buffer overflows and use-after-free bugs.

trailofbits/aflpp

AFL++ is a fork of AFL with better fuzzing performance and advanced features. Use for multi-core fuzzing of C/C++ projects.

trailofbits/agentic-actions-auditor

Audits GitHub Actions workflows for security vulnerabilities in AI agent integrations including Claude Code Action, Gemini CLI, OpenAI Codex, and GitHub AI Inference. Detects attack vectors where attacker-controlled input reaches AI agents running in CI/CD pipelines, including env var intermediary patterns, direct expression injection, dangerous sandbox configurations, and wildcard user allowlists. Use when reviewing workflow files that invoke AI coding agents, auditing CI/CD pipeline security for prompt injection risks, or evaluating agentic action configurations.

trailofbits/algorand-vulnerability-scanner

Scans Algorand smart contracts for 11 common vulnerabilities including rekeying attacks, unchecked transaction fees, missing field validations, and access control issues. Use when auditing Algorand projects (TEAL/PyTeal).

trailofbits/ask-questions-if-underspecified

Clarify requirements before implementing. Use when serious doubts arise.

trailofbits/atheris

Atheris is a coverage-guided Python fuzzer based on libFuzzer. Use for fuzzing pure Python code and Python C extensions.

trailofbits/audit-augmentation

Augments Trailmark code graphs with external audit findings from SARIF static analysis results and weAudit annotation files. Maps findings to graph nodes by file and line overlap, creates severity-based subgraphs, and enables cross-referencing findings with pre-analysis data (blast radius, taint, etc.). Use when projecting SARIF results onto a code graph, overlaying weAudit annotations, cross-referencing Semgrep or CodeQL findings with call graph data, or visualizing audit findings in the context of code structure.

trailofbits/audit-context-building

Enables ultra-granular, line-by-line code analysis to build deep architectural context before vulnerability or bug finding.

trailofbits/audit-prep-assistant

Prepares codebases for security review using Trail of Bits' checklist. Helps set review goals, runs static analysis tools, increases test coverage, removes dead code, ensures accessibility, and generates documentation (flowcharts, user stories, inline comments).

trailofbits/burpsuite-project-parser

Searches and explores Burp Suite project files (.burp) from the command line. Use when searching response headers or bodies with regex patterns, extracting security audit findings, dumping proxy history or site map data, or analyzing HTTP traffic captured in a Burp project.

trailofbits/cairo-vulnerability-scanner

Scans Cairo/StarkNet smart contracts for 6 critical vulnerabilities including felt252 arithmetic overflow, L1-L2 messaging issues, address conversion problems, and signature replay. Use when auditing StarkNet projects.

trailofbits/cargo-fuzz

cargo-fuzz is the de facto fuzzing tool for Rust projects using Cargo. Use for fuzzing Rust code with libFuzzer backend.

trailofbits/chrome-mcp-troubleshooting

Diagnose and fix Claude in Chrome MCP extension connectivity issues. Use when mcp__claude-in-chrome__* tools fail, return "Browser extension is not connected", or behave erratically.

trailofbits/claude-in-chrome-troubleshooting

Diagnose and fix Claude in Chrome MCP extension connectivity issues. Use when mcp__claude-in-chrome__* tools fail, return "Browser extension is not connected", or behave erratically.

trailofbits/code-improver

Runs an autonomous review-and-fix improvement loop over any code target — a skill, plugin, module, or directory — using a reviewer the user names: any installed skill or agent. Keeps a cross-round findings ledger, escalates when fixes stop converging, and guards scope mechanically. Use when asked to 'improve this code until review passes', 'run an improvement loop with <reviewer>', or to iterate review-and-fix with a specific reviewer. For skills prefer the skill-improver entry; for a branch prefer pr-improver.

trailofbits/code-maturity-assessor

Systematic code maturity assessment using Trail of Bits' 9-category framework. Analyzes codebase for arithmetic safety, auditing practices, access controls, complexity, decentralization, documentation, MEV risks, low-level code, and testing. Produces professional scorecard with evidence-based ratings and actionable recommendations.

trailofbits/codeql

Scans a codebase for security vulnerabilities using CodeQL's interprocedural data flow and taint tracking analysis. Triggers on "run codeql", "codeql scan", "codeql analysis", "build codeql database", or "find vulnerabilities with codeql". Supports "run all" (security-and-quality + security-experimental suites) and "important only" (high-precision security findings) scan modes. Also handles creating data extension models and processing CodeQL SARIF output.

trailofbits/constant-time-analysis

Detects timing side-channel vulnerabilities in cryptographic code. Use when implementing or reviewing crypto code, encountering division on secrets, secret-dependent branches, or constant-time programming questions in C, C++, Go, Rust, Swift, Java, Kotlin, C#, PHP, JavaScript, TypeScript, Python, or Ruby.

trailofbits/constant-time-testing

Constant-time testing detects timing side channels in cryptographic code. Use when auditing crypto implementations for timing vulnerabilities.

trailofbits/cosmos-vulnerability-scanner

Scans Cosmos SDK blockchain modules and CosmWasm contracts for consensus-critical vulnerabilities — chain halts, fund loss, state divergence. 25 core + 16 IBC + 10 EVM + 3 CosmWasm patterns. Use when auditing custom x/ modules, reviewing IBC integrations, or assessing pre-launch chain security. Updated for SDK v0.53.x.

Skills associés