File manager - Edit - /var/www/html/portal/tests/Feature/SecurityGuardsTest.php
Back
<?php namespace Tests\Feature; use Illuminate\Support\Facades\Route; use Tests\TestCase; /** * Guards de regressão de segurança derivados dos incidentes do Boletim * Oficial (jan/2026 e jun/2026) e da auditoria dos módulos IndicadoresTI. * * Cada teste protege uma mitigação já aplicada: se ele falhar, uma correção * de segurança foi revertida. Referência: docs/cybersec/. */ class SecurityGuardsTest extends TestCase { /** * Variáveis permitidas em saída não escapada ({!! !!}) nos templates PDF * do IndicadoresTI: apenas SVGs gerados internamente pelo SvgChartBuilder * a partir de dados numéricos (guard V3). */ private const PDF_ECHO_WHITELIST = [ '$svgDonut', '$svgGauge', '$svgSetores', '$svgBar', "\$d['svg']", ]; /** * Guard V1/V3: o DomPDF nunca pode voltar a executar PHP embutido * globalmente (vetor de RCE ampliado no commit e713282f6). */ public function test_dompdf_enable_php_permanece_desativado(): void { $this->assertFalse( (bool) config('dompdf.options.enable_php'), 'config/dompdf.php deve manter enable_php => false globalmente. ' . 'Uso legítimo deve ser ativado por render via setOptions([\'isPhpEnabled\' => true]).' ); } /** * Guard V3: os templates PDF do IndicadoresTI (renderizados com * isPhpEnabled=true) só podem conter {!! !!} para SVGs whitelisted. */ public function test_templates_pdf_indicadores_ti_sem_saida_nao_escapada_de_dados(): void { $templates = [ 'relatorio_pdf_resumido.blade.php', 'relatorio_pdf_detalhado.blade.php', 'relatorio_pdf_matricial.blade.php', ]; foreach ($templates as $template) { $path = resource_path('views/admin/indicadoresTi/reports/' . $template); $this->assertFileExists($path); $conteudo = (string) file_get_contents($path); preg_match_all('/\{!!\s*(.*?)\s*!!\}/s', $conteudo, $matches); foreach ($matches[1] as $expressao) { $this->assertContains( trim($expressao), self::PDF_ECHO_WHITELIST, "Saída não escapada não permitida em {$template}: '{$expressao}'. " . 'Nenhum dado de chamado pode entrar nos PDFs via {!! !!} (guard V3).' ); } } } /** * Guard V4: os autocompletes do IndicadoresTI retornam dados pessoais e * devem permanecer com rate limiting. */ public function test_rotas_de_autocomplete_indicadores_ti_possuem_throttle(): void { $rotas = [ 'admin.indicadoresTi.clientes.buscar', 'admin.indicadoresTi.unidades.buscar', ]; foreach ($rotas as $nome) { $rota = Route::getRoutes()->getByName($nome); $this->assertNotNull($rota, "Rota {$nome} não encontrada."); $this->assertContains( 'throttle:autocomplete', $rota->gatherMiddleware(), "A rota {$nome} deve manter o middleware throttle:autocomplete (guard V4)." ); } } /** * Guard do incidente #2: o public/.htaccess deve continuar bloqueando * todas as extensões executáveis (a regra de jan/2026 só cobria .php e * foi contornada com .phtml/.phar). */ public function test_htaccess_bloqueia_extensoes_executaveis(): void { $path = public_path('.htaccess'); $this->assertFileExists($path); $conteudo = (string) file_get_contents($path); foreach (['phtml', 'phar', 'pht'] as $extensao) { $this->assertStringContainsString( $extensao, $conteudo, "public/.htaccess deve bloquear a extensão .{$extensao} (guard do incidente #2)." ); } } /** * Guard: visualização pública de Cronogramas deve permanecer com rate limiting. */ public function test_rota_publica_cronogramas_possui_throttle(): void { $rota = Route::getRoutes()->getByName('cronogramas.public.show'); $this->assertNotNull($rota, 'Rota cronogramas.public.show não encontrada.'); $this->assertContains( 'throttle:web-public', $rota->gatherMiddleware(), 'A rota cronogramas.public.show deve manter o middleware throttle:web-public.' ); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings