Aller au contenu

Sécurité et exploitation de NextPDF avec Symfony

Les helpers de réponse appliquent un ensemble fixe d’en-têtes de sécurité. Le DTO de message asynchrone valide deux fois son chemin de sortie. La signature est optionnelle et, avec le niveau Pro, limitée au profil baseline documenté ici.

NextPDF\Symfony\Http\PdfResponse applique le même ensemble d’en-têtes à chaque réponse qu’il construit (inline, téléchargement et les deux variantes en streaming). Les en-têtes exacts, vérifiés par rapport à la constante source :

En-têteValeur
Cache-Controlprivate, max-age=0, must-revalidate
Pragmapublic
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
Content-Security-Policydefault-src 'none'
X-Robots-Tagnoindex, nofollow
Referrer-Policyno-referrer

Ils réduisent le sniffing du type de contenu, l’inclusion dans des frames, l’indexation et la fuite de référent des documents générés. Les variantes mises en mémoire tampon définissent aussi Content-Type: application/pdf et Content-Length. Les variantes en streaming définissent le type de contenu, mais omettent Content-Length par conception.

L’ensemble d’en-têtes est fixé par le bundle. Pour ajouter ou modifier des en-têtes (par exemple un Cache-Control plus strict pour les téléchargements authentifiés), modifie la Response retournée par ton contrôleur avant de la renvoyer.

PdfResponse construit l’en-tête Content-Disposition de manière défensive, avec un comportement vérifié par rapport à PdfResponseTest :

  • Le nom de fichier est assaini ; les séparateurs de chemin et les séquences de traversée sont supprimés (un nom de fichier tel que ../../../etc/passwd.pdf ne peut pas s’échapper).
  • Une extension .pdf est ajoutée lorsqu’elle est absente ; une extension existante n’est pas dupliquée, y compris un .PDF en majuscules.
  • Les guillemets droits et les antislashs sont échappés pour la forme quoted-string.
  • Les noms de fichier non-ASCII reçoivent un repli ASCII et une variante filename*=UTF-8'' conforme à la RFC 5987.
  • Un nom de fichier vide revient à document.pdf.

Ne transmets un nom de fichier influencé par l’utilisateur qu’après ton propre contrôle d’autorisation au niveau de l’application ; le bundle assainit pour la sûreté de l’en-tête, pas pour le contrôle d’accès.

NextPDF\Symfony\Message\GeneratePdfMessage valide le chemin de sortie dans son constructeur, et NextPDF\Symfony\Message\GeneratePdfHandler le revalide à l’exécution, avant l’écriture. Règles de rejet vérifiées à la construction :

  • un chemin vide, ou un chemin contenant un octet nul ;
  • un schéma de stream-wrapper tel que php://... ;
  • un segment de traversée .. utilisant soit le séparateur /, soit \ ;
  • un chemin ne se terminant pas par .pdf (insensible à la casse) ;
  • un builderClass qui n’est pas un nom de classe syntaxiquement valide.

La seconde validation dans le handler a son importance, parce qu’un message peut rester dans une file d’attente entre le dispatch et la consommation. Le handler ne fait pas confiance au chemin mis en file d’attente et applique de nouveau le contrôle de chemin avant l’enregistrement. Exécute les workers sous un compte système à privilèges minimaux, restreint au répertoire de sortie prévu.

GeneratePdfHandler résout les builders depuis un service locator PSR-11 indexé par nom de classe et rejette tout ce qui n’est pas un PdfBuilderInterface. Comme le locator n’expose que les builders enregistrés, un builderClass contrôlé par un attaquant dans une charge utile de transport falsifiée ne peut pas instancier une classe arbitraire. Avec PSR-11, lorsqu’un conteneur signale un id comme absent, sa résolution échoue au lieu de renvoyer silencieusement quelque chose d’inattendu (PSR-11 §1.1.2). N’enregistre que des classes de builder de confiance dans le locator.

La signature numérique ne fait pas partie du bundle core. Elle s’active uniquement lorsque nextpdf/premium (qui installe le niveau Pro) est présent et que le compiler pass détecte les classes de signature Pro. Lorsque le bundle et le niveau Pro sont installés, la configuration de signature prise en charge et documentée est le profil baseline B-B.

Le nœud de configuration signature.level accepte des valeurs de chaîne supplémentaires pour rester compatible avec le schéma de la famille de configuration NextPDF. La capacité de signature livrée et prise en charge par ce bundle est B-B. Les profils de signature au-delà de B-B, leurs exigences et leurs considérations opérationnelles sont documentés dans la documentation NextPDF Premium et ne sont volontairement pas décrits ici.

Notes opérationnelles pour le parcours de signature B-B :

  • Le signataire n’est enregistré que lorsque signature.enabled est à true et que signature.certificate est défini ; sinon la section est inerte.
  • Fournis le certificat, la clé privée et le mot de passe via les secrets Symfony ou des variables d’environnement, jamais versionnés dans le dépôt.
  • Restreins les permissions de lecture sur le matériel de clé au compte de l’application.

Les registres de polices et d’images acceptent un Psr\Log\LoggerInterface optionnel lié avec nullOnInvalid(). Lorsqu’il est présent, c’est un collaborateur interchangeable conformément au contrat de logger PSR-3 (PSR-3). Supprime toute donnée permettant d’identifier l’utilisateur dans le contexte de log que tu ajoutes autour de la génération de document ; le bundle ne journalise pas le contenu des documents.

  • Conserve les en-têtes de réponse fixes ; ajoute un cache plus strict pour les téléchargements authentifiés au niveau du contrôleur.
  • Vérifie l’autorisation de la requête avant de générer ou de retourner un document ; le bundle n’effectue pas de contrôle d’accès.
  • Stocke le matériel de clé de signature dans les secrets Symfony / variables d’environnement avec des permissions de fichier à privilèges minimaux.
  • Exécute les workers Messenger sous un compte à privilèges minimaux dont l’accès en écriture est limité au répertoire de sortie.
  • Garde ext-mbstring et ext-zlib activés (le bundle échoue rapidement sinon).
  • Verrouille une seule version majeure de nextpdf/core dans l’application pour rendre la version du moteur déterministe entre les déploiements.

Chaque ligne correspond à une affirmation normative formulée sur cette page, épinglée à un reference_id complet de 64 caractères hexadécimaux issu du corpus SDO sous accès contrôlé. La provenance (manifeste du corpus, transport de récupération) se trouve dans _sidecars/rag-citations.yaml.

SpecClausereference_idAffirmation
PSR-11psr_11_container#1.1.2.p5has() à false implique que get() lève NotFoundException
PSR-3psr_3_logger#x3.p17Collaborateur logger optionnel

La signature numérique n’est disponible que lorsque nextpdf/premium (Pro) est installé ; le profil livré par ce bundle est le profil baseline B-B. C’est une capacité Pro optionnelle ; le bundle Core documenté ici ne nécessite aucune modification de code pour l’adopter. Voir </get-license/?intent=symfony-pro>.

  • /integrations/symfony/production-usage/ — sûreté des workers et streaming.
  • /integrations/symfony/configuration/ — les tables signature, tsa et service.
  • /integrations/symfony/troubleshooting/ — diagnostic des problèmes de signature et de Messenger.
  • /integrations/symfony/integration/ — référence de câblage de bout en bout.