Veille quotidienne CVE — récupère les nouvelles vulnérabilités critiques (CVSS≥7 OU CISA KEV) sur produits whitelist depuis NVD/MSRC/CISA, écrit max 5 fichiers dans _Inbox/raw/cve/ avec frontmatter Schema-conforme. Idempotent via seen_cves dans lazy-obsidian-state.json. Utilise WebFetch et PowerShell avec encoding UTF-8 systématique.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add aibot88/sec_skill_store --skill tommyrequillard-lazy-obsidian-skills-cve-veille --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Tommyrequillard Lazy Obsidian Skills Cve Veille?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-tommyrequillard-lazy-obsidian-skills-cve-veille)More formats (shields.io, HTML) on the badges page.
---
name: cve-veille
description: Veille quotidienne CVE — récupère les nouvelles vulnérabilités critiques (CVSS≥7 OU CISA KEV) sur produits whitelist depuis NVD/MSRC/CISA, écrit max 5 fichiers dans _Inbox/raw/cve/ avec frontmatter Schema-conforme. Idempotent via seen_cves dans lazy-obsidian-state.json. Utilise WebFetch et PowerShell avec encoding UTF-8 systématique.
---
# Skill : cve-veille (D1)
## Objectif
Avaler les CVE des dernières 24h (ou depuis last_run) répondant aux critères de criticité, et créer une page draft par CVE retenue dans `_Inbox/raw/cve/`. Idempotent. Plafond strict de 5 CVE par run pour éviter la pollution de l'inbox.
## ⚠️ Conventions techniques (à respecter strictement)
- **Encoding UTF-8 sans BOM** pour tous les writes : `Set-Content -Encoding utf8 -NoNewline` ou `Out-File -Encoding utf8 -NoNewline`. JAMAIS d'écriture en encoding par défaut PowerShell (UTF-16 LE BOM corromprait les fichiers).
- **Lecture** : `Get-Content -Raw -Encoding utf8` pour les fichiers JSON, `-Raw` pour le markdown.
- **Append jsonl** : `Add-Content -Encoding utf8 -Path <file> -Value <line>`.
- **Atomicité** : pour modifier un fichier existant, écrire `<file>.tmp` puis `Move-Item -Force`.
- **WebFetch** pour les URLs HTTPS, `Invoke-RestMethod` pour les APIs JSON (NVD).
## Procédure
### 1. Lire l'état
Lire `99-Meta/lazy-obsidian-state.json` :
```powershell
$statePath = "D:\tommyDossier\Documents\Obsidian Vault\99-Meta\lazy-obsidian-state.json"
$state = Get-Content $statePath -Raw -Encoding utf8 | ConvertFrom-Json
$lastRun = $state.last_run.'cve-veille'
$seenCves = $state.seen_cves
```
Si `$lastRun` correspond à aujourd'hui (UTC, format `YYYY-MM-DD`) → afficher "Déjà fait aujourd'hui ($lastRun). Skip." et terminer (exit gracieux). Append une ligne `SKIP_IDEMPOTENT` au runs.jsonl.
### 2. Définir la fenêtre temporelle
- `start` = `$lastRun` ou `(Get-Date).AddDays(-1).ToUniversalTime()` si null
- `end` = `(Get-Date).ToUniversalTime()`
- Format ISO 8601 : `yyyy-MM-ddTHH:mm:ss.fffZ`
### 3. Sources à interroger
**a. NVD JSON API 2.0**
```
https://services.nvd.nist.gov/rest/json/cves/2.0?lastModStartDate=<start>&lastModEndDate=<end>
```
Pagination avec `startIndex` si > 2000 résultats (rare en 24h).
**b. MSRC RSS**
```
https://api.msrc.microsoft.com/update-guide/rss
```
Filtrer entrées `pubDate` dans la fenêtre.
**c. CISA KEV catalog**
```
https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
```
Filtrer `vulnerabilities[].dateAdded` dans la fenêtre.
Per-source try/catch. Une source en échec n'invalide pas les autres. Logger les sources échouées dans `sources_failed[]` du runs.jsonl.
### 4. Whitelist produits
Liste configurable (modifier ici si besoin) :
```
Windows
Linux kernel
Apache HTTPD
nginx
OpenSSH
OpenSSL
Kubernetes
Docker
Microsoft Exchange
Active Directory
```
Match case-insensitive, substring sur les champs produit (CPE `criteria` pour NVD, titre/description pour MSRC/RSS).
### 5. Critères de retenue
Une CVE est retenue si **TOUTES** ces conditions :
- ID CVE non présent dans `$seenCves`
- (CVSS v3 baseScore ≥ 7.0) **OU** (présente dans CISA KEV — `vulnerabilities[].cveID`)
- Au moins un produit affecté match (case-insensitive) un item de la whitelist
### 6. Tri & plafond
```powershell
$retained | Sort-Object @{e='cvss';desc=$true}, @{e='date';desc=$true} | Select-Object -First 5
```
**Plafond strict : 5 CVE par run.** Si la fenêtre contient plus de 5 CVE éligibles, on garde les plus critiques (CVSS desc puis date desc).
### 7. Pour chaque CVE retenue : écrire le fichier
Chemin : `_Inbox\raw\cve\CVE-YYYY-NNNNN.md`
Contenu (template — substituer les `<…>`) :
```markdown
---
titre: "CVE-YYYY-NNNNN — <produit principal> <classe vuln en 3-5 mots>"
type: vulnerabilité
cluster: <cluster_inferé>
cve: [CVE-YYYY-NNNNN]
cvss_score: <float>
statut: draft
criticite: <low|medium|high|critical>
importance: standard
source_knowledge: vendor-doc
source_url: <URL NVD primaire>
tags: ["#cyber/cve", "#meta/veille-auto"]
date_maj: <YYYY-MM-DD>
---
# CVE-YYYY-NNNNN — <produit> <classe>
> [!warning] Vulnérabilité critique
> Score CVSS : <score>. CISA KEV : <oui/non>.
## Description
<Description NVD originale, traduite en français si possible, max 6 lignes.>
## Produits affectés
- <Liste CPE / versions, max 5 items>
## Source
- NVD : <URL>
- Vendor advisory : <URL si présent>
- CISA KEV : <URL si applicable>
## À investiguer
- [ ] Cluster cible définitif (parmi les 16 du Schema.md)
- [ ] Lien vers pages existantes du vault (wikilinks)
- [ ] Promotion vers `pages/{01|02|03}-…` si pertinent
```
**Écriture impérative :**
```powershell
$path = "...\_Inbox\raw\cve\CVE-2026-XXXXX.md"
Set-Content -Path $path -Value $content -Encoding utf8 -NoNewline
```
### 8. Inférence du cluster (heuristique)
| Mots-clés produit | Cluster inféré |
|---|---|
| `Active Directory`, `Kerberos`, `NTLM`, `LDAP` | `07-IAM-ActiveDirectory` |
| `Windows`, `Microsoft Exchange`, `Office` | `02-Blue-Team` |
| `Linux kernel` | `02-Blue-Team` |
| `Apache`, `nginx`, `OpenSSL` | `05-AppSec-DevSecOps` |
| `Kubernetes`, `Docker` | `06-Cloud-Security` |
| `OpenSSH` | `04-Reseau-Protocoles` |
| (autre / ambigu) | `99-Meta` |
**Mapping criticité ↔ CVSS :**
- 9.0–10.0 → `critical`
- 7.0–8.9 → `high`
- (<7.0 ne passe pas le filtre)
### 9. Append dans Fact-Check-Log.md
Pour chaque CVE retenue :
```powershell
$line = "- [veille-auto] [$cveId](_Inbox/raw/cve/$cveId.md) — CVSS $score, source NVD, ingéré $now"
Add-Content -Path "...\99-Meta\Fact-Check-Log.md" -Value $line -Encoding utf8
```
Si la section "## Veille automatique" n'existe pas dans `Fact-Check-Log.md`, la créer en append avant de logger.
### 10. Update state.json
```powershell
$state.last_run.'cve-veille' = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
foreach ($cve in $retainedIds) { $state.seen_cves += $cve }
$state | ConvertTo-Json -Depth 5 | Set-Content -Path $statePath -Encoding utf8 -NoNewline
```
Si erreurs → append dans `state.errors[]` (FIFO max 50 entrées).
### 11. Append runs.jsonl
```powershell
$runEntry = @{
ts = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
skill = "cve-veille"
status = "OK" # ou "PARTIAL", "FAIL", "SKIP_IDEMPOTENT"
new = $retainedCount
skipped = $skippedCount
errors = $errorCount
sources_failed = @()
} | ConvertTo-Json -Compress
Add-Content -Path "...\99-Meta\lazy-obsidian-runs.jsonl" -Value $runEntry -Encoding utf8
```
Statuts :
- `OK` : ≥1 retenue, 0 erreur source
- `PARTIAL` : ≥1 retenue mais ≥1 source en échec
- `FAIL` : aucune retenue ET ≥1 source en échec
- `SKIP_IDEMPOTENT` : déjà fait aujourd'hui
### 12. Output utilisateur
Affichage console final :
```
✅ cve-veille — 3 nouvelles CVE retenues, 12 filtrées hors whitelist, 0 erreurs.
- CVE-2026-12345 (CVSS 9.8) → _Inbox/raw/cve/
- CVE-2026-12346 (CVSS 8.1) → _Inbox/raw/cve/
- CVE-2026-12347 (CVSS 7.5) → _Inbox/raw/cve/
```
Si SKIP : `⏭ cve-veille — déjà fait aujourd'hui (2026-04-25T09:12:33Z). Skip.`
Si FAIL : `❌ cve-veille — sources en échec : <liste>. Aucune CVE ingérée.`
## Gestion d'erreurs
| Cause | Action |
|---|---|
| NVD 5xx / timeout | Retry x2 backoff (1s, 5s). Échec → log `state.errors[]`, continuer avec MSRC/CISA |
| NVD parser fail | Écrire `_Inbox\raw\cve\_PARSE-ERROR-<date>.md` avec payload brut, log, skip |
| RSS feed down | Per-source try/catch, log `sources_failed`, autres sources continuent |
| Quota / 429 / 403 | Backoff 30s → 5min → abandon |
| `Set-Content` échoue (fichier verrouillé Obsidian) | Retry après 2s. Si échec → log + skip ce CVE spécifique |
## Limites volontaires (YAGNI)
- Pas de retry infini (max 2)
- Pas de notification externe (push, email)
- Pas de check sémantique (date plausible) — confiance NVD
- Pas de suppression de CVE déjà ingérée même si retirée du KEV
- Pas de classification fine du cluster (heuristique simple ; humain réajuste)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!