Un artículo de Laravel News publicado el 17 de septiembre de 2026 presenta Laravel Scalpel, un paquete creado por Harry Agustiana. Se ejecuta dentro de una aplicación Laravel y busca indicios de intrusión en el sistema de archivos, como archivos PHP introducidos de forma ilegítima, código oculto, directivas del servidor alteradas y cambios posteriores al despliegue.
php artisan scalpel:scan
php artisan scalpel:scan --only=structural,obfuscated
php artisan scalpel:scan --only=useriniWard y Checkpoint cubren otra parte del problema. Esas herramientas revisan el código fuente, la configuración y las dependencias en busca de riesgos de seguridad. Scalpel busca archivos que hayan sido añadidos, modificados o eliminados en una aplicación ya desplegada.
scalpel:scan utiliza seis analizadores por defecto. Cinco inspeccionan los archivos actuales y Baseline Diff los compara con una instantánea guardada. El analizador estructural revisa public/ y storage/ en busca de archivos PHP ejecutables. Detecta .php, .phtml, .pht y .phar, además de dobles extensiones como shell.php.jpg. public/index.php, public/vendor/ y las vistas y cachés compiladas de Laravel quedan permitidos inicialmente. La configuración permite cambiar las rutas analizadas y las listas de archivos y directorios autorizados.
El analizador de código ofuscado busca patrones como eval(base64_decode(...)), ejecución de cargas comprimidas, llamadas dinámicas a funciones, evaluación directa de datos de las peticiones y cadenas codificadas muy largas. Un patrón concreto puede desactivarse en config/scalpel.php cuando el código legítimo de la aplicación provoca una detección. El analizador de .htaccess informa de asociaciones de handlers y tipos MIME que permiten ejecutar Python, Perl, CGI u otros intérpretes. También revisa Options +ExecCGI, reglas que redirigen a URL externas y directivas como auto_prepend_file. El analizador de .user.ini cubre auto_prepend_file, auto_append_file, include_path y disable_functions. Un atacante puede usar auto_prepend_file para ejecutar un archivo oculto en cada petición.
El analizador del entorno informa de archivos .env ausentes, vacíos o ilegibles, de cualquier .env situado bajo public/ y, en sistemas similares a Unix, de permisos de lectura para todos los usuarios. También detecta un APP_KEY vacío y compara las claves de .env con .env.example. Las claves inesperadas o ausentes se consideran posibles indicios de intrusión. Cuando APP_ENV es production, APP_DEBUG=true genera una alerta. La opción --production aplica esa comprobación sin importar el valor de APP_ENV y también marca APP_ENV=local.
scalpel:scan permite seleccionar analizadores mediante --only. scalpel:baseline guarda para cada archivo incluido un hash SHA-256, su tamaño y su fecha de modificación. scalpel:diff informa de archivos añadidos, modificados y eliminados. La baseline debe crearse cuando la aplicación se encuentre en un estado fiable. Hasta entonces, scalpel:scan y scalpel:diff muestran un hallazgo MEDIUM que solicita crearla. Después de cada despliegue, el procedimiento recomendado ejecuta php artisan optimize y después php artisan baseline --force.
Las exclusiones predeterminadas cubren rutas que cambian con frecuencia, como logs, sesiones, vistas compiladas y storage/app. vendor/ se omite en los análisis de contenido, pero sigue incluido en las comparaciones de baseline. Así, un archivo nuevo dentro de un paquete instalado aparece en el diff. El modo estricto calcula el hash de todos los archivos en cada comparación. --fast reutiliza el hash anterior cuando el tamaño y la fecha de modificación coinciden. Un atacante que conserve ambos valores puede ocultar un cambio ante esa comparación. Otro analizador todavía puede detectarlo por su contenido o ubicación.
Las baselines y los informes JSON pueden firmarse con HMAC. Para ello, SCALPEL_SIGNING_ENABLED debe estar activo y SCALPEL_SIGNING_KEY debe contener una clave dedicada distinta de APP_KEY. scalpel:diff verifica la baseline firmada y clasifica como CRITICAL una firma ausente o inválida. La firma no protege la baseline cuando el atacante puede leer la clave o modificar el analizador. Debe activarse antes de crear la primera baseline. scalpel:verify comprueba la firma de un informe JSON guardado.
La prueba del artículo utiliza Scalpel 1.9.0 en una aplicación nueva con Laravel 13.31. Con los permisos de .env fijados en 0600 y una baseline creada, el análisis predeterminado no encontró problemas. Después se añadieron cuatro elementos de prueba inofensivos: eval(base64_decode(...)) dentro de if (false), un archivo llamado avatar.php.jpg, una asociación de handler en .htaccess y un archivo .user.ini con auto_prepend_file. Los cuatro analizadores de contenido se ejecutaron con php artisan scalpel:scan --only=structural,obfuscated,htaccess,userini --no-banner. El análisis completo produjo nueve hallazgos porque Baseline Diff también detectó esos cuatro archivos y un cambio en routes/web.php.
La prueba descubrió un problema potencial con las vistas generadas en CI. php artisan optimize compiló vistas del framework bajo storage/framework/views. El análisis siguiente registró allí 100 hallazgos MEDIUM sobre variables variables y dos hallazgos HIGH relacionados con backticks. Tras ejecutar php artisan optimize:clear y crear otra baseline, el análisis terminó sin hallazgos. El analizador estructural permite ese directorio, pero el de código ofuscado sigue leyendo su contenido. Las aplicaciones que almacenan vistas en caché en producción deben probar esta ruta antes de convertir Scalpel en un bloqueo del despliegue. Añadir storage/framework/views a content_scan_excluded_paths elimina esos avisos y excluye todas las comprobaciones de contenido para las vistas compiladas.
scan y diff admiten salidas en tabla, JSON, anotaciones de GitHub Actions y SARIF. --fail-on fija la gravedad mínima que hace fallar un trabajo de CI. El valor predeterminado es HIGH. El ejemplo SARIF es php artisan scalpel:scan --format=sarif --fail-on=MEDIUM. El código de salida 0 indica que no se encontró ningún hallazgo relevante. El código 1 señala un hallazgo igual o superior al umbral. El código 2 cubre hallazgos inferiores al umbral o un análisis incompleto, como ocurre con un directorio ilegible.
Después de scalpel:scan o scalpel:diff, el paquete emite el evento ScanFinished. El evento incluye los hallazgos, el comando ejecutado, scan o diff, y la duración en milisegundos. Una aplicación puede utilizarlo para enviar avisos por correo, Slack o webhook sin analizar la salida del comando.
Laravel Scalpel requiere PHP 8.2 o posterior y es compatible con Laravel 10 a 13. La instalación usa composer require hryagstn/laravel-scalpel y después php artisan vendor:publish --tag=scalpel-config para publicar la configuración. El analizador comparte el proceso y los permisos del sistema de archivos de la aplicación. Quien pueda modificar el código de la aplicación también puede modificar el analizador o su configuración. El proyecto recomienda activadores externos, directorios de código de solo lectura y guardar los resultados fuera del servidor posiblemente comprometido. Scalpel detecta indicios de intrusión, pero no ofrece funciones de firewall ni de contención. El código fuente y la referencia completa de comandos están en GitHub, y el sitio de Laravel Scalpel incluye un simulador.




Comentarios
Aún no hay comentarios — escribe el primero.
Inicia la conversación
Sin cuenta ni contraseña — introduce tu correo y te enviamos un enlace de acceso de un solo uso. ¿Primera vez? Todo se configura automáticamente.
Tu valoración se aplicará automáticamente al iniciar sesión.
Revisa tu bandeja de entrada
Hemos enviado un enlace de acceso a …. Ábrelo en este dispositivo — esta pestaña te conectará automáticamente.
¿No llega nada? Mira en la carpeta de spam — y marca el correo como «No es spam» para que la próxima vez llegue directo.