> For the complete documentation index, see [llms.txt](https://guides.data.gouv.fr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guides.data.gouv.fr/passe-marche/docs/09_securite_fichiers.md).

# Sécurité des fichiers - Scan antivirus

## Présentation

Tous les fichiers déposés par les candidats sur Passe Marché sont automatiquement analysés par un antivirus avant d'être acceptés dans le dossier de candidature.

Le moteur antivirus utilisé est **ClamAV**, un antivirus open-source maintenu par **Cisco Talos**. ClamAV est le standard de référence pour le scan de fichiers côté serveur :

* Utilisé par des millions de serveurs en production dans le monde
* Base de signatures mise à jour quotidiennement
* Recommandé par l'ANSSI pour les architectures de dépôt de fichiers
* Licence GPL, auditable et transparent

## Configuration

Le scan antivirus est activé via le credential Rails `clamav.enabled: true`. Sans cette configuration, les fichiers ne sont pas scannés et aucun badge n'est affiché.

```bash
rails credentials:edit --environment <env>
# Ajouter :
# clamav:
#   enabled: true
```

### Sans le credential (`clamav.enabled` absent ou `false`)

Les fichiers ne sont pas scannés. Aucun badge affiché. Le parcours candidat fonctionne normalement.

### Avec le credential (`clamav.enabled: true`)

| Situation                         | Comportement                                                                             | Badge                          |
| --------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------ |
| **ClamAV non installé**           | Les fichiers ne sont pas scannés. Même comportement que sans le credential.              | Aucun                          |
| **ClamAV installé, mauvais path** | Même comportement que "non installé". Corriger via le credential `clamav.clamscan_path`. | Aucun                          |
| **ClamAV installé et accessible** | Scan complet.                                                                            | "Vérifié" ou "Malware détecté" |

## Installation pour les développeurs

### macOS (Homebrew)

```bash
brew install clamav

# Configurer freshclam (mise à jour des signatures)
cp /opt/homebrew/etc/clamav/freshclam.conf.sample /opt/homebrew/etc/clamav/freshclam.conf
sed -i '' 's/^Example/#Example/' /opt/homebrew/etc/clamav/freshclam.conf

# Télécharger les signatures (~300 MB)
freshclam
```

Vérifier l'installation :

```bash
clamscan --version
# ClamAV 1.x.x/xxxxx/...
```

Puis activer le scan via le credential (voir section Configuration ci-dessus).

### Linux (Debian/Ubuntu)

```bash
sudo apt-get update && sudo apt-get install -y clamav
sudo freshclam
```

Le binaire `clamscan` sera disponible à `/usr/bin/clamscan` (chemin par défaut de l'app).

### Sans ClamAV (défaut)

Rien à faire. L'app fonctionne sans ClamAV en développement. Aucun badge de scan ne sera affiché et le parcours candidat fonctionne normalement.

## Déploiement (staging / production)

### Prérequis serveur

1. **Activer le scan** via le credential Rails : `clamav.enabled: true` (voir section Configuration ci-dessus).
2. **Installer ClamAV** dans l'image Docker ou sur le serveur :

```dockerfile
RUN apt-get update && apt-get install -y clamav
RUN freshclam
```

3. **Mettre à jour les signatures** régulièrement (cron quotidien recommandé) :

```bash
0 2 * * * /usr/bin/freshclam --quiet
```

4. **Configurer le chemin** si le binaire n'est pas à `/usr/bin/clamscan` :
   * Via credential Rails : `clamav.clamscan_path`

### Vérification

```bash
# Sur le serveur, vérifier que clamscan est accessible
clamscan --version

# Tester un scan
echo "test" > /tmp/test.txt && clamscan /tmp/test.txt
```

## Architecture technique

```
Upload fichier
     │
     ▼
 ScanDocumentJob (Solid Queue)
     │
     ▼
 FileSecurityScanner
     ├── Validation taille (max configuré)
     ├── Validation extension (liste blanche)
     └── Scan antivirus
          │
          ▼
     AntivirusService
          │
          ▼
     ClamavService (via gem Clamby)
          │
          ├── OK → metadata: { scan_safe: true, scanner: "clamav" }
          ├── Malware → metadata: { scan_safe: false, scanner: "clamav" }
          └── Indisponible → metadata: { scanner: "none" }
```

### Badges affichés dans l'interface

| État                 | Badge           | Signification                                      |
| -------------------- | --------------- | -------------------------------------------------- |
| `scan_safe: true`    | Vérifié         | Fichier scanné, aucune menace détectée             |
| `scan_safe: false`   | Malware détecté | Fichier bloqué, ne sera pas inclus dans le dossier |
| `scanner: "none"`    | Non vérifié     | Antivirus indisponible, fichier accepté sans scan  |
| Pas de metadata scan | Scan en cours   | Scan en attente de traitement par Solid Queue      |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://guides.data.gouv.fr/passe-marche/docs/09_securite_fichiers.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
