fix(security): no direct HTTP access to plugin PHP files (audit L2, cheap part)

Every file under src/ exits outside WordPress (defined('ABSPATH') ||
exit; after the use block, so a direct request no longer prints a fatal
error with the server path); divi-convert-fixture.php gets the WP_CLI
guard the other integration scripts have. A unit test keeps both true;
PSR1 side-effects warning excluded for the guard.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-26 19:32:12 +02:00
co-authored by Claude Opus 5.5
parent 4d4bf57c9f
commit b24eb6c3e9
185 changed files with 418 additions and 1 deletions
@@ -13,6 +13,8 @@ use Throwable;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* Copies entries (draft copy, trashed backup) and swaps a copy's content back into its
* original. Meta is copied byte-exact: the stored meta_value strings are read and
@@ -14,6 +14,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* lit/post-duplicate: creates a draft copy of an entry (spec §6.2). The original –
* ID, URL, menu items, content – is not touched. A failure after the insert deletes
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* lit/post-publish: publishes an entry immediately. A scheduled ("future") or
* future-dated entry is republished now instead of staying in the future (spec §6.2);
@@ -20,6 +20,8 @@ use Throwable;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* lit/post-replace-with-copy: swaps a copy made by lit/post-duplicate into its original
* (spec §6.2). ID, URL, status and menu items of the original stay. rev of the original
@@ -17,6 +17,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* lit/post-schedule: schedules an entry for publication at a future point in time
* (site local time). An entry that is currently published stays live until then only
@@ -16,6 +16,8 @@ use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* lit/post-trash: moves an entry to the trash – never a permanent delete. Trashing the
* static front page, the posts page or an entry linked in a menu is allowed but named in
@@ -15,6 +15,8 @@ use LIT\MCP\Integrations\WordPress\PostGuard;
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
use WP_Error;
defined('ABSPATH') || exit;
/**
* lit/post-unpublish: withdraws a published, scheduled or private entry back to draft.
* An entry that is already not public (draft, pending, auto-draft) is a no-op.
@@ -7,6 +7,8 @@ namespace LIT\MCP\Integrations\WordPress\Status;
use RuntimeException;
use Throwable;
defined('ABSPATH') || exit;
/**
* Thrown by PostCloner::replace(). $parts lists the parts of the original replace()
* had started to write (post, meta, terms) – only those need to be restored.
@@ -9,6 +9,8 @@ use LIT\MCP\ChangeLog\ChangeLog;
use Throwable;
use WP_Post;
defined('ABSPATH') || exit;
/**
* Runs the one WordPress call of a status tool (wp_update_post(), wp_trash_post()). If a
* hook throws inside it, the row may already be written – the entry's state is unknown,