Skip to content

1.3.1

Choose a tag to compare

@github-actions github-actions released this 28 Jul 02:09
· 127 commits to main since this release
8ec6179

Security

  • Report/PDF/log storage moved to a protected private directory (unauthenticated disclosure fix) — Generated reports, client PDFs, and diagnostics logs lived under wp_upload_dir()/wpmar/ with no .htaccess/index.php protection outside the logs subdirectory, and filenames built from little more than a domain and timestamp — a few dozen to a few hundred requests could locate and download a report containing administrator email addresses, a full core/theme/plugin version inventory (i.e. a map of unpatched known vulnerabilities), checksum-mismatch findings, and server path/permission details. New artefacts now write to wp-content/wpmar-private/ by default (reports/, pdf/, logs/, tmp/ subdirectories), overridable via the WPMAR_PRIVATE_STORAGE_DIR constant or wpmar_private_storage_dir filter to move storage outside the document root entirely. Every directory gets an auto-generated .htaccess (Require all denied / Deny from all) plus index.php, and every filename carries a 20-character random token — the one defense that does not depend on the web server type. Multisite splits the base directory by site-{blog_id}/, since wp-content (unlike wp_upload_dir()) is shared network-wide. When the private directory isn't writable, the plugin falls back to an equally token-protected wp-content/uploads/wpmar/ and shows an admin notice. Existing v1.3.0 files are migrated automatically in the background after upgrading (WPMAR_Storage_Migrator; batched, idempotent, resumable, with per-file rollback if a paired DB update fails); progress shows on the plugin's admin screens, and old files are not deleted until migration completes. wp wpmar storage migrate [--dry-run] [--network] [--batch=<n>] drives or previews it manually, and wp wpmar storage migrate --revert reverses it (for downgrading back to a pre-1.3.1 release) while keeping the existing filename/token and adding the .htaccess/index.php protection v1.3.0 never had.
  • PDF rendering: Parsedown safe mode unified across the PDF and HTML-email pathsWPMAR_PDF_Writer::write_pdf_from_markdown() instantiated \Parsedown directly, skipping the safe mode already applied to the HTML-email path, so raw HTML (<script>, <annotation>, a remote <img src>) embedded in an attacker-controlled plugin/theme/display-name string reached mPDF unsanitized. Both paths now go through a single markdown_to_safe_html_fragment(), which also strips <img> tags after conversion (Markdown's own ![]() syntax still emits one even under safe mode), and the mPDF config now explicitly sets allow_local_file_access to false.
  • vendor-pdf.zip checksum verification enabled by default — Previously the installer only verified the downloaded/uploaded PDF-library archive's SHA-256 if an operator manually pinned one via the WPMAR_PDF_VENDOR_ZIP_SHA256 constant or wpmar_pdf_vendor_zip_sha256 filter; unset by default, a ~30 MB executable PHP library was extracted into the writable plugin directory over TLS with no other integrity check. The release workflow now embeds the digest for that exact release inside the plugin package itself, and the installer checks it automatically — the constant/filter still take precedence for a custom build, and a source checkout (no bundled digest) keeps today's no-op behaviour.
  • Update URI header added — Prevents a same-slug plugin on WordPress.org from silently overriding this plugin's own GitHub-Releases-based updater, per the header WordPress 5.8 introduced for exactly this case.
  • X-Content-Type-Options: nosniff on every download response — Previously only the diagnostics-log download set this header; Markdown, client-Markdown, PDF, and ZIP downloads now all go through one shared WPMAR_Download_Headers helper so the header can't be forgotten on a new download endpoint.
  • PDF-installer Ajax handlers: capability checked before noncehandle_ajax(), handle_preflight_ajax(), and handle_manual_upload_ajax() checked the nonce before the install_plugins capability, the reverse of the order used everywhere else in the plugin since the 1.0.0 hardening; all three now check capability first.
  • SECURITY.md added — Documents the supported-version policy, the private GitHub Security Advisories reporting channel, and response-time targets.
  • CI hardening — The CI workflow now declares permissions: contents: read (previously unset), pins actions/checkout and shivammathur/setup-php to a commit SHA instead of a floating major-version tag, and runs composer audit against dev dependencies in addition to the existing --no-dev check.