
Harness de recherche de vulnérabilités du noyau Linux piloté par les preuves, utilisé dans l'investigation de la CVE-2026-31720.
Outil de recherche · Import d'origine : 3 avril 2026 · Révision de la documentation : 11 juillet 2026
Philosophie centrale — Signal externe
Laissez des observations reproductibles calculées en dehors de l'inférence du modèle guider l'attention ; ne confondez jamais priorité et preuve.
État du projet. Ce dépôt est une version initiale d'un harnais de recherche assisté par LLM que j'ai construit et utilisé pour une véritable recherche de vulnérabilités dans le noyau Linux. Cette version a servi à découvrir la vulnérabilité publiée sous le nom CVE-2026-31720. Le harnais hiérarchise les cibles d'investigation mais ne prouve pas automatiquement les vulnérabilités ni ne garantit la sécurité du noyau ; la validation finale et le rapport restent effectués par un humain.
Abstract— Laisser un LLM explorer directement une base de code aussi vaste que le noyau Linux disperse rapidement le contexte et confond facilement la présence d'API dangereuses avec une exploitabilité réelle. Kernel Codex Harness définit ce problème non pas comme de la détection automatique de vulnérabilités, mais comme un problème de . Ce projet appelle le principe consistant à contrôler l'attention du modèle avec des observations reproductibles calculées en dehors de l'inférence du LLM. Il combine des signaux statiques liés aux chemins du noyau, aux frontières userspace, à la durée de vie (lifetime), aux usercopy, aux refcounts et aux tailles, ainsi qu'une intelligence optionnelle des crashes syzbot, pour classer les fichiers candidats et transformer chaque candidat en un ensemble restreint de prompts. La revue manuelle et l'autopilote basé sur un budget de temps utilisent le même contrat de réponse et le même état de session. Ce harnais a été utilisé dans une investigation réelle du noyau Linux qui a découvert un dépassement d'écriture hors limites sur la pile dans le chemin audio du gadget USB ; ce défaut a été publié sous le nom . Cette implémentation n'est pas un analyseur statique de précision, mais un workflow de recherche qui limite le périmètre d'investigation du LLM à l'aide d'heuristiques explicables ; chaque résultat exige une revalidation humaine de l'atteignabilité (reachability), de la rupture d'invariant et de l'impact concret.
Index Terms— Linux kernel, vulnerability research, external signal, LLM orchestration, heuristic prioritization, syzbot, program analysis, Codex.
La revue de sécurité du noyau Linux comporte deux types de problèmes d'échelle. Premièrement, l'arborescence source complète est trop vaste pour tenir dans un seul contexte LLM. Deuxièmement, des signaux comme copy_from_user, les allocateurs, les refcounts et les verrous sont fréquents mais ne signifient pas en soi une vulnérabilité. L'analyste doit d'abord décider « où regarder », puis prouver séparément l'atteignabilité depuis l'userspace et les transitions d'état concrètes.
La philosophie centrale de ce projet est l'External Signal.
On ne laisse pas le LLM décider lui-même où regarder. Des signaux reproductibles, extérieurs à l'inférence du modèle, répartissent l'attention, mais la conclusion de vulnérabilité ne se fonde que sur l'atteignabilité et les preuves d'invariant.
Le harnais ne fait donc pas explorer tout le noyau au modèle de manière vague. Il hiérarchise les fichiers, ne fournit qu'une seule branche d'investigation à la fois et exige d'abord une structure de preuve plutôt qu'une conclusion.
L'External Signal n'est pas un jugement généré par le LLM, mais une observation déterminée avant l'exécution du modèle et recalculable à partir de la même arborescence source, du même profil et des mêmes JSON syzbot stockés. Les poids de chemins, les correspondances d'expressions régulières et le chevauchement syzbot en cache en font partie. Ce signal sert uniquement au classement des candidats et au contexte des prompts ; il n'est jamais promu au rang de verdict ou de preuve.
Dans ce document, l'External Signal désigne la philosophie globale du projet. Le modèle de données ExternalSignal dans le code ne représente actuellement que les signaux issus de syzbot ; les deux termes ont donc des portées différentes.
Les correspondances d'expressions régulières, les chemins à haut risque et le chevauchement syzbot sont tous des signaux destinés à ordonner l'investigation. Un score élevé ne constitue pas un résultat de sécurité si le chemin d'appel réel, les privilèges, la configuration du noyau, le namespace ou la disponibilité des périphériques ne permettent pas à un attaquant d'y accéder.
L'audit vérifie d'abord les frontières partant de l'userspace : syscall, ioctl, netlink, procfs, systèmes de fichiers, BPF, hooks de pilotes. Ce n'est qu'ensuite qu'il évalue les classes de bugs telles que UAF, OOB, refcount, course (race), fuite d'informations ou vérifications de capacités.
Une unité d'investigation est par défaut limitée à un seul fichier et à ses chemins proches d'appelants, de teardown et de libération. Les suivis manuels recommandés par le modèle sont limités à deux au maximum. Cette restriction ne vise pas à réduire la capacité d'exploration, mais à maintenir les conclusions dans un périmètre vérifiable.
Les prompts exigent qu'un résultat fort décrive au minimum les éléments suivants.
Si les preuves sont insuffisantes, le modèle renvoie une seule cible à vérifier ensuite au lieu d'affirmer fortement une vulnérabilité. Il s'agit d'un contrat de preuve au niveau du prompt ; le parseur actuel ne vérifie pas automatiquement l'exhaustivité de chaque preuve. L'ingestion normalise le verdict et la cible suivante ; la validation finale des preuves reste donc de la responsabilité humaine.
Le flux d'investigation initial s'inspire des idées d'analyse par fichier, d'extension limitée du contexte et de résultats structurés utilisées par vulnhuntr de Protect AI [1]. Ce projet ne les applique pas telles quelles à l'analyse d'applications Python, mais les reconçoit autour de la surface du noyau atteignable depuis l'userspace, de la durée de vie des objets du noyau, des chemins de teardown et du chevauchement syzbot. En particulier, séparer les signaux de priorisation de la preuve de vulnérabilité et vérifier l'atteignabilité avant la classe de bug constitue le choix de conception central du harnais pour le noyau.
Fig. 1. La couche External Signal transforme les observations calculées avant l'inférence du modèle en unités de revue classées. Elle répartit l'attention mais n'établit pas la preuve d'une vulnérabilité.
TABLEAU I — RESPONSABILITÉS DES MODULES PRINCIPAUX
| Module | Responsabilité |
|---|---|
targeting.py | Exploration des fichiers du noyau et score des signaux de chemins, de motifs et syzbot |
models.py | Modèles de données Candidate, Signal et ExternalSignal dérivé de syzbot |
bundle.py | Génération du manifeste, de l'index de session et des bundles de prompts/extraits |
prompting.py | Prompts d'audit du noyau centrés sur l'atteignabilité et les invariants |
session.py | Stockage de l'état : revue en attente, historique, profondeur des suivis |
ingest.py | Normalisation stricte du verdict et de la cible suivante |
autopilot.py | Gestion de codex exec basée sur un budget de temps, journaux, archives et résultats |
syzbot.py | Collecte des pages publiques syzbot et création d'un cache JSON local |
cli.py | Connexion des commandes scan, inspect, codex, loop, autopilot, etc. |
Le scanner parcourt les fichiers .c et .h situés sous le répertoire d'inclusion du profil. Le score de priorité d'un fichier f se compose conceptuellement comme suit.
Score(f) = Σ path_weight(f)
+ Σ line_signal_weight(f)
+ Σ syzbot_overlap_weight(f)
Ce score n'est ni une probabilité ni une mesure d'exploitabilité. Chaque terme ne fournit qu'un ordre relatif pour décider quels fichiers le modèle doit examiner en premier. L'implémentation actuelle additionne toutes les correspondances au niveau des lignes et ne limite que les signaux les plus importants affichés dans le prompt. Le recalcul d'un même résultat suppose la même arborescence source, le même profil et les mêmes JSON syzbot en cache. Le poids syzbot est appliqué a posteriori aux fichiers déjà candidats via les heuristiques de chemins et de lignes ; une simple correspondance syzbot ne crée pas de nouveau fichier candidat.
Les principaux signaux statiques sont les suivants.
ioctl, gestionnaires compat, hooks d'opérations de fichierscopy_from_user, copy_to_user, __userkmalloc, kzalloc, kvmalloc, chemins d'allocation et de libération de cacheLes profils intégrés sont default, net, fs, io_uring, bpf et drivers. Un profil définit les chemins d'inclusion, les motifs, les poids et le nombre de signaux à conserver par fichier. Plutôt qu'une politique de score unique pour tout le noyau, chaque profil reflète la surface d'attaque et les caractéristiques de durée de vie propres à un sous-système.
syzbot-fetch extrait des pages publiques de bugs syzbot du projet syzkaller [2] le titre, le sous-système, le type de bug et les informations file:line, puis les stocke dans un cache JSON. Un chevauchement exact de fichier constitue un External Signal fort ; un chevauchement de sous-système, un External Signal faible. Le tableau de bord en direct pouvant changer, l'unité de reproduction est le JSON stocké au moment de la collecte. Les informations de crash ne servent que de point de départ pour la chasse aux variantes et ne sont pas traitées comme une preuve de nouvelle vulnérabilité.
scan génère un manifeste de candidats classés et un ensemble initial de bundles de prompts. Chaque prompt contient le chemin cible, la raison du score, les signaux de lignes, le contexte syzbot et la procédure d'audit.
La réponse du modèle est normalisée en l'un des verdicts suivants.
cve_candidateplausible_security_buglatent_bugnot_cve_candidateneeds_more_contextLa réponse comprend une Single best next target et un court résumé. Les anciennes réponses sans cible en attente sont archivées séparément et ne sont pas reliées à une nouvelle cible.
git clone https://github.com/foxirain/linux-kernel-codex-harness.git
cd linux-kernel-codex-harness
python3 -m venv .venv
source .venv/bin/activate
python -m pip install .
Les JSON de profils intégrés sont inclus dans la wheel. Des règles JSON externes peuvent être transmises via --config /path/to/profile.json.
# 1. Créer une session classée.
kernel-harness scan /path/to/linux \
--profile net \
--limit 80 \
--top 20 \
--out artifacts
# 2. Inspecter les candidats à haute priorité.
kernel-harness inspect artifacts/session-YYYYMMDDTHHMMSSZ --top 10
# 3. Générer un prompt ciblé.
kernel-harness codex artifacts/session-YYYYMMDDTHHMMSSZ \
--rank 1 \
--include-snippet
--limit définit le nombre de candidats conservés dans le manifeste et --top le nombre de bundles de prompts pré-générés au départ. Les bundles des rangs suivants peuvent être générés à la demande.
kernel-harness autopilot artifacts/session-YYYYMMDDTHHMMSSZ \
--duration 30m \
--per-run-timeout 10m \
--include-snippet
Le sandbox par défaut est read-only. --sandbox workspace-write ne doit être spécifié que si la modification de fichiers est absolument nécessaire pendant l'analyse.
kernel-harness syzbot-fetch https://syzkaller.appspot.com/upstream \
--out artifacts/syzbot/upstream.json \
--limit 50
kernel-harness scan /path/to/linux \
--profile fs \
--syzbot-json artifacts/syzbot/upstream.json \
--out artifacts
artifacts/session-<timestamp>/
├── SESSION.md
├── targets.json
├── finding_template.json
├── review_state.json
├── codex_response.txt # présent tant qu'une réponse est en attente
├── bundles/
│ ├── <rank>-<target>.md
│ └── <rank>-<target>.snippet.txt
├── responses/
└── autopilot/
├── AUTOPILOT_STATUS.txt
├── AUTOPILOT_PROGRESS.txt
├── AUTOPILOT_FINDINGS.txt
├── prompts/
├── exec/
└── findings/
Cette version ne s'est pas limitée à une preuve de concept ; elle a été utilisée pour une véritable recherche de vulnérabilités dans le noyau Linux.
TABLEAU II — RÉSULTAT DE VULNÉRABILITÉ PUBLIÉE
| Résultat public | Zone concernée | Sévérité / CVSS | Vulnérabilité | Modèle d'investigation |
|---|---|---|---|---|
| CVE-2026-31720 | Audio gadget USB · drivers/usb/gadget/function/f_uac1_legacy.c | La longueur de requête contrôlée par l'hôte pouvait déborder un objet de quatre octets sur la pile | Résultat mis au jour lors d'une investigation assistée par v1 ; la validation et la divulgation sont restées pilotées par un humain |
CVE-2026-31720 : NVD CVSS 3.1 · 7.8 High · CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HLa vérification ne constitue pas un benchmark de précision de détection, mais se concentre sur les régressions de l'implémentation et sa déployabilité.
TABLEAU III — PÉRIMÈTRE DE VÉRIFICATION TECHNIQUE
| Élément de vérification | Propriété attendue |
|---|---|
| Régression des allocateurs | Détection de kmalloc et kvmalloc comme signaux d'allocateur |
| Ressources de profils | Chargement des 6 profils intégrés depuis un checkout source, smoke-test du profil default depuis la wheel installée |
| Contrat de verdict | not_cve_candidate n'est pas confondu avec un résultat positif |
| Politique de suivi | Deux suivis manuels autorisés, troisième demande bloquée |
| Gestion des réponses obsolètes | Les réponses sans cible en attente sont archivées et non réutilisées |
| Défaut sûr | Le sandbox par défaut de l'autopilote est read-only |
| Matrice CI | Exécution de la suite de régressions sous Python 3.11 et 3.12 |
python -m unittest discover -s tests -v
GitHub Actions exécute les régressions unitaires, puis installe la wheel dans un nouvel environnement et effectue un smoke-test du scan avec le profil default. Le cas public ci-dessus est un résultat opérationnel obtenu lors d'une investigation réelle, mais il ne s'agit pas d'un benchmark de précision, de rappel ou de taux de découverte de CVE mesuré sur un corpus représentatif d'arbres Linux.
read-only par défaut.--dangerously-bypass-approvals-and-sandbox.Depuis la première version consignée dans l'historique Git, l'objectif était moins de « laisser le LLM trouver les vulnérabilités tout seul » que de « contrôler quel code examiner en premier et quelles preuves exiger ». L'investigation assistée par v1 qui a découvert CVE-2026-31720 a fourni un cas d'application réelle de l'unité d'investigation restreinte et du contrat de preuve. La v2 étend ce workflow jusqu'à un triage sensible à la provenance, qui préserve à la fois l'état du dépôt et les références connues. Si je devais le réimplémenter aujourd'hui, je donnerais la priorité à ce qui suit.
review et runner,Le principe central que je souhaite néanmoins conserver est l'External Signal. Ne pas laisser le LLM explorer vaguement toute la base de code, mais répéter des unités d'investigation restreintes par des signaux extérieurs au modèle, centrées sur l'atteignabilité et les invariants.
Kernel Codex Harness ne remplace pas la détection de vulnérabilités du noyau Linux. Il transforme plutôt l'External Signal en un classement explicable et limite la revue LLM à un processus d'investigation court et avec état. Cette structure a été utilisée lors d'une investigation réelle pour découvrir CVE-2026-31720. Le résultat central du projet ne consiste pas à revendiquer un nouvel algorithme d'analyse, mais à définir la revue de sécurité par LLM comme un problème d'allocation d'attention par signaux externes, de contrat de preuve et d'orchestration reproductible, puis à l'appliquer à un workflow de recherche réel.
.
├── .github/workflows/ci.yml
├── docs/
│ ├── assets/kernel-harness-architecture.svg
│ ├── AUTOPILOT.md
│ ├── CODEX_CLI.md
│ ├── CODEX_WORKFLOW.md
│ └── SYZBOT.md
├── kernel_harness/
│ ├── resources/
│ │ ├── linux-kernel-default.json
│ │ └── profiles/
│ ├── autopilot.py
│ ├── bundle.py
│ ├── cli.py
│ ├── ingest.py
│ ├── models.py
│ ├── prompting.py
│ ├── session.py
│ ├── syzbot.py
│ └── targeting.py
├── tests/test_regressions.py
├── README.md
└── pyproject.toml
Les procédures opérationnelles détaillées sont disponibles dans docs/.
[1] Protect AI, « vulnhuntr », dépôt GitHub. https://github.com/protectai/vulnhuntr
[2] Google, « syzkaller and syzbot », dépôt GitHub. https://github.com/google/syzkaller
[3] OpenAI, « Codex CLI ». https://developers.openai.com/codex/cli/
Sous licence Apache License 2.0.