Créer un Scanner Antivirus pour VS Code

Tuto Créer un Scanner Antivirus pour VS Code

  •  Thread starter
  •  Admin
  • 1000795812.webp

    Scanner de code “anti‑malware” pour VS Code — Tuto complet

    Objectif : détecter du code potentiellement malveillant (eval, powershell encodé, URLs d’exfiltration, etc.) ou des fichiers infectés dans un projet VS Code.




    Plan
    1. Prérequis & périmètre
    2. Solution rapide (outils existants)
    3. Créer une extension VS Code (TypeScript) : scanner heuristique
    4. b Intégrer ClamAV / YARA[/b]
    5. Automatiser : Tasks VS Code + pre‑commit
    6. Copilot Chat : prompts utiles
    7. Limites, bonnes pratiques




    1) Prérequis & périmètre

    Systèmes : Windows, macOS, Linux
    Outils possibles : VS Code, Node.js 18+, ClamAV (facultatif), YARA (facultatif), Git (pour pre‑commit)

    Ce que ce tuto couvre :
    • Détection par heuristiques (regex & patterns de risque).
    • Intégration optionnelle d’un moteur AV (ClamAV) et de signatures (YARA).
    • Affichage des alertes dans l’onglet Problèmes de VS Code.
    • Automatisation à la demande, à la sauvegarde ou à l’intégration (Git).




    2) Solution rapide (outils existants)

    A) ClamAV (gratuit, signatures malwares connues)
    • Installez ClamAV (via package manager ou installateur).
    • Mettez à jour les signatures :
      Code:
      freshclam
    • Lancez un scan dans le workspace depuis le terminal VS Code :
      Code:
      clamscan -r --bell -i .
    • Les fichiers infectés seront listés dans la sortie.

    B) Semgrep & plugins sécurité
    • Semgrep (règles personnalisables) :
      Code:
      semgrep --config auto
    • Bandit (Python), ESLint security plugins (JS/TS), Snyk/CodeQL selon votre stack.

    Astuce : Combinez ClamAV (malwares connus) + Semgrep (anti‑patterns de code) pour une bonne couverture.




    3) Créer une extension VS Code (TypeScript) : scanner heuristique

    3.1) Bootstrap de l’extension
    • Installez les outils :
      Code:
      npm install -g yo generator-code vsce
    • Générez une extension TypeScript :
      Code:
      yo code
      Choisissez : New Extension (TypeScript)

    3.2) Déclarez la commande dans package.json
    Code:
     { "activationEvents": ["onCommand:malwareScanner.scanWorkspace"], "contributes": { "commands": [ { "command": "malwareScanner.scanWorkspace", "title": "Scanner le workspace (Malware)" } ] } }

    3.3) Code du scanner (heuristiques + diagnostics)
    Créez/éditez src/extension.ts :

    Code:
     import * as vscode from 'vscode'; import * as fs from 'fs'; 
    import * as path from 'path'; 
    import { exec } from 'child_process';
    
    interface Finding { file: vscode.Uri; range: vscode.Range; message: string; severity: vscode.DiagnosticSeverity; ruleId: string; }
    
    const suspiciousPatterns: { ruleId: string; regex: RegExp; message: string }[] = [ { ruleId: 'JS-EVAL', regex: /\beval\s*(/i, message: "Usage de 'eval' potentiellement dangereux." }, { ruleId: 'JS-FUNCTION-CALL', regex: /\bnew\s+Function\s*(/i, message: "Construction dynamique de code (new Function)." }, { ruleId: 'JS-CHILD-PROC', regex: /\b(child_process|spawn|exec|execFile)\b/i, message: "Exécution de commandes système." }, { ruleId: 'PS-ENC', regex: /powershell(?:.exe)?\s+-enc\s+[A-Za-z0-9+/=]+/i, message: "Commande PowerShell encodée." }, { ruleId: 'B64-LONG', regex: /'"`['"`]/, message: "Chaîne base64 longue suspecte." }, { ruleId: 'URL-EXFIL', regex: /\bhttps?://[^\s'"`]+/i, message: "Lien externe (potentielle exfiltration)." }, { ruleId: 'WIN-PERSIST', regex: /\b(\Run\|\RunOnce\|Startup\|schtasks.exe)\b/i, message: "Indicateurs de persistance Windows." } ];
    
    export function activate(context: vscode.ExtensionContext) { const diagnostics = vscode.languages.createDiagnosticCollection('malwareScanner'); context.subscriptions.push(diagnostics);
    
    const scanCmd = vscode.commands.registerCommand('malwareScanner.scanWorkspace', async () => { diagnostics.clear(); const folders = vscode.workspace.workspaceFolders; if (!folders) { vscode.window.showWarningMessage('Aucun dossier de workspace ouvert.'); return; }
    
    const findings: Finding[] = [];
    for (const folder of folders) {
      await scanFolder(folder.uri.fsPath, findings);
    }
    
    // Publier les diagnostics
    const byFile = new Map<string, vscode.Diagnostic[]>();
    for (const f of findings) {
      const diag = new vscode.Diagnostic(f.range, \`[\${f.ruleId}] \${f.message}\`, f.severity);
      diag.source = 'MalwareScanner';
      const key = f.file.toString();
      if (!byFile.has(key)) byFile.set(key, []);
      byFile.get(key)!.push(diag);
    }
    byFile.forEach((diags, file) => diagnostics.set(vscode.Uri.parse(file), diags));
    
    vscode.window.showInformationMessage(\`Scan terminé: \${findings.length} alerte(s).\`);
     
    });
    
    context.subscriptions.push(scanCmd); 
    }
    async function scanFolder(dir: string, findings: Finding[]) { const entries = await fs.promises.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const full = path.join(dir, entry.name);
    
    if (entry.isDirectory()) {
      if (['.git', 'node_modules', 'dist', 'build', '.venv', '.tox', '.pytest_cache'].includes(entry.name)) continue;
      await scanFolder(full, findings);
      continue;
    }
    
    if (!/\.(js|ts|mjs|cjs|jsx|tsx|py|ps1|bat|cmd|sh|php|rb|go|cs|json|yml|yaml|ini|conf|txt)$/i.test(entry.name)) continue;
    
    await scanFile(full, findings);
     
    } }
    
    async function scanFile(filePath: string, findings: Finding[]) { try { const text = await fs.promises.readFile(filePath, 'utf8'); const lines = text.split(/\r?\n/); 
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      for (const rule of suspiciousPatterns) {
        const m = rule.regex.exec(line);
       if (m) {
          const start = m.index;
          const end = m.index + m[0].length;
          findings.push({
            file: vscode.Uri.file(filePath),
            range: new vscode.Range(new vscode.Position(i, start), new vscode.Position(i, end)),
            message: rule.message,
            severity: vscode.DiagnosticSeverity.Warning,
            ruleId: rule.ruleId
          });
        }
      }
    
      // Heuristique: détecter une base64 longue et vérifier du contenu décodé potentiellement dangereux
      const b64Match = line.match(/(['"\`])([A-Za-z0-9+/]{80,}={0,2})\1/);
      if (b64Match) {
        try {
          const buf = Buffer.from(b64Match[2], 'base64');
          const decoded = buf.toString('utf8');
          if (/\b(eval|cmd\.exe|powershell|wget|curl|Invoke-WebRequest|nc -e)\b/i.test(decoded)) {
            findings.push({
              file: vscode.Uri.file(filePath),
              range: new vscode.Range(new vscode.Position(i, 0), new vscode.Position(i, line.length)),
              message: "Chaîne base64 décodée contenant des indicateurs dangereux.",
              severity: vscode.DiagnosticSeverity.Error,
              ruleId: 'B64-DECODED-DANGEROUS'
            });
          }
        } catch {
          // ignore
        }
      }
    }
    } catch { // binaire ou permissions: ignorer } }
    
    export function deactivate() {}

    3.4) Tester en mode développement
    • Installer les dépendances et compiler :
      Code:
      npm install npm run compile
    • Appuyer sur F5 pour lancer un “Extension Development Host”.
    • Commande palette → taper :
      Code:
      Scanner le workspace (Malware)
    • Voir les alertes dans l’onglet Problèmes.

    3.5) (Option) Scan en continu
    Ajoutez un FileSystemWatcher pour scanner à la sauvegarde (idée simple) :
    Code:
     const watcher = vscode.workspace.createFileSystemWatcher('**/.{js,ts,py,ps1,sh}'); watcher.onDidChange(uri => scanFile(uri.fsPath, [] / vous pouvez réémettre les diagnostics ciblés ici /)); watcher.onDidCreate(uri => scanFile(uri.fsPath, [])); watcher.onDidDelete(uri => { / retirer diagnostics pour ce fichier */ }); context.subscriptions.push(watcher);




    4) (Option) Intégrer ClamAV / YARA

    ClamAV (via CLI) : lancez le moteur et parsez sa sortie.
    Code:
     function runClamAV(rootPath: string): Promise { return new Promise((resolve) => { exec(`clamscan -r --bell -i "${rootPath}"`, { timeout: 5 * 60_000 }, (err, stdout) => { resolve(stdout || ''); }); }); }

    YARA : stockez vos règles dans rules/ et exécutez yara en CLI, puis créez des diagnostics pour chaque match.
    Astuce : gardez YARA/ClamAV optionnels (feature flags) pour ne pas bloquer l’extension si non installés.




    5) Automatiser : Tasks VS Code + pre‑commit

    5.1) Task VS Code (exemple ClamAV + Semgrep) dans [.vscode/tasks.json] :
    Code:
     { "version": "2.0.0", "tasks": [ { "label": "Scan ClamAV", "type": "shell", "command": "clamscan -r --bell -i .", "problemMatcher": [] }, { "label": "Scan Semgrep", "type": "shell", "command": "semgrep --config auto", "problemMatcher": [] } ] }

    5.2) Hook pre‑commit (Git + Husky)
    Code:
     npm i -D husky lint-staged npx husky install npx husky add .husky/pre-commit "npm run scan:quick"

    Ajoutez un script scan:quick dans package.json :
    Code:
     "scripts": { "scan:quick": "semgrep --config auto && echo 'OK Semgrep' || (echo 'Semgrep KO' && exit 1)" }

    Variante : ajoutez un clamscan si installé localement.




    6) Copilot Chat : prompts utiles

    Utilisez Copilot Chat dans VS Code pour accélérer la création/examen des règles :
    • Code:
      Explique ce fichier et signale tout pattern à risque (eval, exec, powershell -enc, base64 longue).
    • Code:
      Écris une règle regex pour détecter des commandes PowerShell encodées en base64 dans des scripts .js et .ps1.
    • Code:
      Propose des améliorations à mon extension VS Code : moins de faux positifs, cache par hash, affichage des extraits suspects.
    • Code:
      Génère un rapport JSON structuré (fichier, ligne, règle, extrait).




    7) Limites & bonnes pratiques

    • Faux positifs : eval ou child_process peuvent être légitimes. Autorisez des commentaires d’ignore (ex. // malware-scan: ignore JS-EVAL ) et ajustez la sévérité.
    • Faux négatifs : du code très obfusqué peut passer. Multipliez heuristiques + signatures (ClamAV/YARA) + SAST (Semgrep).
    • Performance : ignorez node_modules , .git , binaires, archives ; mettez des timeouts ; cachez par hash.
    • Sécurité : ne jamais exécuter le code scanné. Ne décompressez pas automatiquement des archives inconnues.
    • CI/CD : répliquez le scan en pipeline (GitHub Actions/Azure DevOps) et faites échouer en cas d’alertes critiques.
    • Traçabilité : exportez un rapport JSON (règle, fichier, ligne, extrait, SHA256).




    Conclusion

    Avec ce tuto, vous pouvez :
    • Utiliser rapidement ClamAV/Semgrep dans VS Code.
    • Développer une extension légère qui met en évidence les patterns suspects.
    • Automatiser les contrôles à la sauvegarde et au commit.
     
    Similar content Most view View more
    Back
    Top