LFW

Blog · Lo que encuentra la auditoría gratuita

Su biblioteca de medios es pública

La biblioteca de medios no es una carpeta privada, ni en WordPress ni en ningún otro sitio. Qué significa eso para los borradores y los dosieres que se suben para obtener un enlace, por qué apagar la API es la solución equivocada y cómo marcar un archivo como privado sin romper nada.

Público por defecto, en todos los sistemas

Una biblioteca de medios es una carpeta en un servidor web. Subir un archivo es publicarlo. Eso vale para WordPress, para Drupal y para un sitio estático por igual; la diferencia es solo lo fácil que resulta encontrar el listado.

En WordPress, el listado está a una dirección de distancia. La API REST en /wp-json/wp/v2/media devuelve cada archivo de la biblioteca a cualquiera que lo pida, sin iniciar sesión. La JSON:API de Drupal hace el equivalente. Esto no es un fallo. La misma API alimenta el editor de bloques, las galerías, las aplicaciones móviles y las integraciones que su equipo ya usa.

De dónde viene la sorpresa

La gente lleva a la biblioteca un modelo de Dropbox: una carpeta privada donde dejar un archivo para obtener un enlace. Así que la biblioteca se llena de lo que nunca debió difundirse. El borrador tres de un documento cuyo borrador cuatro es el que está en la página. Un dosier de la junta subido para que una persona pudiera descargarlo. Un informe programado para la semana que viene, subido hoy.

Se confunden dos hechos. Un archivo al que ninguna página enlaza está sin enlazar, no es privado. Un archivo difícil de encontrar está escondido, no es privado. La API lista ambos, y un buscador que encuentre la dirección indexará ambos.

Por qué apagar la API es la solución equivocada

La respuesta tentadora es desactivar la API REST, o esconder el punto de acceso de medios. Eso es seguridad por oscuridad: detiene una forma de listar archivos mientras cada dirección directa sigue funcionando, y rompe las funciones del editor y las integraciones que dependen de la API.

La pregunta real no es si la biblioteca puede listarse. Es qué archivos de ella deben ser públicos. Una vez que responda eso archivo por archivo, la API deja de ser un problema y vuelve a ser infraestructura.

Cómo manejarlo en WordPress

Primero, mire. Abra /wp-json/wp/v2/media?media_type=application en su propio sitio y lea lo que devuelve. Esa es la lista que ve un desconocido.

Segundo, decida archivo por archivo. Los archivos públicos se quedan. Los borradores superados y todo lo que nunca debió publicarse se borran; una versión publicada por documento. Los archivos que tienen que existir pero no deben ser localizables se marcan como privados.

Tercero, márquelos. Escribimos un plugin pequeño exactamente para esto, LFW Private Media: una casilla Privado en cada adjunto, más acciones en lote en la lista de Medios. Un archivo privado desaparece de la API pública, de la búsqueda del sitio, de las páginas de adjuntos y de los sitemaps, mientras sus editores siguen viéndolo todo. Descárguelo en LFW.com/dl/lfw-private-media.zip. Si prefiere ver el mecanismo antes que instalar nada, la idea completa cabe en un archivo pequeño:

Ver el código Ocultar el código PHP, 27 líneas
<?php
/**
 * Plugin Name: Private media (minimal)
 * Keeps attachments carrying the meta key _lfw_private out of the public REST API.
 * Editors (anyone who can upload files) still see them.
 */

// The collection: /wp-json/wp/v2/media
add_filter( 'rest_attachment_query', function ( $args ) {
  if ( current_user_can( 'upload_files' ) ) { return $args; }
  $args['meta_query']   = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
  $args['meta_query'][] = array( 'key' => '_lfw_private', 'compare' => 'NOT EXISTS' );
  return $args;
} );

// A single item: /wp-json/wp/v2/media/123
add_filter( 'rest_request_before_callbacks', function ( $response, $handler, $request ) {
  if ( current_user_can( 'upload_files' ) ) { return $response; }
  if ( preg_match( '#^/wp/v2/media/(\d+)$#', $request->get_route(), $m )
       && '1' === get_post_meta( (int) $m[1], '_lfw_private', true ) ) {
    return new WP_Error( 'rest_post_invalid_id', 'Invalid post ID.', array( 'status' => 404 ) );
  }
  return $response;
}, 10, 3 );

// Mark a file private: add the meta key _lfw_private with the value 1.
// With WP-CLI: wp post meta update <attachment-id> _lfw_private 1

Un límite honesto, para cualquiera de las dos versiones. Un archivo que ya es público en una dirección directa sigue siendo alcanzable para quien tenga esa dirección. Marcarlo como privado impide que los desconocidos lo descubran. No pone el archivo detrás de un inicio de sesión. Todo lo genuinamente confidencial no pertenece a la carpeta de subidas; pertenece a una descarga con control de acceso.

Si es cliente

No necesita instalar nada. Abra una solicitud en su portal y auditaremos la biblioteca con usted, borraremos lo que deba irse, marcaremos como privado lo que deba quedarse e instalaremos el plugin. Es una tarea pequeña dentro de la iguala, no un proyecto.

Si todavía no es cliente, la auditoría gratuita le dirá cuántos archivos lista hoy su sitio a los desconocidos. Ese suele ser el momento en que termina el modelo de Dropbox.

Siga leyendo

6 de septiembre de 2026 8 minutos

Los cuatro archivos que nadie enlaza

Todo sitio web tiene cuatro archivos de texto plano que ningún visitante ve: robots.txt, sitemap.xml, security.txt y llms.txt. Los buscadores, los escáneres de seguridad y los agentes de IA los leen en cada visita. Qué es cada uno, quién lo lee de verdad, qué poner en él y la única regla que los mantiene a todos seguros. Esta semana repasamos la lista en nuestro propio sitio y encontramos huecos, así que la auditoría gratuita ahora los comprueba.

6 de septiembre de 2026 6 minutos

Nuestra imagen principal desaparecía en iPhone. Un bloqueador de anuncios la escondía.

Durante semanas, la imagen principal de tres de nuestras propias páginas desaparecía un segundo y medio en iPhone, solo en la primera carga. Nada lo reproducía en el laboratorio. Un rastreo de campo de cincuenta líneas lo encontró en tres cargas de página: un bloqueador de anuncios escondía cualquier elemento cuya clase empezara por ad-.

Todos los artículos →

Prefer to write?

Tell us what needs to work better.

Slow, fragile, hard to edit, missing a workflow. Say it plainly, and you'll get a straight answer, not a ticket number.

You'll get a straight answer, usually the same day.