Blog Security GitHub GitHub Secret Scanning DevSecOps API

GitHub Secret Scanning Custom Patterns vía REST API: gobierno de secretos como código

Panel de seguridad de GitHub con patrones personalizados de secret scanning gestionados mediante API

GitHub ha anunciado la disponibilidad general de endpoints REST para gestionar Secret Scanning Custom Patterns. El cambio puede parecer una ampliación menor de la API, pero tiene una implicación relevante para equipos de seguridad, plataforma y DevSecOps: parte del gobierno de patrones personalizados deja de depender exclusivamente de operaciones manuales en la interfaz web y puede integrarse en flujos automatizados, auditables y revisables.

La novedad permite realizar operaciones básicas de ciclo de vida sobre patrones personalizados mediante REST API: listar, crear, actualizar y eliminar patrones en los ámbitos admitidos de repositorio, organización y enterprise para clientes de secret scanning. Hay un matiz importante: según el anuncio de GitHub, los dry runs y el paso final de publicación siguen realizándose en la interfaz web. Por tanto, la API no sustituye por completo al flujo visual de validación y publicación, pero sí permite automatizar inventario, preparación, reconciliación y mantenimiento operativo de los patrones.

Secret scanning ya cubre muchos proveedores conocidos, pero las organizaciones rara vez trabajan solo con secretos estándar. Es habitual encontrar tokens internos, claves heredadas, credenciales de appliances, identificadores corporativos, formatos propios de API keys o convenciones de naming que no aparecen en catálogos públicos. Los custom patterns existen precisamente para cubrir esa zona gris: detectar cadenas con formato de secreto que son específicas de una organización.

Qué son los custom patterns en GitHub Secret Scanning

Un patrón personalizado de secret scanning es una regla definida por el usuario o la organización para que GitHub detecte posibles secretos con un formato propio. Normalmente se apoya en expresiones regulares y metadatos asociados al patrón. Por ejemplo, una compañía podría tener tokens internos con un prefijo corporativo, una longitud concreta y un conjunto limitado de caracteres. Si ese token aparece en código cubierto por secret scanning, GitHub puede generar una alerta.

Estos patrones no sustituyen a la detección nativa de GitHub para proveedores soportados. La complementan. Secret scanning seguirá detectando secretos conocidos de proveedores integrados, mientras que los custom patterns permiten incorporar formatos que GitHub no puede conocer de antemano porque pertenecen a cada organización.

Desde una perspectiva de arquitectura de seguridad, esto encaja con una idea sencilla: no basta con activar un producto de detección; hay que modelar qué secretos existen realmente en la plataforma. En entornos con servicios internos, despliegues multi-cloud, integraciones heredadas o plataformas de datos, muchos secretos no tienen una firma pública. Si esos formatos no se documentan y no se convierten en reglas de detección, la organización puede tener una falsa sensación de cobertura.

Qué cambia con la REST API

Hasta ahora, la gestión de custom patterns dependía en gran medida de la interfaz web. Eso puede ser suficiente para equipos pequeños, pero se vuelve frágil en organizaciones con múltiples unidades, decenas o cientos de repositorios y requisitos de auditoría.

La REST API permite incorporar prácticas más maduras:

  • Inventario periódico de patrones existentes.
  • Comparación entre configuración real y configuración esperada.
  • Revisión mediante pull requests antes de modificar definiciones.
  • Automatización parcial del ciclo de vida de los patrones.
  • Trazabilidad de cambios en pipelines y repositorios de configuración.
  • Separación de responsabilidades entre seguridad, plataforma y equipos de producto.

El valor no está solo en llamar a GET, POST, PATCH o DELETE. Está en tratar las reglas de detección como activos de seguridad: con propietario, justificación, pruebas, revisión y proceso de retirada.

Importante: la API anunciada por GitHub cubre operaciones CRUD sobre custom patterns, pero los dry runs y la publicación final del patrón continúan realizándose en la UI. Si diseñas automatizaciones alrededor de esta capacidad, contempla explícitamente ese paso manual o semimanual de validación y publicación.

Modelo mental: patrón, ámbito y ciclo de vida

Antes de automatizar conviene separar tres conceptos: patrón, ámbito y ciclo de vida.

El patrón describe qué se quiere detectar. Debe ser lo bastante específico como para minimizar falsos positivos, pero no tan restrictivo como para dejar fuera variantes válidas del secreto. Una expresión regular demasiado amplia puede generar ruido masivo; una demasiado estricta puede no detectar credenciales reales.

El ámbito define dónde se aplica. GitHub indica que los endpoints están disponibles a nivel de repositorio, organización y enterprise para clientes de secret scanning. Cuanto más amplio sea el ámbito, mayor impacto tendrá una expresión defectuosa. Por eso no conviene promover reglas globales sin validarlas antes en repositorios representativos.

El ciclo de vida determina cómo se propone, prueba, aprueba, crea, publica, revisa y elimina un patrón. Un patrón debería tener, como mínimo:

  • propietario;
  • propósito;
  • formato del secreto que intenta detectar;
  • ejemplos positivos controlados;
  • ejemplos negativos;
  • ámbito previsto;
  • criterio de publicación;
  • criterio de retirada o revisión.

Esta disciplina puede parecer burocrática hasta que se produce un incidente. En ese momento, el equipo necesita responder preguntas muy concretas: qué secretos eran detectables, desde cuándo, en qué repositorios, con qué patrón y con qué precisión esperada.

Autenticación y permisos

Para consumir la REST API de GitHub se necesita un token con permisos adecuados para el ámbito en el que se va a operar. En entornos empresariales conviene preferir GitHub Apps o fine-grained personal access tokens frente a tokens personales amplios. El principio es el mismo que en cualquier integración sensible: mínimo privilegio, ámbito limitado y rotación controlada.

No debe asumirse que un token con capacidad de lectura sobre repositorios pueda modificar configuración de seguridad. Los permisos concretos dependen del endpoint, del ámbito y del tipo de credencial. Antes de implementar una automatización, revisa la documentación oficial vigente de GitHub REST API para confirmar rutas, permisos y campos obligatorios.

Un envoltorio básico para llamadas curl podría centralizar cabeceras, versión de API y token:

#!/usr/bin/env bash
set -euo pipefail

: "${GITHUB_TOKEN:?Debe definir GITHUB_TOKEN}"

GITHUB_API_VERSION="2026-03-10"
GITHUB_API_BASE="https://api.github.com"

curl_github() {
  local method="$1"
  local path="$2"
  local data="${3:-}"

  if [[ -n "$data" ]]; then
    curl --fail-with-body \
      --request "$method" \
      --url "${GITHUB_API_BASE}${path}" \
      --header "Accept: application/vnd.github+json" \
      --header "Authorization: Bearer ${GITHUB_TOKEN}" \
      --header "X-GitHub-Api-Version: ${GITHUB_API_VERSION}" \
      --header "Content-Type: application/json" \
      --data "$data"
  else
    curl --fail-with-body \
      --request "$method" \
      --url "${GITHUB_API_BASE}${path}" \
      --header "Accept: application/vnd.github+json" \
      --header "Authorization: Bearer ${GITHUB_TOKEN}" \
      --header "X-GitHub-Api-Version: ${GITHUB_API_VERSION}"
  fi
}

--fail-with-body ayuda a que los pipelines fallen ante errores HTTP, pero conserva el cuerpo de respuesta para diagnóstico. La cabecera X-GitHub-Api-Version evita depender implícitamente de cambios de versión en la API.

Advertencia: no almacenes GITHUB_TOKEN en el repositorio ni en archivos .env versionados. Usa secretos del sistema de CI/CD, credenciales de GitHub Apps o el mecanismo aprobado por tu plataforma.

Inventariar patrones existentes

La primera automatización útil no es crear patrones, sino inventariar lo que ya existe. Antes de añadir reglas nuevas, el equipo de seguridad necesita saber qué patrones están definidos, en qué ámbito, quién los mantiene y si existen duplicados o reglas obsoletas.

GitHub ha anunciado endpoints de listado para custom patterns en los ámbitos admitidos. En una organización, el flujo conceptual sería:

#!/usr/bin/env bash
set -euo pipefail

: "${GITHUB_TOKEN:?Debe definir GITHUB_TOKEN}"
: "${GITHUB_ORG:?Debe definir GITHUB_ORG}"

GITHUB_API_VERSION="2026-03-10"
GITHUB_API_BASE="https://api.github.com"

curl --fail-with-body \
  --request GET \
  --url "${GITHUB_API_BASE}/orgs/${GITHUB_ORG}/secret-scanning/custom-patterns" \
  --header "Accept: application/vnd.github+json" \
  --header "Authorization: Bearer ${GITHUB_TOKEN}" \
  --header "X-GitHub-Api-Version: ${GITHUB_API_VERSION}"

El path anterior representa el caso de organización. Para repositorios o enterprise, usa la ruta correspondiente documentada por GitHub.

La salida debe tratarse como inventario de seguridad. En un pipeline real, el JSON puede normalizarse con jq, almacenarse como artefacto y compararse contra una definición esperada. Si aparece un patrón manual no declarado, no significa necesariamente que sea incorrecto; puede haber sido creado durante una respuesta urgente a incidente. Pero sí debe reconciliarse y documentarse.

Diseñar patrones antes de crearlos

La facilidad de crear patrones por API no debe llevar a publicar expresiones regulares sin revisión. Una mala regla puede generar cientos de alertas irrelevantes o, peor, no detectar secretos reales.

Un buen patrón suele apoyarse en características estables del formato:

  • prefijo o marcador reconocible;
  • longitud definida;
  • alfabeto permitido;
  • delimitadores;
  • segmentos de versión o entorno;
  • checksum u otra estructura verificable, si existe.

Por ejemplo, si una organización usa tokens internos ficticios con el formato IST_ seguido de 32 caracteres alfanuméricos, una expresión razonable podría ser:

IST_[A-Za-z0-9]{32}

Este formato es solo ilustrativo. No corresponde a un servicio real. La idea es mostrar que un prefijo fijo y una longitud concreta reducen falsos positivos frente a una regla genérica basada en “cualquier cadena larga”.

También conviene evitar reglas basadas únicamente en entropía o longitud. Pueden parecer atractivas, pero en repositorios reales suelen coincidir con hashes, identificadores de build, valores de prueba o datos generados automáticamente.

Probar expresiones antes de enviarlas a GitHub

Aunque GitHub mantenga el dry run en la interfaz web, el equipo puede añadir una primera capa de validación en su propio repositorio de configuración. Las pruebas no sustituyen al dry run oficial, pero ayudan a revisar cambios antes de que lleguen a la consola.

Un ejemplo sencillo en Python:

import re

PATTERN = re.compile(r"IST_[A-Za-z0-9]{32}")

VALID_EXAMPLES = [
    "IST_A1B2C3D4E5F6G7H8I9J0K1L2M3N4P5Q6",
    "export TOKEN=IST_1234567890abcdefABCDEF1234567890",
]

INVALID_EXAMPLES = [
    "IST_short",
    "NOTIST_A1B2C3D4E5F6G7H8I9J0K1L2M3N4P5Q6",
    "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "IST_A1B2C3D4E5F6G7H8I9J0K1L2M3N4P5Q6_EXTRA",
]

for example in VALID_EXAMPLES:
    assert PATTERN.search(example), f"Debe detectar: {example}"

for example in INVALID_EXAMPLES:
    assert not PATTERN.fullmatch(example), f"No debe detectar como token completo: {example}"

print("Pruebas de patrón completadas correctamente")

El punto crítico es incluir casos negativos. En reglas de detección, los ejemplos que no deben alertar son tan importantes como los positivos, porque documentan los límites intencionales del patrón.

Crear y actualizar patrones con cautela

La API permite crear y actualizar patrones, pero el payload exacto, los campos obligatorios y las restricciones dependen de la documentación oficial vigente. No conviene copiar estructuras de ejemplo sin validarlas contra la referencia de GitHub.

Una práctica recomendable es separar dos tipos de información:

  1. Definición compatible con GitHub, que contiene únicamente campos aceptados por la API.
  2. Metadatos internos de gobierno, que sirven para auditoría y revisión, pero no deben enviarse a GitHub si la API no los acepta.

Por ejemplo, un archivo interno podría tener esta forma:

{
  "github": {
    "name": "Internal service token",
    "pattern": "IST_[A-Za-z0-9]{32}"
  },
  "governance": {
    "owner": "platform-security",
    "purpose": "Detectar tokens internos de servicios corporativos",
    "scope": "organization",
    "review_cycle": "quarterly"
  },
  "tests": {
    "positive": [
      "IST_A1B2C3D4E5F6G7H8I9J0K1L2M3N4P5Q6"
    ],
    "negative": [
      "IST_short",
      "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    ]
  }
}

El pipeline debería enviar a GitHub solo los campos válidos según la documentación oficial y conservar los metadatos internos para reporting, ownership y auditoría.

Editar un patrón en producción debe tratarse como un cambio sensible. Una modificación pequeña en una expresión regular puede alterar la cobertura de detección en muchos repositorios. Por eso es preferible que los cambios pasen por pull request, revisión de seguridad y validación previa.

Automatización con GitHub Actions

Un caso de uso natural es un workflow que valide patrones en pull requests y prepare la sincronización al fusionar en una rama protegida. Dado que GitHub mantiene el dry run y la publicación final en la UI, el workflow no debería prometer una publicación completamente automática si ese paso todavía requiere intervención visual.

Un flujo razonable podría ser:

  1. Validar sintaxis y pruebas de patrones en pull requests.
  2. Al fusionar en main, comparar definiciones esperadas con patrones existentes.
  3. Crear o actualizar patrones mediante API cuando corresponda.
  4. Generar un informe de cambios pendientes.
  5. Ejecutar dry run y publicación final desde la UI, según el proceso de seguridad definido.

Ejemplo de workflow orientado a validación y preparación:

name: Validate secret scanning custom patterns

on:
  pull_request:
    paths:
      - "security/secret-patterns/**"
      - ".github/workflows/secret-patterns.yml"
  push:
    branches:
      - main
    paths:
      - "security/secret-patterns/**"

permissions:
  contents: read

jobs:
  validate:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout del repositorio
        uses: actions/checkout@v4

      - name: Configurar Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Ejecutar pruebas de patrones
        run: |
          python -m unittest discover security/secret-patterns/tests

  reconcile:
    if: github.event_name == 'push'
    needs: validate
    runs-on: ubuntu-latest

    steps:
      - name: Checkout del repositorio
        uses: actions/checkout@v4

      - name: Preparar reconciliación de patrones
        env:
          GITHUB_TOKEN_FOR_SECURITY_API: $
          GITHUB_ORG: $
        run: |
          ./security/secret-patterns/reconcile-custom-patterns.sh

La separación es deliberada. En pull requests se valida la calidad del cambio. En main se puede preparar o ejecutar la reconciliación mediante API. La publicación final debe respetar el límite indicado por GitHub: dry runs y publishing siguen en la interfaz web.

Gobierno y auditoría

La API aporta mucho valor cuando se combina con un repositorio de configuración. Ese repositorio puede actuar como fuente de verdad para:

  • patrones aprobados;
  • propietarios;
  • justificación;
  • ejemplos de prueba;
  • ámbito previsto;
  • historial de cambios;
  • revisiones periódicas;
  • excepciones documentadas.

Un job periódico puede comparar la configuración real en GitHub con la esperada en el repositorio. Si detecta diferencias, puede abrir una incidencia, generar un informe o bloquear cambios hasta que se reconcilien.

Esta aproximación reduce la deriva de configuración. También mejora la respuesta ante incidentes, porque el equipo puede reconstruir qué regla estaba vigente, cuándo se modificó y bajo qué revisión.

Relación con respuesta a incidentes

Detectar un secreto no equivale a neutralizarlo. Secret scanning es un sensor; no es un mecanismo de contención por sí mismo.

Cuando una alerta identifica una credencial expuesta, el flujo de respuesta debería incluir:

  1. confirmar si la credencial es real;
  2. revocarla o rotarla;
  3. analizar alcance y uso indebido;
  4. revisar logs;
  5. eliminar la causa raíz;
  6. añadir o ajustar patrones si el formato no estaba bien cubierto;
  7. documentar el aprendizaje.

Los custom patterns son especialmente útiles después de incidentes relacionados con secretos internos. Si durante la investigación se descubre un nuevo formato de token o una variante no detectada, el equipo puede convertir ese aprendizaje en una regla revisable.

Riesgos y límites

El principal riesgo técnico es el falso positivo masivo. Si una expresión regular amplia se aplica a toda una organización, puede inundar los canales de seguridad con alertas irrelevantes. Ese ruido degrada la confianza en el sistema y puede ocultar hallazgos reales.

El segundo riesgo es el falso negativo silencioso. Una regla demasiado estricta puede no detectar variaciones válidas del secreto. Esto suele ocurrir cuando el formato real no está documentado o cuando distintos equipos generan credenciales con pequeñas diferencias.

También existe un riesgo de exposición de conocimiento sensible. Documentar que existe un token interno con cierto prefijo y longitud ayuda a defender, pero también puede ayudar a un atacante si esa información se publica en un repositorio accesible indebidamente. Los repositorios de configuración de seguridad deben tener permisos adecuados y revisión estricta.

Por último, no todos los problemas de secretos deberían resolverse con detección posterior al commit. Siempre que sea posible, conviene reducir la existencia de credenciales copiables en entornos de desarrollo. Identidades federadas, credenciales efímeras, managed identities y mecanismos de workload identity reducen el problema en origen. Secret scanning es una red de seguridad, no una excusa para distribuir secretos permanentes.

Recomendación práctica

Para adoptar esta capacidad sin generar ruido, empieza de forma incremental:

  1. Inventaría los patrones existentes.
  2. Selecciona pocos formatos críticos de secretos internos.
  3. Define reglas precisas con ejemplos positivos y negativos.
  4. Valida localmente las expresiones regulares.
  5. Usa la API para listar, crear, actualizar o eliminar patrones según el proceso aprobado.
  6. Ejecuta dry run y publicación final en la UI, tal como requiere GitHub en esta fase.
  7. Audita periódicamente la configuración real frente a la esperada.

La disponibilidad de la REST API para Secret Scanning Custom Patterns convierte una configuración de seguridad en un recurso más gobernable. No elimina la necesidad de criterio técnico, revisión humana ni respuesta a incidentes, pero sí facilita que la detección de secretos propios se gestione con más trazabilidad y menos dependencia de acciones manuales dispersas.

El resultado deseable no es tener muchos patrones, sino tener los patrones correctos: precisos, mantenidos, revisados y conectados con la realidad de la plataforma.

Referencias