Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 66 additions & 5 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Segurança e qualidade
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
workflow_dispatch:

Expand Down Expand Up @@ -54,6 +55,28 @@ jobs:
- uses: actions/checkout@v4
- run: docker build --tag ferroada:ci .
- run: docker build --tag ferroada-coraza:ci deploy/coraza
# Sem registry neste repositório: o job constrói ferroada:ci localmente
# e não faz push. Cosign keyless (OIDC do GitHub, id-token: write) fica
# para quando o operador publicar a imagem — não inventamos GHCR/Hub.
- name: Cosign (sem registry)
run: |
cat <<'EOF'
Este repositório não publica a imagem num registry (GHCR, Docker Hub
ou outro). O job constrói ferroada:ci localmente e para aí.

Quando existir registry, assinar com cosign keyless via OIDC do
GitHub (sem chave longa no repo):

permissions:
id-token: write
contents: read
- uses: sigstore/cosign-installer@v3
- docker push "$IMAGE"
- cosign sign --yes "$IMAGE@$DIGEST"

Identidade: https://token.actions.githubusercontent.com
Subject: repo:DenisCDev/ferroada:*
EOF

packs:
runs-on: ubuntu-latest
Expand All @@ -72,14 +95,52 @@ jobs:
version: v3.17.3
- run: python3 deploy/helm/assert-chart.py

sbom:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with:
tool: cargo-cyclonedx
- name: Gerar CycloneDX do crate ferroada
run: |
set -euo pipefail
cargo cyclonedx --format json --spec-version 1.5 --describe crate
if [ -f ferroada.cdx.json ]; then
:
elif [ -f bom.json ]; then
mv bom.json ferroada.cdx.json
else
echo "SBOM JSON do crate ferroada não foi gerado" >&2
ls -la
exit 1
fi
python3 -c "import json; d=json.load(open('ferroada.cdx.json')); assert d.get('bomFormat')=='CycloneDX', d"
- uses: actions/upload-artifact@v4
with:
name: sbom-ferroada-cyclonedx
path: ferroada.cdx.json
if-no-files-found: error
retention-days: 30

fuzz:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 10
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
target: [waf, protocol, dlp]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
components: rust-src
- uses: Swatinem/rust-cache@v2
with:
workspaces: fuzz
shared-key: fuzz-nightly
- run: cargo install cargo-fuzz --locked
- run: cargo fuzz run waf -- -max_total_time=45
- run: cargo fuzz run protocol -- -max_total_time=45
- run: cargo fuzz run dlp -- -max_total_time=45
- run: cargo fuzz run ${{ matrix.target }} -- -max_total_time=45
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ Thumbs.db

# Claude Code
.claude/

# SBOM gerado localmente — o CI publica como artefacto, não no git
*.cdx.json
*.cdx.xml
bom.json
bom.xml
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ conexão HTTP/2 a 100 streams simultâneos, rejeitando headers excessivos com 43
antes da aplicação. O Ferroada fixa a versão exata no manifesto e no lockfile
para que build local, container e CI usem a mesma base.

O Ferroada **não** é production-grade: falta auditoria de segurança externa
e não há linha LTS. Relatar falhas e o que isto cobre: [SECURITY.md](SECURITY.md).

```
Internet → [Ferroada :3000] → Seu Sistema :8080
↓
Expand Down Expand Up @@ -739,3 +742,4 @@ Cliente (resposta limpa e hardened)
- **Rust** — binário único, sem runtime, sem garbage collector
- **Distroless** — imagem Docker sem shell, sem package manager (~20MB)
- **Zero dependências externas** — não precisa de Redis, banco de dados nem serviço auxiliar
- **Ainda não é production-grade** — falta auditoria externa e LTS. Ver [SECURITY.md](SECURITY.md).
53 changes: 53 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Política de segurança

O Ferroada **não** é production-grade. Falta auditoria de segurança externa
e não há linha LTS. Tratar o binário como “pronto para produção global”
depende dessas duas coisas, não deste ficheiro.

`SMAUG_AUDIT.md` (2026-08-31) é revisão interna do repositório. Não substitui
auditoria externa.

## Como reportar uma falha

Não abra issue pública com PoC, payload ou passos que permitam explorar.

1. Use o [relatório privado de vulnerabilidade do GitHub](https://github.com/DenisCDev/ferroada/security/advisories/new) neste repositório.
2. Inclua: versão ou commit, configuração relevante (**sem** segredos), passos para reproduzir, impacto esperado.
3. Se o formulário privado não estiver activo, contacte o maintainer por mensagem privada no GitHub. Não publique o exploit.

Não há CNA neste projecto, não atribuímos CVE, e não há bug bounty.

## Prazos internos

Metas de trabalho, não SLA contratual e não janela LTS. Um atraso não torna
o produto production-grade.

| Severidade | O que conta | Primeira resposta | Correção visada |
| --- | --- | --- | --- |
| Crítica | RCE no proxy, bypass total do WAF em rota fail-closed, leak de token/dashboard | 2 dias úteis | 7 dias úteis |
| Alta | Bypass parcial, DoS no data plane, leak de PII que o DLP deveria parar | 5 dias úteis | 14 dias úteis |
| Média | Falha que exige config insegura do operador, ou impacto limitado | 10 dias úteis | 30 dias úteis |
| Baixa | Hardening, disclosure menor, dívida de dependência transitiva | 15 dias úteis | próximo ciclo |

“Correção visada” é o patch na `main` (ou o workaround documentado). Versões
antigas **não** têm janela de patch.

## O que isto ainda não é

- Sem auditoria de segurança externa.
- Sem linha LTS: só a `main` e a última tag, se existir, recebem correção.
- Sem CNA, sem atribuição de CVE daqui, sem programa de recompensa.
- Sem operator Kubernetes, sem OIDC/mTLS no dashboard.
- A imagem de CI **não** é publicada nem assinada: este repositório não tem
registry do Ferroada (nem GHCR, nem Docker Hub). Cosign keyless (OIDC do
GitHub Actions, sem chave longa no repo) está documentado no job `docker`
de `.github/workflows/security.yml` para quando houver registry. Até lá,
o job constrói `ferroada:ci` localmente e para.

## O que já existe (sem vender como selo)

- `cargo audit --deny warnings` no `Dockerfile` e no job `rust` do CI.
Exceções transitivas do Pingora 0.8.1 estão em `.cargo/audit.toml`.
- Fuzz `waf`, `protocol` e `dlp` no CI de pull request (tempo curto por alvo).
- SBOM CycloneDX do crate `ferroada` como **artefacto** de CI, não commitado
no git.
Loading