Ir al contenido
Volver a Tutoriales

Cómo Auditar y Asegurar APIs Usando el OWASP API Security Top 10

Intermedio · 1 hour 10 minutes · 17 min de lectura · Byte Smith ·

Antes de comenzar

  • Un inventario de APIs o al menos acceso a repositorios de código fuente, configuraciones de API gateway y documentación de servicios
  • Documentación del modelo de autenticación y autorización para las APIs que deseas revisar
  • Un entorno de prueba o staging donde puedas reproducir solicitudes de forma segura
  • Logs de acceso, métricas o telemetría del gateway para las APIs bajo revisión
  • Acceso básico al código fuente o especificaciones OpenAPI

Lo que aprenderás

  • Construir o verificar un inventario real de APIs que incluya APIs públicas, internas, de socios y shadow
  • Auditar la autorización a nivel de objeto, función y tenant de manera más efectiva
  • Revisar validación de entrada, aplicación de esquemas y riesgos estilo mass-assignment
  • Verificar rate limits, controles de abuso y rutas de amplificación de costos
  • Encontrar exposición de datos sensibles en respuestas, logs, rutas de debug y llamadas a terceros
  • Convertir hallazgos de auditoría en un plan de remediación priorizado que tu equipo pueda ejecutar
1
2
3
4
5
6
7
8
9
En esta página

La seguridad de APIs sigue siendo una de las formas más rápidas de sufrir una brecha porque las APIs exponen funciones de negocio, identificadores de objetos, acciones privilegiadas y datos sensibles de una manera que es fácil de automatizar a escala. Una pequeña falla de autorización en un endpoint a menudo puede reproducirse en miles de IDs, tenants u objetos. Por eso una revisión de API no debería detenerse en “usamos OAuth” o “el gateway tiene auth habilitado.”

Las integraciones modernas de IA y SaaS empeoran el problema. Muchos equipos ahora consumen APIs de terceros como si fueran sistemas internos de confianza, hacen proxy de prompts y resultados de IA a través de capas API, y añaden endpoints específicos de socios o beta más rápido de lo que el inventario puede seguir. Esa combinación crea exactamente los tipos de problemas que OWASP destaca en gestión impropia de inventario, consumo de recursos sin restricciones y consumo inseguro de APIs.

Este tutorial te da un flujo de trabajo de auditoría práctico basado en el OWASP API Security Top 10. Construirás un inventario de API utilizable, revisarás autorización y límites de tenant, inspeccionarás esquema y controles de abuso, verificarás exposición de datos, revisarás seguridad operacional y luego convertirás los hallazgos en un plan de remediación que corrija los mayores riesgos primero.

Paso 1: Construye o verifica tu inventario de APIs

No empieces con escaneo de vulnerabilidades. Empieza con visibilidad. Si no sabes qué APIs existen, quién las posee, qué versión está activa y quién puede alcanzarlas, ya estás en territorio API9.

Inventaría APIs públicas, internas, de socios y shadow

Construye un archivo de inventario único que responda estas preguntas para cada superficie API:

  • ¿Cuál es el hostname o base path?
  • ¿Es pública, interna, solo para socios o desconocida?
  • ¿Quién la posee?
  • ¿Qué modelo de auth usa?
  • ¿En qué entorno está?
  • ¿Hay un plan de deprecación documentado?

Archivo: api-inventory.csv

service,base_url,audience,owner,environment,auth,openapi_spec,current_version,status
payments-api,https://api.example.com/payments,public,payments-team,production,oauth2,openapi/payments.yaml,v2,active
admin-api,https://admin-api.internal.example.com,internal,platform-team,production,jwt-rbac,openapi/admin.yaml,v1,active
partner-orders,https://partners.example.com/orders,partner,bizops-team,production,api-key-plus-hmac,openapi/partner-orders.yaml,v1,active
legacy-beta,https://beta-api.example.com,unknown,unknown,production,unknown,missing,v0,investigate

Extrae inventario del código y tráfico, no solo de documentación

La documentación es un punto de partida, no la verdad. Para encontrar endpoints no documentados o obsoletos, combina búsqueda de código fuente y logs de acceso.

Búsqueda de ejemplo en código fuente:

grep -R "router\.\|app\.\|@RequestMapping\|@GetMapping\|@PostMapping" ./services
grep -R "openapi\|swagger" ./services

Inventario de ejemplo derivado de logs JSON de acceso:

jq -r '.host + "," + .method + "," + .path' access.log \
  | sort -u \
  | tee observed-routes.csv

Si tu gateway registra IDs de ruta o nombres de servicio upstream, extrae esos también.

Marca APIs shadow y obsoletas explícitamente

Una auditoría real necesita un apartado para endpoints que aún no comprendes completamente. No los fuerces en “interno” o “seguro” solo para que la hoja de cálculo se vea más limpia.

Crea una hoja de trabajo de revisión:

Archivo: shadow-api-review.md

# Shadow API Review

## beta-api.example.com
- Owner: unknown
- Environment: production
- OpenAPI spec: missing
- Auth model: unknown
- Last seen in traffic: 2026-03-08
- Public DNS: yes
- Action: classify or remove within 7 days

Inventaría versiones y flujos de datos

No inventaríes solo hostnames. Rastrea versiones y rutas de compartición de datos también.

Archivo: api-data-flows.yaml

payments-api:
  inbound_clients:
    - web-app
    - mobile-app
  outbound_dependencies:
    - tax-provider
    - fraud-provider
  sensitive_data:
    - customer-name
    - partial-card-metadata
    - billing-address

partner-orders:
  inbound_clients:
    - reseller-a
    - reseller-b
  outbound_dependencies:
    - warehouse-api
  sensitive_data:
    - customer-email
    - shipping-address
Consejo
Si no puedes responder rápidamente “qué APIs son públicas, cuáles son solo para socios y qué versiones siguen activas,” tu primera remediación es el inventario, no pruebas de penetración.

Ahora deberías tener un inventario de API funcional con rutas reales, audiencias, versiones, propietarios y flujos de datos.

Paso 2: Revisa autenticación y autorización

Esta es la parte de mayor rendimiento de la auditoría. Las mayores brechas de API normalmente provienen de verificaciones de autorización faltantes o inconsistentes, no de payloads exóticos.

Verifica la autorización a nivel de objeto

La autorización a nivel de objeto pregunta: ¿puede este llamador acceder a este objeto específico?

Si tu API carga un registro desde un ID, UUID, slug o clave foránea proporcionada por el usuario, necesitas una verificación de propiedad o política después de la búsqueda y antes de devolver o mutar el objeto.

Archivo: src/middleware/ownership.ts

import { Request, Response, NextFunction } from "express";

export function requireAccountOwnership(
  fetchAccount: (accountId: string) => Promise<{ id: string; tenantId: string } | null>
) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const accountId = req.params.accountId;
    const account = await fetchAccount(accountId);

    if (!account) {
      return res.status(404).json({ error: "Not found" });
    }

    if (account.tenantId !== req.auth?.tenantId) {
      return res.status(403).json({ error: "Forbidden" });
    }

    res.locals.account = account;
    next();
  };
}

Si tu ruta de código parece “leer ID del path, buscar objeto, devolver objeto,” pero nunca verifica tenant o propiedad, eso es una señal de alerta.

Verifica la autorización a nivel de función

La autorización a nivel de función pregunta: ¿puede este llamador acceder a esta función o acción?

Eso incluye rutas de admin, exportaciones, acciones masivas, flujos de aprobación y operaciones de negocio sensibles.

Archivo: src/middleware/requireScope.ts

import { Request, Response, NextFunction } from "express";

export function requireScope(requiredScope: string) {
  return (req: Request, res: Response, next: NextFunction) => {
    const scopes = req.auth?.scopes ?? [];

    if (!scopes.includes(requiredScope)) {
      return res.status(403).json({ error: "Missing required scope" });
    }

    next();
  };
}

Y luego úsalo consistentemente:

app.post(
  "/admin/users/:userId/suspend",
  requireScope("admin:user:suspend"),
  suspendUserHandler
);

Verifica la separación de tenants

Las APIs multi-tenant no deberían depender solo de un ID de tenant proporcionado por el cliente. El contexto de tenant debería venir de claims de auth verificados o búsqueda del lado del servidor, no de un header arbitrario que el cliente puede cambiar.

Mal patrón:

const tenantId = req.headers["x-tenant-id"];

Mejor patrón:

const tenantId = req.auth?.tenantId;

Luego verifica que cada ruta de acceso a datos se restrinja por ese tenant.

Verifica alcance de token, audiencia y expiración

Para cada mecanismo de auth, responde:

  • ¿El token tiene verificación de audiencia?
  • ¿Los scopes o roles son lo suficientemente estrechos?
  • ¿La expiración es razonable?
  • ¿Los refresh tokens se manejan por separado?
  • ¿Un token puede acceder a APIs públicas y de admin?

Crea una matriz de auth simple:

Archivo: auth-matrix.yaml

payments-api:
  auth_type: oauth2-jwt
  audience: payments-api
  scopes:
    - payments:read
    - payments:write
  admin_scopes:
    - payments:refund
  max_access_token_lifetime_minutes: 15

admin-api:
  auth_type: internal-jwt
  audience: admin-api
  scopes:
    - admin:users:read
    - admin:users:suspend
  max_access_token_lifetime_minutes: 10
Advertencia
“Autenticado” no es lo mismo que “autorizado.” Para auditorías de API, asume que cada parámetro de ruta, cada ID de objeto y cada endpoint de acción necesita su propia decisión de autorización.

Ahora deberías saber si tus APIs aplican propiedad, permisos a nivel de acción, límites de tenant y reglas sensatas de alcance de tokens.

Paso 3: Revisa manejo de entrada y controles de esquema

Este paso es donde encuentras bugs estilo mass-assignment, validación débil de queries, parsing inseguro y divergencia de esquemas entre documentación y comportamiento real.

Valida bodies de solicitud contra un esquema

No dependas de sentencias if escritas a mano dispersas en controladores. Usa esquemas de solicitud explícitos para body, parámetros de ruta y parámetros de query.

Archivo: src/validation/updateProfile.ts

import { z } from "zod";

export const updateProfileSchema = z.object({
  displayName: z.string().min(1).max(80),
  marketingOptIn: z.boolean().optional(),
});

Archivo: src/middleware/validateBody.ts

import { AnyZodObject } from "zod";
import { Request, Response, NextFunction } from "express";

export function validateBody(schema: AnyZodObject) {
  return (req: Request, res: Response, next: NextFunction) => {
    const result = schema.safeParse(req.body);

    if (!result.success) {
      return res.status(400).json({
        error: "Invalid request body",
        details: result.error.flatten(),
      });
    }

    req.body = result.data;
    next();
  };
}

Previene exceso de propiedades de objeto

Solo permite propiedades conocidas. No vincules JSON arbitrario a modelos ORM u objetos de actualización directamente.

Mal patrón:

await userRepository.update(req.params.userId, req.body);

Mejor patrón:

const allowed = {
  displayName: req.body.displayName,
  marketingOptIn: req.body.marketingOptIn,
};

await userRepository.update(req.params.userId, allowed);

Valida parámetros de query y paginación

Los parámetros de query son parte de la superficie de ataque también. Aplica rangos y defaults.

Archivo: src/validation/listOrdersQuery.ts

import { z } from "zod";

export const listOrdersQuerySchema = z.object({
  limit: z.coerce.number().int().min(1).max(100).default(25),
  offset: z.coerce.number().int().min(0).default(0),
  status: z.enum(["pending", "paid", "failed"]).optional(),
});

Revisa deserialización y comportamiento del parser

Marca cualquier endpoint que:

  • acepte objetos serializados crudos sin validación de esquema
  • interprete dinámicamente operadores o nombres de campo desde JSON
  • acepte queries GraphQL con controles débiles de complejidad
  • acepte formatos de archivo inseguros o transformaciones de documentos

Alinea OpenAPI con el comportamiento real

Si tu especificación OpenAPI dice que solo displayName es escribible, pero el endpoint realmente acepta isAdmin, tenantId o accountBalance, tienes una brecha entre especificación y runtime.

Un extracto seguro de esquema de solicitud se ve así:

Archivo: openapi/profile.yaml

paths:
  /v1/me/profile:
    patch:
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                displayName:
                  type: string
                  maxLength: 80
                marketingOptIn:
                  type: boolean
Nota
additionalProperties: false es una de las formas más fáciles de reducir la exposición accidental a nivel de propiedad cuando tu tooling y runtime lo soportan.

Ahora deberías saber si tu API aplica esquemas de solicitud, limita propiedades escribibles, restringe parámetros de query y mantiene el comportamiento de runtime alineado con el contrato documentado.

Paso 4: Revisa rate limiting y controles de abuso

Aquí es donde revisas tanto el abuso clásico de API como las rutas modernas de amplificación de costos. No todos los casos de abuso son fuerza bruta. Algunos son abuso de paginación, abuso de exportación masiva, inundaciones de OTP, abuso de gasto de tokens de IA o automatización de flujos de trabajo de socios.

Crea perfiles de rate por ruta

No apliques un solo límite global a todo. Diferentes endpoints necesitan diferentes controles.

Archivo: rate-limit-profile.yaml

routes:
  /v1/auth/login:
    limit_per_minute: 5
    burst: 2
    key: ip_plus_username
  /v1/password/reset:
    limit_per_hour: 3
    key: account_identifier
  /v1/orders/search:
    limit_per_minute: 30
    burst: 10
    key: token_subject
  /v1/ai/generate:
    limit_per_minute: 10
    burst: 2
    key: tenant_id

Añade límites a nivel de implementación

Archivo: src/middleware/rateLimit.ts

import rateLimit from "express-rate-limit";

export const loginRateLimit = rateLimit({
  windowMs: 60 * 1000,
  max: 5,
  standardHeaders: true,
  legacyHeaders: false,
  keyGenerator: (req) => `${req.ip}:${req.body.username ?? "unknown"}`,
});

Revisa protección contra enumeración

Verifica si los atacantes pueden enumerar baratamente:

  • IDs de usuario
  • IDs de cuenta
  • IDs de factura
  • existencia de email
  • flujos de restablecimiento de contraseña
  • tokens de invitación
  • registros de socios

Busca respuestas inconsistentes 404 vs 403, diferencias de timing y bodies de error diferentes para “existe” versus “no existe.”

Revisa abuso de bots y flujos de negocio

Identifica flujos con alto valor de negocio:

  • creación de cupones
  • creación de trials
  • redención de tarjetas de regalo
  • descargas masivas
  • asignación de puestos
  • endpoints de generación de IA
  • endpoints de envío de OTP o email

Añade controles como:

  • cuotas específicas por ruta
  • claves de idempotencia
  • CAPTCHA o desafío en flujos públicos
  • alertas de anomalías en flujos de trabajo
  • encolamiento para trabajos async de alto costo

Revisa rutas de amplificación de costos

Las APIs modernas a menudo proxean costos externos:

  • SMS
  • email
  • renderizado de documentos
  • inferencia de IA
  • geocodificación
  • verificaciones de fraude

Si una ruta puede quemar dinero por solicitud, necesita controles más estrictos que un endpoint normal de solo lectura.

Advertencia
Los controles de abuso no son solo sobre disponibilidad. También son sobre proteger dinero, cuotas de socios y sistemas downstream costosos.

Ahora deberías saber qué endpoints necesitan controles de ráfaga más fuertes, resistencia a enumeración y cuotas conscientes de costos.

Paso 5: Revisa exposición de datos sensibles

Este paso captura APIs que técnicamente requieren auth pero aún exponen demasiados datos al llamador incorrecto, al sink de log incorrecto o al servicio downstream incorrecto.

Audita exposición de campos en respuestas

Para cada recurso sensible, define una allowlist de respuesta por rol o audiencia.

Archivo: src/serializers/customerSerializer.ts

type Customer = {
  id: string;
  email: string;
  fullName: string;
  internalRiskScore: number;
  billingAddress: string;
};

export function serializeCustomerForSelf(customer: Customer) {
  return {
    id: customer.id,
    email: customer.email,
    fullName: customer.fullName,
    billingAddress: customer.billingAddress,
  };
}

export function serializeCustomerForSupport(customer: Customer) {
  return {
    id: customer.id,
    email: customer.email,
    fullName: customer.fullName,
  };
}

No devuelvas entidades ORM completas directamente.

Redacta logs

Los logs de acceso y de aplicación a menudo filtran tokens, emails, números de cuenta o bodies de solicitud completos. Redacta antes de escribir.

Archivo: src/logging/redact.ts

export function redact(value: string): string {
  return value
    .replace(/Bearer\s+[A-Za-z0-9._-]+/g, "Bearer [REDACTED]")
    .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[REDACTED_EMAIL]");
}

Y nunca registres bodies sensibles por defecto en rutas de auth, pagos o prompts de IA.

Elimina o asegura endpoints de debug

Revisa todas las rutas como:

  • /debug
  • /internal
  • /health/details
  • /graphql-playground
  • /swagger
  • /metrics
  • /__admin

Estas a menudo se dejan expuestas porque son “para ops,” pero la exposición en producción debe ser intencional y protegida.

Revisa reenvío a terceros

Si tu API reenvía prompts, payloads, datos de clientes o identificadores a proveedores SaaS externos, documenta y valida ese flujo explícitamente.

Archivo: third-party-forwarding-review.yaml

dependency: external-ai-provider
forwarded_fields:
  - prompt
  - account_tier
  - locale
disallowed_fields:
  - raw_access_token
  - full_payment_card
  - national_id
response_validation: required
timeout_seconds: 15
Consejo
La exposición de datos sensibles es a menudo un problema de serialización, no solo un problema de encriptación. Revisa qué devuelve cada endpoint por rol, no solo si el endpoint está autenticado.

Ahora deberías saber si tus APIs devuelven datos en exceso, filtran información a logs, exponen superficies de debug o reenvían más datos de lo necesario a terceros.

Paso 6: Revisa seguridad operacional

Buenos controles a nivel de código aún fallan si el borde API está mal configurado o si no puedes detectar abuso a tiempo.

Revisa controles de gateway y reverse-proxy

Para cada borde API, verifica:

  • TLS en todos los lugares donde debería estar
  • solo métodos HTTP requeridos expuestos
  • límites de tamaño de body
  • política de timeout de solicitud y upstream
  • propagación de request ID
  • validación de esquema donde sea soportado
  • allowlists de IP para APIs de socios o admin

Revisa monitoreo y alertas

Como mínimo, rastrea:

  • picos de 401 y 403
  • picos de 429
  • latencia a nivel de ruta
  • 5xx a nivel de ruta
  • fallos de auth por endpoint
  • barridos de IDs de objetos de alto volumen
  • tráfico a versiones deprecadas
  • uso inusual de socios

Crea un pequeño checklist de métricas:

Archivo: api-monitoring-checklist.md

# API Monitoring Checklist

- 401/403 dashboard per route
- 429 dashboard per route
- Token subject or tenant-based rate anomaly alerts
- Object enumeration detection on high-value routes
- Deprecated version traffic alerts
- Third-party dependency timeout alerts

Revisa versionamiento y deprecación

Cada versión debería tener:

  • un propietario
  • una audiencia
  • una fecha de fin de vida
  • un plan de comunicación de deprecación
  • una verificación de retiro de tráfico

También puedes exponer headers de deprecación y sunset.

Archivo: src/middleware/deprecation.ts

import { Request, Response, NextFunction } from "express";

export function markDeprecated(res: Response) {
  res.setHeader("Deprecation", "true");
  res.setHeader("Sunset", "Wed, 30 Sep 2026 23:59:59 GMT");
  res.setHeader("Link", '</docs/migrate-v2>; rel="deprecation"');
}

Revisa APIs de socios e internas también

Muchas organizaciones hacen un trabajo decente en APIs públicas y un trabajo débil en APIs “solo internas.” Las rutas internas, de socios y de admin deberían estar inventariadas, versionadas, monitoreadas y revisadas igualmente.

Info
Una API oculta con monitoreo débil es a menudo más peligrosa que una API pública con controles fuertes, porque nadie le está prestando atención.

Ahora deberías saber si el borde API está endurecido, si puedes detectar abuso y si las versiones antiguas y rutas ocultas están siendo gestionadas deliberadamente.

Paso 7: Convierte hallazgos en un plan de remediación

Una auditoría de API solo importa si produce cambios. Los mejores planes de remediación separan la reducción rápida de riesgo del trabajo de diseño que necesita más tiempo.

Captura hallazgos en un formato estructurado

Archivo: api-audit-findings.yaml

findings:
  - id: API-001
    category: API1-BOLA
    service: payments-api
    endpoint: GET /v1/accounts/{accountId}
    severity: critical
    issue: Account lookup does not verify tenant ownership
    quick_fix: Add tenant-scoped query and authorization middleware
    owner: payments-team
    due_in_days: 7

  - id: API-002
    category: API3-BOPLA
    service: partner-orders
    endpoint: PATCH /v1/orders/{id}
    severity: high
    issue: Writable object accepts undocumented internal fields
    quick_fix: Add request schema with explicit allowlist
    owner: bizops-team
    due_in_days: 14

  - id: API-003
    category: API9-Inventory
    service: legacy-beta
    endpoint: unknown
    severity: high
    issue: Public beta host has no owner, no spec, and no retirement plan
    quick_fix: Remove public exposure or assign owner immediately
    owner: platform-team
    due_in_days: 3

Separa correcciones rápidas de correcciones arquitectónicas

Buenas correcciones rápidas:

  • añadir verificaciones de propiedad
  • añadir verificaciones de scope faltantes
  • restringir campos de respuesta
  • añadir validación de esquema
  • reducir límites de ruta
  • deshabilitar endpoints de debug
  • eliminar DNS público o enrutamiento obsoleto

Correcciones arquitectónicas a medio plazo:

  • mover authz a una capa de políticas centralizada
  • separar APIs de admin y públicas
  • rediseñar aislamiento de tenant
  • crear descubrimiento automatizado de inventario
  • añadir controles de política de admisión o gateway
  • estandarizar serializadores de respuesta y generación de esquemas

Asigna propietarios y fechas límite

Cada hallazgo necesita:

  • un equipo propietario
  • una severidad
  • un enfoque de remediación
  • una fecha objetivo
  • un método de validación

Re-prueba la corrección

Una corrección no está completa hasta que puedas probar que la ruta de abuso ya no existe. Para cada hallazgo, guarda una prueba positiva y una negativa.

Archivo: tests/account-ownership.http

### Allowed: own tenant account
GET https://api.example.com/v1/accounts/acc_123
Authorization: Bearer {{tenant_a_token}}

### Blocked: another tenant account
GET https://api.example.com/v1/accounts/acc_999
Authorization: Bearer {{tenant_a_token}}

Problemas Comunes de Configuración

Auditar solo APIs públicas

Los equipos a menudo revisan el gateway público e ignoran superficies internas, de admin, de socios, beta y deprecadas. Eso deja algunas de las rutas de mayor riesgo fuera de la auditoría.

Asumir que autenticación equivale a autorización

Un token válido no es prueba de que el llamador debería acceder a un objeto, campo o función específica. Revisa authz por separado a niveles de objeto, campo, función y tenant.

Encontrar APIs shadow pero no eliminarlas

El trabajo de inventario solo reduce riesgo si las APIs obsoletas o desconocidas obtienen propiedad, protección o eliminación. Una hoja de cálculo sola no cierra la exposición.

Generar especificaciones OpenAPI pero no aplicarlas

Una especificación que no está atada a validación, pruebas o revisión puede divergir hasta convertirse en decoración. Prefiere validación de esquema y pruebas de contrato sobre especificaciones solo de documentación.

Corregir un endpoint en lugar del patrón

Si encuentras un problema de autorización a nivel de objeto, busca el mismo patrón de acceso en todo el código base. Las fallas de API a menudo se repiten por framework, serializador o patrón de repositorio.

Conclusión

Una auditoría de API fuerte comienza con inventario y termina con remediación priorizada. La ruta de revisión de mayor valor es normalmente: verificar todas las superficies API, verificar autorización de objeto y función, restringir esquemas y propiedades escribibles, asegurar controles de abuso, reducir exposición de datos sensibles y luego limpiar brechas operacionales como versiones ocultas y monitoreo débil.

Repite esta auditoría en un calendario, no solo después de incidentes. Una cadencia práctica es trimestral para APIs de alto riesgo, después de cambios importantes de auth o gateway, y siempre que añadas nuevas integraciones de socios, SaaS o dependientes de IA. Para mantener el inventario actualizado, vincula el descubrimiento de rutas a revisión de código, cambios de configuración de gateway y telemetría de tráfico en lugar de depender solo de actualizaciones de documentación.

El objetivo principal no es “pasar OWASP.” Es asegurarse de que tus APIs sean difíciles de enumerar, difíciles de abusar, difíciles de sobre-consumir y fáciles de entender y retirar cuando ya no deberían existir.