Skip to content
Closed

Main #39

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
2 changes: 0 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ run:

linters:
disable-all: true
disable:
- staticcheck
enable:
- errcheck
- govet
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `wardex aggregate` to combine multiple framework decisions into one final gate.
- Added `wardex policy check-expiry` to identify expired compliance exceptions in YAML policies.
- **Empirical Risk Calibration**:
- Re-calibrated default `Criticality` and `Exposure` parameters for Hospital (1.5), Startup (0.75), and Dev environments based on NVD/EPSS empirical analysis (PR #35).
- Re-calibrated default `Criticality` and `Exposure` parameters for Hospital (1.5), Startup (0.75), and Infrastructure (1.5) profiles based on NAICS 22 and NVD/EPSS empirical analysis (PR #35).
- **Security Hardening (Team PCP Response)**:
- Implementation of immutable GitHub Actions pinning via SHA256.
- Strict `permissions: read-all` enforcement for `pull_request_target` workflows.
Expand Down
25 changes: 23 additions & 2 deletions README-en.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<a href="README-en.md">English</a> | <a href="README-fr.md">Français</a> | <a href="README-es.md">Castellano</a> | <a href="README.md">Português</a>
<br><br>

<img src="doc/banner.png" alt="Wardex Secure Release Gate Banner" width="800">
</div>

> [!IMPORTANT]
Expand Down Expand Up @@ -80,7 +79,7 @@ Please refer to the [CHANGELOG.md](CHANGELOG.md) for detailed release notes and
## What's New (v1.7.1)

- **Governance Commands (Automation Ready)**: New subcommands for complex workflows: `wardex evaluate` (focused gate check), `wardex aggregate` (composite multi-framework decision), and `wardex policy check-expiry` (audit of YAML policy exceptions).
- **Empirical Risk Calibration**: `Criticality` and `Exposure` parameters re-calibrated for Hospital (1.5), Startup (0.75), and Dev environments based on NVD/EPSS empirical analysis.
- **Empirical Risk Calibration**: `Criticality` and `Exposure` parameters re-calibrated for Hospital (1.5), Startup (0.75), and Infrastructure (1.5) environments based on NVD/EPSS empirical analysis.
- **Human-in-the-Loop EPSS Enrichment (HITL)**: Failed evaluations due to missing EPSS vectors (where Wardex assumes a "fail-close" 1.0) can now be enriched via the FIRST.org API.
- **Strict Semantic Fail-Close**: The `0.05` fallback for unknown scores has been revoked to `0.0`. Without concrete data, Wardex assumes maximum risk.

Expand Down Expand Up @@ -183,6 +182,28 @@ wardex accept verify

Wardex guarantees the integrity of these exceptions using HMAC-SHA256 signatures, append-only audit logs (`JSONL`), and configuration drift detection.

## Contextual Risk — Same CVE, 4 Decisions

Wardex calculates: `FinalRisk = (CVSS x EPSS) x (1 - Compensation) x Criticality x Exposure`

| CVE | CVSS | EPSS | [BANK] | [SAAS] | [INFRA] | [HOSP] |
|---|---|---|---|---|---|---|
| **Log4Shell** | 10.0 | 0.94 | **14.1** `BLOCK` | **3.5** `BLOCK` | **7.1** `BLOCK` | **11.3** `BLOCK` |
| **xz backdoor** | 10.0 | 0.86 | **12.9** `BLOCK` | **3.2** `BLOCK` | **6.5** `BLOCK` | **10.3** `BLOCK` |
| **curl SOCKS5** | 9.8 | 0.26 | **3.8** `BLOCK` | **1.0** `ALLOW` | **1.9** `BLOCK` | **3.1** `BLOCK` |
| **minimist** | 9.8 | 0.01 | **0.1** `ALLOW` | **0.0** `ALLOW` | **0.1** `ALLOW` | **0.1** `ALLOW` |

Validated with **237 real CVEs** and live EPSS scores from FIRST.org:

| Profile | Appetite | BLOCK | ALLOW | % Block |
|---|---|---|---|---|
| [BANK] Tier-1 Bank (DORA) | 0.5 | **176** | 57 | 74% |
| [HOSP] Hospital (HIPAA) | 0.8 | **168** | 63 | 71% |
| [SAAS] Startup SaaS | 2.0 | **111** | 86 | 47% |
| [INFRA] Utilities (NIS2) | 0.3 | **180** | 53 | 76% |

Full report: [EPSS Multi-Context Stress Test Report](doc/epss-stress-test-report.md)

## Local Policy Management

Wardex enables granular management of compliance policies by framework and domain (e.g., ISO 27001) using a simple, validatable YAML schema. Instead of manually creating or editing large files, you can use the `policy` subcommand to safely manipulate controls via automation:
Expand Down
1 change: 0 additions & 1 deletion README-es.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<a href="README-en.md">English</a> | <a href="README-fr.md">Français</a> | <a href="README-es.md">Castellano</a> | <a href="README.md">Português</a>
<br><br>

<img src="doc/banner.png" alt="Wardex Secure Release Gate Banner" width="800">
</div>

> [!IMPORTANT]
Expand Down
1 change: 0 additions & 1 deletion README-fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<a href="README-en.md">English</a> | <a href="README-fr.md">Français</a> | <a href="README-es.md">Castellano</a> | <a href="README.md">Português</a>
<br><br>

<img src="doc/banner.png" alt="Wardex Secure Release Gate Banner" width="800">
</div>

> [!IMPORTANT]
Expand Down
58 changes: 7 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<a href="README-en.md">English</a> | <a href="README-fr.md">Français</a> | <a href="README-es.md">Castellano</a> | <a href="README.md">Português</a>
<br><br>

<img src="doc/banner.png" alt="Wardex Secure Release Gate Banner" width="800">
</div>

> [!IMPORTANT]
Expand Down Expand Up @@ -83,11 +82,7 @@ go install github.com/had-nu/wardex@latest
# Para builds locais (ex: escolher uma tag específica)
git fetch --tags
git checkout v1.7.1
<<<<<<< HEAD
make build
=======
go build -o wardex .
>>>>>>> origin/main
```

Por favor, consulte o [CHANGELOG.md](CHANGELOG.md) para detalhes sobre as notas de lançamento e correções de bugs.
Expand Down Expand Up @@ -139,46 +134,7 @@ Consulte os ficheiros de exemplo para configurar a sua pipeline:
## Novidades (v1.7.1)

- **Comandos de Governança (Automation Ready)**: Novos subcomandos para pipelines complexas: `wardex evaluate` (focado em gate), `wardex aggregate` (decisão composta) e `wardex policy check-expiry` (auditoria de exceções em YAML).
- **Calibração Empírica de Risco**: Parâmetros de `Criticality` e `Exposure` re-calibrados para perfis Hospital (1.5), Startup (0.75) e Dev, baseados em análise estatística de dados NVD/EPSS.
- **Enriquecimento EPSS c/ Human-in-the-Loop (HITL)**: Avaliações falhadas devido a vectores EPSS em falta (onde o Wardex assume "fail-close" 1.0) podem agora ser enriquecidas via API FIRST.org.
- **Fail-Close Semântico Rigoroso**: O fallback de `0.05` para pontuações de vulnerabilidade desconhecidas foi revogado para `0.0`. Sem dados concretos, o Wardex assume risco máximo.

Integrar o **Wardex** no GitHub Actions permite transformar sua pipeline num processo de **Governança de Risco** real. O Wardex atua como um "Release Gate" logo após os seus scans de segurança.

Veja um exemplo prático:

```yaml
# .github/workflows/wardex-gate.yml
jobs:
risk-governance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

# Instalação Segura (v1.7.1)
- name: Install Wardex
run: |
VERSION="v1.7.1"
curl -sSL "https://github.com/had-nu/wardex/releases/download/${VERSION}/wardex_Linux_x86_64.tar.gz" | tar -xz
sudo mv wardex /usr/local/bin/

# Avaliação de Risco
- name: Evaluate Risk Gate
run: |
wardex --config ./doc/examples/wardex-config.yaml \
--gate ./evidence.json \
./doc/examples/policy-nis2.yaml \
--fail-above 0.9
```

Consulte os ficheiros de exemplo para configurar a sua pipeline:
- [Configuração de CI/CD (wardex-config.yaml)](doc/examples/wardex-config.yaml)
- [Exemplo de Política NIS2/ISO27001 (policy-nis2.yaml)](doc/examples/policy-nis2.yaml)

## Novidades (v1.7.1)

- **Comandos de Governança (Automation Ready)**: Novos subcomandos para pipelines complexas: `wardex evaluate` (focado em gate), `wardex aggregate` (decisão composta) e `wardex policy check-expiry` (auditoria de exceções em YAML).
- **Calibração Empírica de Risco**: Parâmetros de `Criticality` e `Exposure` re-calibrados para perfis Hospital (1.5), Startup (0.75) e Dev, baseados em análise estatística de dados NVD/EPSS.
- **Calibração Empírica de Risco**: Parâmetros de `Criticality` e `Exposure` re-calibrados para perfis Hospital (1.5), Startup (0.75) e Infraestrutura Crítica (1.5), baseados em análise estatística de dados NVD/EPSS.
- **Enriquecimento EPSS c/ Human-in-the-Loop (HITL)**: Avaliações falhadas devido a vectores EPSS em falta (onde o Wardex assume "fail-close" 1.0) podem agora ser enriquecidas via API FIRST.org.
- **Fail-Close Semântico Rigoroso**: O fallback de `0.05` para pontuações de vulnerabilidade desconhecidas foi revogado para `0.0`. Sem dados concretos, o Wardex assume risco máximo.

Expand Down Expand Up @@ -255,12 +211,12 @@ O comando consulta a API da FIRST.org (`api.first.org`), obtém as probabilidade

O Wardex calcula: `FinalRisk = (CVSS x EPSS) x (1 - Compensacoes) x Criticidade x Exposicao`

| CVE | CVSS | EPSS | [BANK] | [SAAS] | [DEV] | [HOSP] |
| CVE | CVSS | EPSS | [BANK] | [SAAS] | [INFRA] | [HOSP] |
|---|---|---|---|---|---|---|
| **Log4Shell** | 10.0 | 0.94 | **14.2** `BLOCK` | **2.5** `BLOCK` | **0.3** `ALLOW` | **7.9** `BLOCK` |
| **xz backdoor** | 10.0 | 0.86 | **12.8** `BLOCK` | **2.3** `BLOCK` | **0.2** `ALLOW` | **7.1** `BLOCK` |
| **curl SOCKS5** | 9.8 | 0.26 | **3.9** `BLOCK` | **0.7** `ALLOW` | **0.1** `ALLOW` | **2.1** `BLOCK` |
| **minimist** | 9.8 | 0.01 | **0.1** `ALLOW` | **0.0** `ALLOW` | **0.0** `ALLOW` | **0.1** `ALLOW` |
| **Log4Shell** | 10.0 | 0.94 | **14.1** `BLOCK` | **3.5** `BLOCK` | **7.1** `BLOCK` | **11.3** `BLOCK` |
| **xz backdoor** | 10.0 | 0.86 | **12.9** `BLOCK` | **3.2** `BLOCK` | **6.5** `BLOCK` | **10.3** `BLOCK` |
| **curl SOCKS5** | 9.8 | 0.26 | **3.8** `BLOCK` | **1.0** `ALLOW` | **1.9** `BLOCK` | **3.1** `BLOCK` |
| **minimist** | 9.8 | 0.01 | **0.1** `ALLOW` | **0.0** `ALLOW` | **0.1** `ALLOW` | **0.1** `ALLOW` |

Validado com **237 CVEs reais** e scores EPSS ao vivo da FIRST.org:

Expand All @@ -269,7 +225,7 @@ Validado com **237 CVEs reais** e scores EPSS ao vivo da FIRST.org:
| [BANK] Banco Tier-1 (DORA) | 0.5 | **176** | 57 | 74% |
| [HOSP] Hospital (HIPAA) | 0.8 | **168** | 63 | 71% |
| [SAAS] Startup SaaS | 2.0 | **111** | 86 | 47% |
| [DEV] Dev Sandbox | 4.0 | **0** | 238 | 0% |
| [INFRA] Energia/Águas (NIS2) | 0.3 | **180** | 53 | 76% |

Relatorio completo: [EPSS Multi-Context Stress Test Report](doc/epss-stress-test-report.md)

Expand Down
5 changes: 3 additions & 2 deletions cmd/aggregate/aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ func runAggregate(cmd *cobra.Command, args []string) error {
_, _ = fmt.Fprintln(w, "|------|----------|---------|---------|--------|")
for _, r := range results {
icon := "✅"
if r.decision == "block" {
switch r.decision {
case "block":
icon = "❌"
} else if r.decision == "warn" {
case "warn":
icon = "⚠️"
}
_, _ = fmt.Fprintf(w, "| %s | %s %s | %d | %d | %d |\n",
Expand Down
5 changes: 3 additions & 2 deletions cmd/evaluate/evaluate.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,10 @@ func runEvaluate(cmd *cobra.Command, args []string) error {
_, _ = fmt.Fprintln(w, "|-----|------|------|--------------|----------|")
for _, d := range gateReport.Decisions {
icon := "[OK]"
if d.Decision == "block" {
switch d.Decision {
case "block":
icon = "[BLOCK]"
} else if d.Decision == "warn" {
case "warn":
icon = "[WARN]"
}
_, _ = fmt.Fprintf(w, "| %s | %.1f | %.2f | **%.1f** | %s %s |\n",
Expand Down
65 changes: 65 additions & 0 deletions data/calibration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"metadata": {
"generated_at": "2026-04-04T21:27:43.555957Z",
"corpus_size": 237,
"note": "Synthetic calibration \u2014 VCDB substitute for CI without network access"
},
"calibrations": [
{
"profile_name": "BANK",
"naics_codes": [
"52"
],
"c_alpha": 1.5,
"e_alpha": 0.8,
"c_alpha_source": "FIPS 199 modal=High + regulatory adjustment",
"e_alpha_source": "VCDB access vector distribution: 80.0% internet-facing (mostly internet-facing)",
"n_incidents": 150,
"theta_block": 0.5,
"theta_warn": 0.3,
"n_cves": 237
},
{
"profile_name": "HOSP",
"naics_codes": [
"62"
],
"c_alpha": 1.5,
"e_alpha": 0.8,
"c_alpha_source": "FIPS 199 modal=High + regulatory adjustment",
"e_alpha_source": "VCDB access vector distribution: 71.4% internet-facing (mostly internet-facing)",
"n_incidents": 140,
"theta_block": 0.8,
"theta_warn": 0.5,
"n_cves": 237
},
{
"profile_name": "SAAS",
"naics_codes": [
"51"
],
"c_alpha": 0.75,
"e_alpha": 0.5,
"c_alpha_source": "FIPS 199 modal=Moderate (VCDB n=140)",
"e_alpha_source": "VCDB access vector distribution: 57.1% internet-facing (mixed exposure)",
"n_incidents": 140,
"theta_block": 2.0,
"theta_warn": 1.0,
"n_cves": 237
},
{
"profile_name": "INFRA",
"naics_codes": [
"22"
],
"c_alpha": 1.5,
"e_alpha": 0.5,
"c_alpha_source": "FIPS 199 modal=High + regulatory adjustment",
"e_alpha_source": "VCDB access vector distribution: 50.0% internet-facing (mixed exposure)",
"n_incidents": 100,
"theta_block": 0.3,
"theta_warn": 0.2,
"n_cves": 237
}
]
}
Loading
Loading