
Modelador de ameaças de IaC com os frameworks STRIDE, MITRE ATT&CK e PASTA. Suporte a REST API, GraphQL e Docker para Terraform, CloudFormation e Kubernetes.
Modelador de ameaças IaC estático que analisa manifestos Terraform, CloudFormation e Kubernetes e produz relatórios estruturados de modelagem de ameaças usando os frameworks STRIDE, MITRE ATT&CK ou PASTA. Sem chamadas de rede, sem credenciais de nuvem, totalmente offline. Funciona como CLI, API REST ou serviço containerizado.
CLI:
pip install threatmap
threatmap scan ./examples --output report.md --fail-on HIGH
Docker:
docker run -v $(pwd):/workspace bogdynn/threatmap:2.1.0 threatmap scan /workspace --output /workspace/report.md
Servidor de API REST:
threatmap serve --host 0.0.0.0 --port 8000
# Ou via Docker:
docker run -p 8000:8000 bogdynn/threatmap:2.1.0
# Endpoints da API: /health, /version, /rules, /analyze
API GraphQL:
docker run -p 8000:8000 bogdynn/threatmap:2.1.0
# Endpoint GraphQL: http://localhost:8000/graphql
# Consultas: health, version, rules
# Mutações: analyze(content, filename, framework)
| Formato | Provedor | Extensão |
|---|---|---|
| Terraform HCL | AWS, Azure, GCP | .tf |
| CloudFormation | AWS | .yaml, .yml, .json |
| Manifestos Kubernetes | Kubernetes | .yaml, .yml |
Instale a partir do PyPI:
pip install threatmap
Ou para desenvolvimento local:
git clone https://github.com/bogdanticu88/threatmap.git
cd threatmap
pip install -e .
Digitalize um diretório e imprima um relatório Markdown na saída padrão:
threatmap scan ./terraform/
Digitalize múltiplos caminhos e escreva um relatório JSON em um arquivo:
threatmap scan ./terraform/ ./k8s/ ./cloudformation/ --format json --output report.json
Gere um relatório HTML interativo ou um relatório SARIF para o GitHub Security:
threatmap scan ./infra/ --format html --output report.html
threatmap scan ./infra/ --format sarif --output report.sarif
Gate de CI — código de saída 1 se qualquer ameaça CRÍTICA ou ALTA for encontrada:
threatmap scan ./infra/ --fail-on HIGH --output threat-report.md
Imprima apenas uma tabela de resumo no terminal, sem gerar um relatório completo:
threatmap scan ./infra/ --summary
Use indicadores de severidade somente ASCII (sem emojis) para ambientes que não suportam Unicode:
threatmap scan ./infra/ --ascii --output report.md
Analise usando diferentes frameworks de modelagem de ameaças:
# STRIDE (padrão)
threatmap scan ./infra/ --framework stride
# MITRE ATT&CK (mapeia para táticas e técnicas)
threatmap scan ./infra/ --framework mitre --format json
# PASTA (modelagem de ameaças centrada em ativos)
threatmap scan ./infra/ --framework pasta --format json
STRIDE (73 regras)
MITRE ATT&CK (11 regras, 14 táticas)
PASTA (12 regras, centrado em ativos)
Executar threatmap scan ./examples --output report.md contra os exemplos incluídos produz um relatório Markdown completo. Abaixo está um trecho representativo.
| ID | Severidade | Categoria STRIDE | Recurso | Descrição |
|---|---|---|---|---|
| T-001 | 🔴 CRÍTICA | Divulgação de Informação | AuditBucket | Bucket S3 'AuditBucket' não possui bloqueio de acesso público configurado — o bucket pode estar acessível publicamente. |
| T-002 | 🔴 CRÍTICA | Spoofing | WebSecurityGroup | Grupo de segurança 'WebSecurityGroup' expõe SSH/RDP (porta 22/3389) para 0.0.0.0/0. |
| T-003 | 🔴 CRÍTICA | Elevação de Privilégio | app_contributor | Atribuição de função 'app_contributor' concede a função privilegiada 'Contributor'. |
| T-006 | 🟠 ALTA | Divulgação de Informação | AuditBucket | Bucket S3 'AuditBucket' não possui criptografia do lado do servidor configurada. |
| T-008 | 🟠 ALTA | Elevação de Privilégio | api | Contêiner 'api' no Deployment 'api' pode ser executado como root (sem runAsNonRoot=true ou runAsUser=0). |
| T-011 | 🟠 ALTA | Elevação de Privilégio | web | Instância EC2 'web' permite IMDSv1 — serviço de metadados acessível sem tokens de sessão, possibilitando roubo de credenciais via SSRF. |
### T-002 — Spoofing (CRÍTICA)
Recurso: AWS::EC2::SecurityGroup.WebSecurityGroup
Propriedade: ingress.ssh_rdp_open
Descoberta: Grupo de segurança 'WebSecurityGroup' expõe SSH/RDP (porta 22/3389) para 0.0.0.0/0.
Mitigação: Remova o acesso público SSH/RDP. Use o AWS Systems Manager Session Manager
ou um bastion host com restrições de IP.
O relatório anexa um diagrama flowchart LR Mermaid. Os nós são coloridos pela severidade do pior caso (🔴 vermelho = CRÍTICA, 🟠 laranja = ALTA). Cole o bloco em qualquer renderizador Mermaid ou visualize diretamente no GitHub.
flowchart LR
Internet((Internet))
subgraph Networking
aws_security_group_web_sg{web_sg}
NetworkPolicy_default_deny{default-deny}
azurerm_network_security_group_app_nsg{app_nsg}
end
subgraph Compute
aws_instance_web[web]
end
subgraph Kubernetes
Namespace_myapp[myapp]
Deployment_api[api]
Service_api_svc[api-svc]
Ingress_api_ingress[api-ingress]
end
subgraph Data
aws_s3_bucket_app_data[(app_data)]
aws_db_instance_app_db[(app_db)]
azurerm_storage_account_app_storage[(app_storage)]
end
subgraph Security
azurerm_key_vault_app_kv[app_kv]
end
subgraph Identity
azurerm_role_assignment_app_contributor[/app_contributor/]
end
AWS__S3__Bucket_AppBucket -->|ref| AWS__S3__Bucket_AuditBucket
AWS__CloudTrail__Trail_AppTrail -->|ref| AWS__S3__Bucket_AuditBucket
Internet -->|HTTPS| Ingress_api_ingress
style aws_security_group_web_sg fill:#ff4444,color:#fff
style aws_s3_bucket_app_data fill:#ff4444,color:#fff
style aws_instance_web fill:#ff8800,color:#fff
style Deployment_api fill:#ff8800,color:#fff
style azurerm_key_vault_app_kv fill:#ffcc00,color:#000
style azurerm_network_security_group_app_nsg fill:#ff8800,color:#fff
style azurerm_role_assignment_app_contributor fill:#ff4444,color:#fff
O threatmap agora inclui Inteligência de Grafo que rastreia relações entre recursos. Ele identifica automaticamente ameaças "encadeadas" onde o comprometimento de um recurso (ex.: uma EC2 exposta à Internet) leva diretamente a outro (ex.: um bucket S3 privado), sinalizando-as como caminhos de ataque de Elevação de Privilégio.
Você pode definir requisitos de segurança internos criando um arquivo threatmap_rules.yaml na raiz do seu projeto.
rules:
- resource_type: "aws_s3_bucket"
property: "force_destroy"
expected: false
stride: "Tampering"
severity: "MEDIUM"
description: "Buckets de produção não devem ter force_destroy habilitado."
mitigation: "Defina force_destroy = false."
A maioria das descobertas agora inclui um campo remediation (visível em relatórios JSON, HTML e SARIF) que fornece o trecho de código exato necessário para corrigir o problema de segurança.
Analisador STRIDE — Regras de ameaça específicas por provedor:
threatmap/analyzers/
├── aws.py # 22 regras — S3, IAM, EC2, RDS, EKS, CloudTrail, KMS, Lambda
├── azure.py # 19 regras — Storage, Key Vault, NSG, RBAC, AKS, ACR, SQL
├── gcp.py # 15 regras — GCS, Firewall, Compute, Cloud SQL, GKE, IAM, KMS
└── kubernetes.py # 17 regras — workloads, RBAC, network, secrets
Analisador MITRE ATT&CK — 11 regras mapeadas para táticas MITRE:
Analisador PASTA — 12 regras com foco centrado em ativos:
APIs:
/health, /version, /rules, /analyze, /analyze/file/graphql com Query (health, version, rules) e Mutation (analyze)Cada regra é uma função que recebe um objeto Resource (normalizado a partir de qualquer formato de origem analisado) e retorna um Threat se a condição for atendida. As regras são condicionais Python simples — sem DSL, sem mecanismo de regex, sem arquivos de regras externas.
A severidade reflete tanto a explorabilidade quanto o raio de explosão:
| Severidade | Significado |
|---|---|
| CRÍTICA | Diretamente explorável sem pré-condições adicionais (ex.: SSH aberto para 0.0.0.0/0, política IAM curinga, vinculação cluster-admin para anônimo) |
| ALTA | Risco significativo que requer uma etapa adicional (ex.: RDS não criptografado com acesso público, IMDSv1 em uma instância EC2) |
| MÉDIA | Controles de defesa em profundidade ausentes — risco imediato menor, mas viola as linhas de base de segurança (ex.: sem versionamento, sem logging, sem limites de recursos) |
| BAIXA | Lacunas de melhores práticas com explorabilidade limitada isolada (ex.: Lambda não em VPC) |
publicly_accessible = true, Principal: "*").metadata_options em uma instância EC2 significa que IMDSv1 está ativo, pois esse é o padrão da AWS).(stride_category, resource_name, trigger_property), portanto, o mesmo problema lógico nunca é relatado duas vezes, mesmo que apareça em múltiplos formatos de arquivo.# .github/workflows/threat-model.yml
name: Threat Model
on: [pull_request]
jobs:
threatmap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install threatmap
run: pip install threatmap
- name: Run threat model scan
run: |
threatmap scan ./infra/ \
--format markdown \
--output threat-report.md \
--fail-on HIGH
- name: Upload threat report
if: always()
uses: actions/upload-artifact@v4
with:
name: threat-report
path: threat-report.md
A flag --fail-on HIGH faz o job sair com código 1 se qualquer ameaça ALTA ou CRÍTICA for encontrada, bloqueando o merge do PR. O artefato enviado dá aos revisores o relatório completo sem sair do pull request.
| Provedor | Regras |
|---|---|
| AWS (Terraform + CloudFormation) | 22 |
| Azure (Terraform) | 19 |
| GCP (Terraform) | 15 |
| Kubernetes | 17 |
| Total | 73 |
Categorias cobertas por provedor:
| Provedor | S | T | R | I | D | E |
|---|---|---|---|---|---|---|
| AWS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Azure | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| GCP | ✓ | ✓ | ✓ | ✓ | — | ✓ |
| Kubernetes | ✓ | ✓ | — | ✓ | ✓ | ✓ |
(S=Spoofing, T=Adulteração, R=Repúdio, I=Divulgação de Informação, D=Negação de Serviço, E=Elevação de Privilégio)
Execute os testes:
pytest tests/ -v
Execute com cobertura:
pytest tests/ --cov=threatmap --cov-report=term-missing
threatmap/analyzers/<provider>.py seguindo o padrão existentetests/fixtures/ que acione a nova regratests/test_analyzers.py