v1.7.7
External security audit + GPL switchFull security, functional and code audit. All findings fixed. License switched to GPL v2+ (WordPress.org-repository-compliant). The ~84 layers are now classified into three maturity tiers: 39 Stable, 39 Beta, 6 Labs (default-hidden, opt-in via Security → Advanced).
🛡 Security (critical / high)
- Path traversal in File-Browser restore fixed — crafted entry names could bypass the realpath check, allowing writes outside
ABSPATH. - SSRF in Multi-Push receiver closed — pull_url is now validated against private/loopback/link-local IPs (v4+v6) and non-https schemes.
- Backup directory protection: random filename suffix from 6 → 24 chars (62²⁴ brute-force resistant), plus
web.config(IIS) andindex.php-404 in addition to.htaccess. Protects Nginx hosts too. - Zip-Slip / zip-bomb / symlink protection via new
ZipSafeclass in every extract path (restore, anonymizer, file-browser). - DOM-XSS from backup contents (imported backups could trigger cross-admin XSS) fixed by consistent escaping of all innerHTML sinks.
- PBKDF2 iterations raised to 600,000 (NIST/OWASP 2024+). Legacy RES1 path keeps 200,000 for backwards compatibility.
- SHA-256 verification on backup import: optional "Expected SHA-256" field on the upload form, server verifies via
hash_equalsbefore touching the file. Wire tampering and corruption are detected. Hash chip in backup list with click-to-copy. - Content-Disposition header injection fixed: RFC 5987 with ASCII fallback + UTF-8 encoded variant, plus
X-Content-Type-Options: nosniff.
🐛 Functional regressions (critical)
- 11 killer features that could not be activated (Auto-Heal, Webhook-Trigger, 2FA-Guard, Watchdog, Bandwidth-Throttle, Maint-during-Backup, Magic-Link-TTL, Anonymizer-Rules) — schema whitelist did not contain the keys. Toggle appeared to save, value silently discarded. Fixed.
- Encryption magic mismatch: write path used
RES1, import magic-byte check looked forBKSRSV→ self-encrypted backups got rejected on import. Fixed via sharedEncryption::is_known_magic()source. - Version inconsistency: plugin header showed 1.7.7,
readme.txtstable tag 1.0.0. Synced plus new tooling (bin/sync-version.php) and CI gate to prevent future drift. - Logs tab hung at "Loading…" (and 12 other AJAX endpoints silently broken): autoloader switch no longer eager-loaded file-bottom
add_action()calls. All migrated intoboot()methods, plus new test forbidding the anti-pattern.
🏗 Architecture cleanup
- PSR-4 autoloader replaces 95
require_oncelines with lazy class loading. - Encryption rewritten as streaming (RES2 format, chunked AES-256-GCM with per-chunk AAD): now scales to 25-GB backups instead of OOM at ~256 MB. Legacy RES1 backups remain decryptable.
- class-admin.php 2097 → 909 LOC (-57 %): 6 large tabs split into dedicated classes under
includes/admin/class-tab-*.php. backsta.php 467 → 209 LOC (-55 %). - 113 default settings centralized in
SettingsSchema::defaults()— single source of truth. Tests prevent drift between defaults and toggle whitelist.
🧪 Trust / distribution
- License: GPL v2+ (previously Proprietary). Plugin is now WordPress.org-repository-compatible and GPL-compliance-compliant.
- PHPUnit test suite with 19 tests / 38 assertions: encryption roundtrip + tamper + wrong-password + legacy-RES1, zip-slip protection, schema consistency, autoloader coverage, version sync, cross-class method resolution.
- CI on PHP 8.0 / 8.1 / 8.2 / 8.3 with lint + version check + PHPUnit. README, CONTRIBUTING, SECURITY (with audit history), CHANGELOG.
- Feature registry with Stable/Beta/Labs tier system: 39 stable, 39 beta, 6 labs (default-hidden). Toggle in Security → Advanced.