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
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: CI

on:
push:
pull_request:

permissions:
contents: read

jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip
- name: Install project and test dependencies
run: python -m pip install -e ".[dev]"
- name: Compile source
run: python -m compileall -q main.py src
- name: Run tests
run: python -m pytest -q
48 changes: 28 additions & 20 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
# attack_surface_mapper_project_v10.22
# Attack Surface Mapper

## v10.22.9 quality hardening

- Repairs corrupted UTF-8 text in API/auth validation evidence so generated Spanish reports remain readable and professional.
- Adds a minimal GitHub Actions quality gate for source compilation and the full pytest suite.
- Adds a regression test that rejects mojibake markers in Python source files.
- Aligns the package name, version and description with the public project identity.
- Repairs legacy changelog encoding so the project history is readable.

## v10.22.8 polish

- Añade un exportador independiente de Elasticsearch (`scripts/export_elasticsearch_bundle.py`) que empaqueta findings, summaries y run manifest desde un run ya generado sin tocar el pipeline principal.
- Genera mappings estables, NDJSON `_bulk` y helpers de ingesta para las tres vías pedidas por el tutor: manual/Kibana Dev Tools, `curl` y Python.
- Reutiliza el contrato actual del hallazgo (`finding_id`, `correlation_id`, `priority_score`, `finding_role`, `validated`, `validation_basis`, etc.) y evita exportar `raw` completo para mantener los índices más estables.

- Introduce un scoring estructurado (`scoring_version`, `priority_score`) basado en severidad, confianza, rol del hallazgo y base de validación, manteniendo la salida `low/medium/high/critical` pero haciéndola más estable y auditable.
- Expone el score numérico y su razón en reportes, CSV, agregados y matriz de revisión para facilitar comparativas futuras e ingest estructurado.
- Introduce un scoring estructurado (`scoring_version`, `priority_score`) basado en severidad, confianza, rol del hallazgo y base de validación, manteniendo la salida `low/medium/high/critical` pero haciéndola más estable y auditable.
- Expone el score numérico y su razón en reportes, CSV, agregados y matriz de revisión para facilitar comparativas futuras e ingest estructurado.
- Ajusta `comparison.json` para detectar cambios en `priority_score` aunque la etiqueta de prioridad no cambie, mejorando el seguimiento fino entre runs.

- Introduce una capa de validación explícita en el modelo de hallazgo con `finding_role`, `validated` y `validation_basis`, separando mejor descubrimiento, candidatos y evidencia validada.
- Propaga esa semántica a `report.summary.json`, `aggregate_summary.json`, `comparison.json` y la matriz de revisión para dejar el output estructurado más estable y más honesto.
- Mantiene compatibilidad con hallazgos previos o JSON legacy: reporting, agregado y comparación infieren el rol de validación cuando el campo nuevo todavía no existe.
- Amplía el golden set y la exportación de revisión con `finding_role`, `validated` y `validation_basis` para afinar falsos positivos con una semántica más clara.
- Introduce una capa de validación explícita en el modelo de hallazgo con `finding_role`, `validated` y `validation_basis`, separando mejor descubrimiento, candidatos y evidencia validada.
- Propaga esa semántica a `report.summary.json`, `aggregate_summary.json`, `comparison.json` y la matriz de revisión para dejar el output estructurado más estable y más honesto.
- Mantiene compatibilidad con hallazgos previos o JSON legacy: reporting, agregado y comparación infieren el rol de validación cuando el campo nuevo todavía no existe.
- Amplía el golden set y la exportación de revisión con `finding_role`, `validated` y `validation_basis` para afinar falsos positivos con una semántica más clara.

- Conserva el `debug_http_trace` de browser discovery y validación pasiva en una misma ejecución para facilitar análisis de ruido y troubleshooting.
- Ajusta el resumen ejecutivo para que la nota sobre hallazgos altos/críticos confirmados dependa de los datos reales del run.
Expand All @@ -27,21 +35,21 @@
- Estabiliza `report.summary.json`, `aggregate_summary.json` y `run_manifest.json` con secciones y claves más predecibles para futuro consumo estructurado.
- Endurece `scripts/validate_labs.ps1` para validar artefactos generados, IDs estables y un mínimo configurable de hallazgos.
- Reduce falsos positivos de `APIValidator` descartando pantallas de login servidas desde rutas como `/swagger` o `/graphql`.
- Enriquece `comparison.json` y la sección de comparativa en reportes con promociones, regresiones y cambios de confianza/verificación.
- Alinea mejor `verification_status`, `needs_manual_validation` y prioridad para que un hallazgo `confirmed` no siga marcado como revisión manual por inercia de categoría.
- Añade una matriz de revisión exportable (`reviews/lab_findings_review.csv`) para etiquetar hallazgos de labs como `verdadero`, `falso` o `dudoso` durante el afinado de falsos positivos.
- Ajusta la priorización de correlación para dar más peso a evidencia `confirmed` y evita que la mera multiplicidad de fuentes infle hallazgos todavía `likely`.
- Enriquece `comparison.json` y la sección de comparativa en reportes con promociones, regresiones y cambios de confianza/verificación.
- Alinea mejor `verification_status`, `needs_manual_validation` y prioridad para que un hallazgo `confirmed` no siga marcado como revisión manual por inercia de categoría.
- Añade una matriz de revisión exportable (`reviews/lab_findings_review.csv`) para etiquetar hallazgos de labs como `verdadero`, `falso` o `dudoso` durante el afinado de falsos positivos.
- Ajusta la priorización de correlación para dar más peso a evidencia `confirmed` y evita que la mera multiplicidad de fuentes infle hallazgos todavía `likely`.

- Permite validar `passive-recon-enum` dentro del flujo repetible de labs con un override local (`config/examples/lab-passive-recon-enum.yml`) que desactiva Nuclei y mantiene el perfil comparable en Docker.
- Evita que headers confirmados de severidad media, como CSP ausente, escalen a prioridad `high` solo por estar confirmados; la prioridad se reserva mejor para evidencia aplicativa o impacto más claro.
- Endurece `APIValidator`, `PanelsValidator` y `SensitiveFilesValidator` contra superficies de login servidas desde rutas de docs, respuestas HTML que simulan ficheros y respuestas GraphQL demasiado débiles o indistinguibles del fallback.
- Reordena `top_findings` y el agregado para que hallazgos confirmados de aplicación queden por delante de inventario, fingerprints y headers higiénicos cuando comparten prioridad similar.

- Acota mejor la prioridad de documentación y superficies API: `Swagger UI Exposed` deja de escalar a `critical`, `GraphQL Endpoint Accessible Without Authentication` se mantiene en `medium` cuando sigue en `likely`, y el inventario `Multiple API Endpoints Exposed` no compite como si fuese una confirmación de impacto.
- Ajusta la matriz de revisión para que headers de higiene y superficies de inventario API queden en `revisar` o `descubrimiento`, evitando priorizar por defecto hallazgos que todavía son de contexto o endurecimiento.
- Separa mejor el reporting entre riesgo de aplicación, higiene/endurecimiento y descubrimiento: `report.summary.json` expone listas dedicadas (`top_risk_findings`, `top_hygiene_findings`, `top_discovery_findings`) y el markdown mueve headers/TLS a una sección propia para que no compitan visualmente con acceso indebido real.
- Ajusta `AuthValidator` para que rutas de superficie API como `/graphql`, `/swagger` o `/api-docs` no se expresen por defecto como fallo de autorización: ahora se reportan como `api` (`GraphQL Surface Exposed`, `Swagger UI Exposed`, etc.) y se acotan a `likely/medium` salvo evidencia más fuerte.
- Filtra `top_risk_findings` para dejar fuera señales de baja prioridad como CORS amplio `likely` cuando ya existen hallazgos medios/altos más accionables, manteniendo el summary centrado en lo que primero merece revisión.
- Evita que headers confirmados de severidad media, como CSP ausente, escalen a prioridad `high` solo por estar confirmados; la prioridad se reserva mejor para evidencia aplicativa o impacto más claro.
- Endurece `APIValidator`, `PanelsValidator` y `SensitiveFilesValidator` contra superficies de login servidas desde rutas de docs, respuestas HTML que simulan ficheros y respuestas GraphQL demasiado débiles o indistinguibles del fallback.
- Reordena `top_findings` y el agregado para que hallazgos confirmados de aplicación queden por delante de inventario, fingerprints y headers higiénicos cuando comparten prioridad similar.

- Acota mejor la prioridad de documentación y superficies API: `Swagger UI Exposed` deja de escalar a `critical`, `GraphQL Endpoint Accessible Without Authentication` se mantiene en `medium` cuando sigue en `likely`, y el inventario `Multiple API Endpoints Exposed` no compite como si fuese una confirmación de impacto.
- Ajusta la matriz de revisión para que headers de higiene y superficies de inventario API queden en `revisar` o `descubrimiento`, evitando priorizar por defecto hallazgos que todavía son de contexto o endurecimiento.
- Separa mejor el reporting entre riesgo de aplicación, higiene/endurecimiento y descubrimiento: `report.summary.json` expone listas dedicadas (`top_risk_findings`, `top_hygiene_findings`, `top_discovery_findings`) y el markdown mueve headers/TLS a una sección propia para que no compitan visualmente con acceso indebido real.
- Ajusta `AuthValidator` para que rutas de superficie API como `/graphql`, `/swagger` o `/api-docs` no se expresen por defecto como fallo de autorización: ahora se reportan como `api` (`GraphQL Surface Exposed`, `Swagger UI Exposed`, etc.) y se acotan a `likely/medium` salvo evidencia más fuerte.
- Filtra `top_risk_findings` para dejar fuera señales de baja prioridad como CORS amplio `likely` cuando ya existen hallazgos medios/altos más accionables, manteniendo el summary centrado en lo que primero merece revisión.

## v10.22.6 false-positive tuning

Expand Down
11 changes: 8 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "nuclei-mvp-project-v10"
version = "0.10.3"
description = "Nuclei + validaciones propias + correlación + reporting + Nmap + Scrapling por modos (fetcher/dynamic)"
name = "attack-surface-mapper"
version = "10.22.9"
description = "Pipeline-based attack-surface discovery, validation, correlation, and reporting."
requires-python = ">=3.11"
dependencies = [
"requests>=2.31.0",
Expand All @@ -14,6 +14,11 @@ dependencies = [
"playwright>=1.52.0",
]

[project.optional-dependencies]
dev = [
"pytest>=8.3.0,<9",
]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["."]
8 changes: 4 additions & 4 deletions src/attack_surface_mapper/validators/api_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,17 @@ def _classify_path(self, path: str, response, preview: str, content_type: str, b
graphql_signature = ''
if looks_like_login_surface(response, preview):
title = 'API Surface Exposed'
description = 'Se ha detectado una superficie de API accesible públicamente.'
description = 'Se ha detectado una superficie de API accesible públicamente.'
if path in {'/swagger', '/swagger-ui', '/api-docs'}:
title = 'Swagger UI Exposed'
description = 'Se ha detectado una interfaz de documentación Swagger accesible sin restricciones claras.'
description = 'Se ha detectado una interfaz de documentación Swagger accesible sin restricciones claras.'
elif path == '/openapi.json':
title = 'OpenAPI Specification Exposed'
description = 'Se ha detectado un documento OpenAPI/Swagger accesible públicamente.'
description = 'Se ha detectado un documento OpenAPI/Swagger accesible públicamente.'
elif path.startswith('/graphql'):
title = 'GraphQL Surface Exposed'
description = 'Se ha detectado un endpoint o interfaz GraphQL accesible.'
return False, 'low', 'respuesta parece una superficie de login pública', 'discarded', title, description, 'medium'
return False, 'low', 'respuesta parece una superficie de login pública', 'discarded', title, description, 'medium'
score = 0
reasons: list[str] = []
if response.status_code in (200, 201, 202, 204):
Expand Down
2 changes: 1 addition & 1 deletion src/attack_surface_mapper/validators/auth_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def _check_protected_paths(self, session, target: str, host: str | None, port: s
description=description,
severity=severity,
target=response.url,
evidence=f'GET {response.url} devolvió {response.status_code}; validación={reason}',
evidence=f'GET {response.url} devolvió {response.status_code}; validación={reason}',
cwe=['CWE-200'],
tags=['api', 'exposure'],
template_id=f"custom-auth-open-{path.strip('/') or 'root'}",
Expand Down
19 changes: 19 additions & 0 deletions tests/test_source_encoding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from pathlib import Path


def test_public_project_text_has_no_mojibake_markers() -> None:
root = Path(__file__).resolve().parents[1]
source_files = [
root / "main.py",
root / "README.md",
root / "CHANGELOG.md",
root / "pyproject.toml",
*sorted((root / "src").rglob("*.py")),
]
offenders = [
str(path.relative_to(root))
for path in source_files
if any(marker in path.read_text(encoding="utf-8") for marker in ("Ã", "Â", "â€", "�"))
]

assert offenders == []
Loading