Files
xamxam/docs/de-librairisation.md

5.3 KiB

De-librairisation Plan

Why

XAMXAM currently contains ~3,300 lines of custom code implementing common infrastructural concerns that well-maintained ecosystem libraries have already solved — correctly, securely, and with years of security audits and edge-case hardening behind them. By replacing these bespoke implementations with off-the-shelf packages we:

  • Eliminate attack surface — we stop maintaining our own SMTP client, HTTP client, and Markdown parser.
  • Reduce maintenance burden — each line of infrastructure code we own is a line we must understand, debug, and keep secure. Off-the-shelf libs shift that to dedicated maintenance teams.
  • Gain features for free — DKIM signing, TLS 1.3, connection pooling, async I/O, proper content security — all things we would never build ourselves.
  • Make the codebase smaller and more readable — the remaining code is actual application logic, not protocol plumbing.

What we replace

# Component Current size Replaced by Why
1 Markdown parser ~1770 lines league/commonmark 2.x Parsedown 1.8.0 is unmaintained since 2019. It has known XSS vulnerabilities fixed in later versions that never shipped. league/commonmark is the de-facto standard, actively maintained, security-audited, and supports GFM extensions (tables, strikethrough, autolinks).
2 SMTP client ~680 lines phpmailer/phpmailer 6.x Raw socket SMTP with manual STARTTLS negotiation is one of the hardest things to get right in application code. PHPMailer handles TLS 1.3, DKIM, MIME encoding, character sets, connection pooling — all things our custom code does not.
3 HTTP client ~200 lines guzzlehttp/guzzle 7.x PeerTubeService::httpRequest() uses file_get_contents() with stream_context_create(). Manual JSON parsing, no retry logic, no connection reuse, fragile error handling. Guzzle is the PHP HTTP standard.
4 Encryption ~86 lines defuse/php-encryption 2.x Our AES-256-GCM implementation is actually correct, but home-rolled crypto is never recommended. defuse/php-encryption is the recommended library by the PHP security community. Requires migration of existing encrypted data.

What we keep (and why)

Component Why keep
password_hash() / password_verify() Already the correct approach — PHP's built-in bcrypt. No library needed.
CSRF (App.php) Implementation is correct: 256-bit random token, hash_equals() verification, rotated after mutations. A Symfony CSRF component would be an upgrade but not urgent.
Rate limiter (RateLimit.php) Adequate for current scale. A concurrent-safe Symfony rate-limiter would be better but the file race condition is low-risk at our traffic levels.
PHP templates Plain PHP include with extract() is fast, simple, and well-understood. Auto-escaping (Twig) would be a security upgrade but the migration cost is high and content is mostly admin-controlled.
Logging error_log() with JSON-lines is sufficient. Monolog would be cleaner but adds no security benefit.

Composer setup

The project currently has no composer.json. PHP CS Fixer and PHPStan were installed manually into vendor/bin/. We will:

  1. Create composer.json with the four packages above.
  2. Run composer install to populate vendor/.
  3. Keep existing PHP CS Fixer and PHPStan configs — they already work.

Migration order (by risk)

Phase 1: Markdown parser (low risk, high payoff)

  • Surface: 4 files import Parsedown
  • API similarity: $pd->text($input)$converter->convert($input)
  • SafeMode equivalent: league/commonmark is safe by default (no raw HTML in safe mode)
  • No data migration needed: input is Markdown strings, output is HTML — both are ephemeral and regenerated on each page load
  • Files to change:
    • app/src/Controllers/AboutController.php
    • app/src/Controllers/LicenceController.php
    • app/templates/partials/form/form-help-block.php
    • app/public/admin/form-help-inline-fragment.php

Phase 2: HTTP client (low risk, PeerTube-specific)

  • Surface: app/src/PeerTubeService.php only
  • No data migration needed: purely a transport layer replacement
  • Can be done independently of Phase 1

Phase 3: SMTP client (medium risk, needs testing)

  • Surface: app/src/SmtpRelay.php
  • API change: SmtpRelay::send($db, $to, $subject, $htmlBody) signature stays, but internals replaced with PHPMailer
  • No data migration needed: SMTP settings in DB are read identically
  • Must test: actual email sending to a real SMTP server before deploying

Phase 4: Encryption (highest risk, requires migration)

  • Surface: app/src/Crypto.php, app/src/ShareLink.php, app/src/AdminAuth.php
  • Affects: encrypted passwords in share_links.encrypted_password, SMTP password in site_settings
  • Migration required: decrypt all values with old Crypto, re-encrypt with defuse/php-encryption, write migration script
  • Do last, and only if the risk/reward is worth it (our current implementation is actually correct)

Target state

After all phases, the codebase loses ~2,700 lines of infrastructure code and gains four well-maintained dependencies with known security postures and upgrade paths.