lit/media-preview downscales an image attachment via wp_get_image_editor and returns it as ImageContent; lit/media-download returns a file (full or a named size) as an embedded resource, rejecting files above the upload limit. Both are direct tools (ruling Q6: embedded resources, like ImageContent, only become content blocks for tools called directly). Adds MediaFiles::isWithinUploads() so neither tool ever reads a file outside wp_upload_dir()'s basedir. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
27 lines
742 B
PHP
27 lines
742 B
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace LIT\MCP\Integrations\Media;
|
|
|
|
/**
|
|
* Shared file-path safety check for lit-media-preview and lit-media-download
|
|
* (controller ruling: never read a file outside the uploads directory, even
|
|
* one get_attached_file() or an intermediate size's stored path points at).
|
|
*/
|
|
final class MediaFiles
|
|
{
|
|
public static function isWithinUploads(string $file): bool
|
|
{
|
|
$real = realpath($file);
|
|
if ($real === false) {
|
|
return false;
|
|
}
|
|
|
|
$uploads = wp_upload_dir();
|
|
$basedir = is_array($uploads) ? realpath((string) ($uploads['basedir'] ?? '')) : false;
|
|
|
|
return is_string($basedir) && str_starts_with($real, $basedir . DIRECTORY_SEPARATOR);
|
|
}
|
|
}
|