Repository navigation
Description
Rodei SAST, SCA e DAST no master em b8f081a. Nada explorável apareceu. Este issue registra o que foi rodado, o que foi triado como falso positivo e as duas coisas que sobraram como trabalho real — para que ninguém precise repetir a triagem.
Resultado por ferramenta
| camada | ferramenta | resultado |
|---|---|---|
| SCA (PHP) | composer audit |
limpo — "No security vulnerability advisories found" |
| SCA (JS) | npm audit |
limpo — 0 vulnerabilidades em qualquer severidade |
| SAST | semgrep (p/php, p/security-audit, p/owasp-top-ten) |
19 achados, 0 confirmados após triagem |
| DAST | OWASP ZAP baseline, app rodando com sqlite | 0 FAIL, 14 WARN, 53 PASS |
Os 53 PASS do ZAP importam tanto quanto os warnings: sem XSS refletido, sem SQLi, sem listagem de diretório, flags de cookie corretas, e POST /login sem token devolve 419 — CSRF está sendo aplicado de verdade.
Falsos positivos do semgrep (triados, não filar)
laravel-unsafe-validatoremProfileController.php:28— a regra marcaRule::unique(...)->ignore($request->...)textualmente. O valor é$user->user_id, com$user = $request->user(): id do próprio autenticado, vindo da sessão, não de input.tainted-filenameemserver.php:17— é oserver.phpde fábrica do Laravel, edocker/nginx/default.conf:6temroot /var/www/html/public. O arquivo não é alcançável por HTTP em produção. (Ver mesmo assim o último item abaixo.)insecure-use-string-copy-fn×5 emtools/safeexec.c:349-361— todos sãostrncpy(dest, optarg, 255)seguidos dedest[255]=0explícito, comBUFFSIZE 256. Corretos. (O safeexec sai de cena de qualquer forma — Judge sandbox: cap resident memory with cgroups #86.)missing-usernoDockerfile— o comentário logo acima explica: o PHP-FPM sobe como root para ler config e abrir a porta, e cai para o usuáriowwwdefinido nowww.conf. É o desenho padrão e está documentado. ODockerfile.judgetemUSER judge.request-host-usedemdocker/nginx/default.conf:74— está dentro de um bloco comentado de HMR do Vite.
O que sobrou: cabeçalhos de resposta
docker/nginx/default.conf já manda X-Frame-Options, X-Content-Type-Options e Referrer-Policy. O ZAP apontou os que faltam:
- Content-Security-Policy — ausente em todas as páginas. É a mitigação de XSS que sobra depois do escaping do Blade, e a aplicação serve conteúdo controlado por usuário (enunciados, nomes de equipe, saída de compilador em
submission-show) - Permissions-Policy — ausente
- Cross-Origin-Embedder-Policy / Cross-Origin-Opener-Policy / Cross-Origin-Resource-Policy — ausentes
- Strict-Transport-Security — ausente. O bloco TLS do nginx está comentado; quando for habilitado, o HSTS vai junto
Ignorar: "Big Redirect", "Non-Storable Content", "Session Management Response Identified", "Modern Web Application" e "Authentication Request Identified" são informativos do ZAP, não defeitos.
O que sobrou: CI
- Pinar as actions em SHA de commit. O
.github/workflows/ci.ymlusaactions/checkout@v4,shivammathur/setup-php@v2,docker/build-push-action@v6etc. Tag é mutável: quem controla o repositório da action pode movê-la e passar a executar código diferente num workflow que tem acesso aoGITHUB_TOKENe ao cache. 10 ocorrências, todas minhas — o semgrep pegou código que eu mesmo escrevi ontem.
Limpeza, de baixo risco
- Remover
resources/views/welcome.blade.phpeserver.php. São restos do esqueleto do Laravel: owelcomecarrega uma folha de estilo do Google Fonts sem SRI (o único recurso externo da aplicação, e a origem do warning de SRI do ZAP) e linka documentação do Laravel. Oserver.phpnão é usado desde o Laravel 11.
Como reproduzir
docker run --rm -v "$PWD":/app -w /app composer:latest composer audit
npm audit
docker run --rm -v "$PWD":/src -w /src semgrep/semgrep semgrep \
--config=p/php --config=p/security-audit --config=p/owasp-top-ten \
--exclude=vendor --exclude=node_modules --exclude=boca-master
# DAST: subir a app com sqlite e apontar o ZAP
docker run --rm --network <rede> ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t http://<app>:8000Nota para quem for repetir o DAST: php artisan serve não repassa variáveis de ambiente arbitrárias ao processo filho (só a allowlist do ServeCommand), então -e SESSION_DRIVER=file é ignorado e a app tenta o Redis do .env. Usar php -S 0.0.0.0:8000 -t public server.php.
Activity
fix(judge): remove safeexec and the rest of the pre-sandbox model (#96)
feat(sos): issue #139 -- team S.O.S. to the local site staff (#160)
feat(reports): judge history, per-site report and charts (#144)
Judge history, per-site report and charts (#144) (#165)