Files
WP-LIT-MCP/src/Integrations/Media/MediaGuard.php
T
janniclas.loosenandClaude Opus 5.5 b24eb6c3e9 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
2026-09-26 19:32:12 +02:00

59 lines
2.0 KiB
PHP

<?php
declare(strict_types=1);
namespace LIT\MCP\Integrations\Media;
use LIT\MCP\Abilities\Errors;
use LIT\MCP\Integrations\WordPress\PostGuard;
use WP_Error;
use WP_Post;
defined('ABSPATH') || exit;
/**
* Loads an attachment for abilities and checks the capability on that attachment
* (spec §4.5). Every error is ready to be returned from permission()/execute().
*/
final class MediaGuard
{
/**
* Trashed attachments (only possible with MEDIA_TRASH) are refused unless $allowTrashed:
* readers pass it, writers must not (a change or a delete there would be surprising or permanent).
*
* @param string $capability Meta capability checked on the attachment: edit_post, delete_post or read_post.
*/
public static function attachment(
mixed $id,
string $capability = 'edit_post',
bool $allowTrashed = false
): WP_Post|WP_Error {
$attachmentId = PostGuard::id($id);
if ($attachmentId === null) {
return Errors::invalidInput('id fehlt oder ist ungültig.', ['id' => 'positive Ganzzahl erwartet']);
}
$attachment = get_post($attachmentId);
if (! $attachment instanceof WP_Post || $attachment->post_type !== 'attachment') {
return Errors::notFound(
sprintf('Medium %d nicht gefunden.', $attachmentId),
'ID prüfen; Medien über lit/media-search (direkt: lit-media-search) suchen.'
);
}
if (! current_user_can($capability, $attachmentId)) {
return Errors::forbidden(sprintf('Keine Berechtigung für Medium %d.', $attachmentId));
}
if (! $allowTrashed && $attachment->post_status === 'trash') {
return Errors::invalidInput(
sprintf('Medium %d liegt im Papierkorb.', $attachmentId),
['id' => 'Medium liegt im Papierkorb'],
'Medium zuerst in der WordPress-Mediathek wiederherstellen.'
);
}
return $attachment;
}
}