ShimGuard

Servidor MCP que envuelve la CLI de ShimGuard para verificaciones de procedencia de agent-shims.

Documentación

ShimGuard

CI License: MIT npm PyPI version

Verifica que un problema de GitHub cerrado como "corregido" realmente tenga una corrección fusionada, antes de confiar en el rastreador.

Installing shimguard-cli from npm and running its first verify command against the real sybil-solutions/codex-shim repo, reporting 2 MISMATCH results

npx shimguard-cli verify sybil-solutions/codex-shim --issues 38,41,42,43,45,46

Ese único comando contra el repositorio real sybil-solutions/codex-shim (más de 1,000 estrellas) revela 6 resultados de DISCREPANCIA: 6 problemas de seguridad, cada uno cerrado con un comentario de "Corregido en el PR #52", donde el PR #52 nunca se fusionó realmente. El código vulnerable sigue en main hoy. Nadie que lea los problemas cerrados lo sabría.

Contenido

Por qué existe esto

Al leer un rastreador de problemas, confías en dos señales: el estado del problema state (abierto o cerrado) y el comentario de cierre del mantenedor ("corregido en #N"). Ninguna señal está verificada contra la realidad por GitHub mismo. Un mantenedor puede cerrar un problema citando un PR que nunca se fusionó, un bot automatizado puede cerrar por una palabra clave "corrige #N" en la descripción de un PR antes de que ese PR se fusione, o una corrección puede ser revertida después de que el problema ya se cerró. Cualquiera de estos deja un rastreador diciendo "corregido" sobre un error que sigue activo.

ShimGuard verifica la única cosa que un humano que revisa problemas no hace: ¿el PR que el rastreador cita como la corrección realmente muestra merged: true? Es una verificación pequeña, mecánica e inequívoca, no una heurística ni una suposición.

Instalación

ShimGuard incluye dos paquetes independientes e igualmente de primera clase: elige el que se adapte a tu cadena de herramientas, o instala ambos. Ninguno está en desuso en favor del otro; ambos implementan la misma verificación de "problema cerrado cita Corregido en PR #N, ¿está #N realmente fusionado?" contra la misma API REST de GitHub.

# npm -- JavaScript/TypeScript CLI + library
npm install -g shimguard-cli
# or run it once with no install
npx shimguard-cli verify <owner>/<repo> --issues <numbers>

# PyPI -- Python CLI + library (genuine port, not a wrapper around the Node binary)
pip install shimguard-cli

El CLI de npm requiere Node.js 18 o posterior (usa la API integrada fetch). El punto de entrada del CLI del paquete de Python también es shimguard (por ejemplo, shimguard verify sybil-solutions/codex-shim --issues 45,46); consulta python/README.md y docs/getting-started.md para el tutorial específico de Python, y CHANGELOG.md para el historial de versiones de cada distribución.

Inicio rápido

shimguard verify sybil-solutions/codex-shim --issues 38,41,42,43,45,46
ShimGuard v0.1 -- Tracker Verification: sybil-solutions/codex-shim

[MISMATCH] Issue #45 "_resolve_api_key silently falls back to Cursor API key for any model with an empty api_key, forwarding it to arbitrary upstream URLs"
  https://github.com/sybil-solutions/codex-shim/issues/45
  Cited fix: PR #52 (open, not merged)
  Issue is closed and cites PR #52 as the fix, but that PR is open and was never merged.

Summary: 6 MISMATCH, 0 MATCH, 0 UNVERIFIED (6 checked)

El código de salida es 1 cuando se encuentra alguna DISCREPANCIA (útil para controlar CI), 0 cuando cada corrección reclamada de los problemas verificados realmente se fusionó, 2 en un error de uso o de red.

ShimGuard no es solo un buscador de errores: ejecútalo contra una mezcla de problemas y reporta correctamente COINCIDENCIA, NO VERIFICADO y DISCREPANCIA lado a lado, saliendo con 0 cuando nada está demostrablemente roto, exactamente la señal que una puerta de CI necesita.

Running shimguard verify against a mix of issues in the real sybil-solutions/codex-shim repo: one MATCH (merged fix), one UNVERIFIED (no cited fix), exit code 0 since nothing is provably broken

Opcional: verifica el código, no solo el estado de fusión

Para una verificación aún más sólida, apunta ShimGuard al archivo y patrón específicos que un problema nombró como el código vulnerable:

cat > patterns.json <<'EOF'
{
  "45": { "path": "codex_shim/settings.py", "pattern": "cursor_key_fallback" }
}
EOF

shimguard verify sybil-solutions/codex-shim --issues 45 --patterns patterns.json

Si el PR está fusionado pero el patrón citado aún está presente en el archivo en HEAD, ShimGuard aún reporta MISMATCH: un PR fusionado no garantiza que la línea vulnerable específica se haya eliminado realmente.

[!ADVERTENCIA] pattern se compila como un RegExp de JavaScript, y path se valida para permanecer dentro del repositorio objetivo (sin recorrido .. a un repositorio o endpoint de API diferente). Solo apunta --patterns a archivos que escribiste o revisaste tú mismo. Consulta SECURITY.md.

Referencia de CLI

Usage: shimguard [options] [command]

Verify that GitHub issues closed as "fixed" actually have a merged fix. Catches
security issues marked fixed whose PR was never merged.

Options:
  -V, --version            output the version number
  -h, --help               display help for command

Commands:
  verify [options] <repo>  Check whether closed issues in a repo actually have
                           a merged fix
  help [command]           display help for command
Usage: shimguard verify [options] <repo>

Check whether closed issues in a repo actually have a merged fix

Arguments:
  repo                target repo as <owner>/<repo>, e.g.
                      sybil-solutions/codex-shim

Options:
  --issues <numbers>  comma-separated issue numbers to check, e.g. 38,41,42
  --patterns <file>   JSON file mapping issue number -> {path, pattern} for an
                      optional code-pattern check
  --token <token>     GitHub token for higher API rate limits (defaults to
                      $GITHUB_TOKEN)
  --format <format>   output format: text or json (default: "text")
  -h, --help          display help for command

La salida --format json es estable y está diseñada para que scripts y agentes de IA la analicen directamente:

{
  "repo": "sybil-solutions/codex-shim",
  "checked": 1,
  "summary": { "mismatch": 1, "match": 0, "unverified": 0 },
  "results": [
    {
      "issue": { "number": 45, "title": "...", "state": "closed", "htmlUrl": "..." },
      "citedPullRequest": { "number": 52, "state": "open", "merged": false, "htmlUrl": "..." },
      "patternCheck": null,
      "verdict": "MISMATCH",
      "reason": "Issue is closed and cites PR #52 as the fix, but that PR is open and was never merged."
    }
  ]
}

Running shimguard verify with --format json against the real sybil-solutions/codex-shim repo, printing the structured JSON verdict for issue 45

Servidor MCP

ShimGuard incluye un servidor de Protocolo de Contexto de Modelo, para que un agente compatible con MCP (Claude Desktop, Claude Code, Cursor o cualquier otro cliente MCP) pueda llamarlo como una herramienta en lugar de ejecutar el CLI y analizar texto. Es parte de la distribución de Python:

pip install "shimguard-cli[mcp]"

Regístralo con un cliente MCP como Claude Desktop:

{
  "mcpServers": {
    "shimguard": {
      "command": "shimguard-mcp"
    }
  }
}

Expone una sola herramienta, run, que toma exactamente los argv que pasarías al CLI shimguard y devuelve un resultado estructurado ({returncode, stdout, stderr, json?} on success, {error: ...} si el comando falló, expiró o salió con código distinto de cero). Ejemplo de llamada:

run(args=["verify", "sybil-solutions/codex-shim", "--issues", "45,46", "--format", "json"])

que devuelve el mismo informe --format json mostrado arriba, como un campo json analizado junto con el stdout sin procesar. Los detalles completos están en el README del paquete de Python.

API de biblioteca

La lógica de verificación de ShimGuard también se puede importar directamente:

import { TrackerVerifier, RestGitHubClient, RegexPatternMatcher } from "shimguard-cli";

const client = new RestGitHubClient(process.env.GITHUB_TOKEN);
const verifier = new TrackerVerifier(client, new RegexPatternMatcher(client));

const result = await verifier.verify({ owner: "sybil-solutions", repo: "codex-shim", number: 45 });
console.log(result.verdict); // "MISMATCH"

TrackerVerifier toma cualquier GitHubClient y un PatternMatcher opcional (consulta src/types.ts, src/pattern-matcher.ts), ambos son interfaces, por lo que un futuro escáner de configuración local o un host de código diferente pueden conectarse sin cambiar el verificador en sí.

El paquete de Python expone la misma forma:

from shimguard import TrackerVerifier, RestGitHubClient, RegexPatternMatcher, IssueRef

client = RestGitHubClient()  # or RestGitHubClient(token=os.environ["GITHUB_TOKEN"])
verifier = TrackerVerifier(client, RegexPatternMatcher(client))

result = verifier.verify(IssueRef(owner="sybil-solutions", repo="codex-shim", number=45))
print(result.verdict)  # "MISMATCH"

Cómo se compara

Ninguna herramienta de código abierto existente verifica "este rastreador de problemas dice corregido-en-PR-#N, ¿está #N realmente fusionado?" Esa afirmación se verificó buscando herramientas de verificación de corrección de problemas, herramientas de verificación de parches y herramientas de corrección de avisos de seguridad antes de escribir esto. Las herramientas adyacentes más cercanas resuelven problemas diferentes:

HerramientaQué verifica realmente¿Lee el rastreador de problemas / estado de fusión de PR?
ShimGuard¿La afirmación "corregido en PR #N" citada por un problema de GitHub coincide con el estado de fusión real del PR #N (y, opcionalmente, el patrón de código citado desapareció de HEAD)?Sí, esta es toda la verificación
gitleaks / trufflehogSecretos confirmados en el código fuente (claves API, tokens)No, escanea contenido de archivos, no el estado del rastreador
trivy / grype / osv-scannerCVEs conocidos en tu árbol de dependenciasNo, escanea un manifiesto/archivo de bloqueo de dependencias, no el estado del rastreador
Vanir (Google)Si la firma de código de un CVE conocido aún está presente en un árbol de código fuente objetivoNo, trabaja de CVE a código, no toca un rastreador de problemas de GitHub
VFCFinder (NC State, ASIACCS 2024)Encuentra un commit de corrección probable para un aviso que no tiene una corrección vinculada aúnDirección opuesta: encuentra una cita faltante, no verifica una existente

La brecha que ShimGuard llena es real, no teórica. wow-actions/auto-close-fixed-issues, una Acción de GitHub usada por otros repositorios, cierra un problema en el evento closed de un PR, no en su evento merged: un bot puede marcar un problema como "corregido" en el momento en que un PR se cierra, ya sea que realmente se haya fusionado o no. El enlace nativo de GitHub por palabra clave Closes #N solo cierra automáticamente en una fusión real a la rama predeterminada, por lo que este modo de falla específico proviene de comentarios manuales de mantenedores y automatización de terceros, no de los valores predeterminados de GitHub, que es exactamente por qué nada lo detecta después del hecho.

Qué es ShimGuard y por qué existe

ShimGuard es un CLI y una biblioteca, distribuido como un paquete de npm y un paquete de PyPI, que verifica si la corrección reclamada de un problema de GitHub ("Corregido en PR #N") es realmente cierta, verificando el estado de fusión real de ese PR (y, opcionalmente, si el patrón de código vulnerable aún está presente en HEAD). Existe porque cerrar un problema con una cita a un PR no fusionado es un modo de falla real y observado, no hipotético: sybil-solutions/codex-shim, un proyecto de más de 1,000 estrellas, tiene 6 problemas de seguridad cerrados de esta manera al momento de escribir esto, cada uno citando el mismo PR #52 no fusionado. ShimGuard no escanea secretos en el código fuente (consulta gitleaks, trufflehog para eso) y no hace escaneo general de vulnerabilidades contra dependencias (consulta osv-scanner, trivy, grype). Verifica una afirmación específica y limitada: ¿el estado "corregido" de un rastreador coincide con la realidad?

Preguntas frecuentes

¿ShimGuard modifica mi repositorio o el repositorio objetivo? No. Solo hace solicitudes de solo lectura a la API de GitHub (problemas, comentarios, solicitudes de extracción y, opcionalmente, contenido de archivos). Nunca escribe, comenta ni modifica nada.

¿Necesita un token de GitHub? No para uso ocasional. Las solicitudes no autenticadas funcionan, sujetas al límite de tasa estándar de GitHub (60 solicitudes/hora). Configura GITHUB_TOKEN o pasa --token para el límite autenticado más alto (5,000 solicitudes/hora), útil en CI.

¿Qué cuenta como una "corrección citada"? ShimGuard busca frases como "Corregido en PR #52", "corregido por #101" o "resuelto en #20" en el cuerpo del problema y sus comentarios, y extrae el número de PR referenciado. Si no se encuentra tal frase, el resultado es UNVERIFIED, no MATCH ni MISMATCH: ShimGuard nunca adivina.

¿Puedo usarlo en CI? Sí. shimguard verify sale con 1 cuando se encuentra alguna DISCREPANCIA, por lo que un paso de CI puede controlarse directamente con él. --format json da un informe estable y analizable para un bot o un panel.

¿Por qué "ShimGuard" si no escanea configuraciones de shim BYOK? Un marco anterior de esta idea era un escáner de seguridad de configuración local más amplio para shims de modelos BYOK (trae tu propia clave). Ese alcance se redujo a la cuña más precisa y defendible: verificar afirmaciones del rastreador contra código fusionado real, que es lo que se lanzó en v0.1. El nombre refleja el caso de origen del proyecto (sybil-solutions/codex-shim, un shim de modelo BYOK), no un alcance que esta versión no tiene.

¿ShimGuard funciona en Windows, macOS y Linux? El CLI de npm requiere Node.js 18 o posterior (para la API integrada fetch) y se ejecuta en cualquier lugar donde Node se ejecute, incluidos Windows, macOS y Linux. El paquete de PyPI requiere Python 3.9 o posterior y se lista como Independiente del Sistema Operativo en sus propios clasificadores. Ninguno de los paquetes tiene una dependencia nativa o compilada.

¿En qué se diferencia ShimGuard de gitleaks o trufflehog? Gitleaks y trufflehog escanean el contenido de archivos en busca de secretos accidentalmente confirmados en un repositorio, cosas como claves API y tokens. ShimGuard no escanea el contenido de archivos en busca de secretos en absoluto: verifica la API de problemas y solicitudes de extracción de GitHub para una discrepancia específica: un problema cerrado como "corregido en PR #N" donde el PR #N nunca se fusionó realmente. Las dos categorías de herramientas detectan modos de falla diferentes y pueden ejecutarse en la misma canalización sin superponerse; consulta "Cómo se compara" arriba para la lista completa de herramientas adyacentes que este proyecto verificó antes de escribir una línea de código.

¿Por qué shimguard --version podría imprimir un número diferente al del paquete instalado? En algunas versiones pasadas, ejecutar shimguard --version reportaba una cadena de versión que iba por detrás de la versión real del paquete instalado: la cadena de versión pasada a commander en src/cli.ts no siempre se incrementaba en la misma versión que un incremento de versión de package.json. Es una discrepancia solo de visualización y no afecta el comportamiento de verify. Para verificar la versión real instalada, lee el package.json del propio paquete o ejecuta npm view shimguard-cli version.

¿ShimGuard escanea automáticamente cada problema cerrado en un repositorio? No. Pasas los números de problema específicos para verificar con --issues 38,41,42; ShimGuard actualmente no recorre el historial completo de problemas cerrados de un repositorio buscando afirmaciones de corrección citadas por sí mismo. Para un repositorio grande, elige los problemas que te importan, por ejemplo, los etiquetados como security o vinculados a un hito de versión.

¿Puedo usar ShimGuard en un producto comercial o en una canalización de CI de pago? Sí. ShimGuard tiene licencia MIT (consulta LICENSE), que permite uso comercial, modificación y redistribución, incluso dentro de un producto de pago o herramienta interna, sin regalías y sin requisito de abrir tu propio código. Mantener el aviso de MIT es la única condición.

Contribuciones

Consulta CONTRIBUTING.md.

Seguridad

Consulta SECURITY.md.

Licencia

MIT, consulta LICENSE.