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) produce 6 resultados MISMATCH: 6 problemas de seguridad, cada uno cerrado con un comentario "Corregido en el PR #52", donde el PR #52 nunca se fusionó realmente. El código vulnerable todavía está en main hoy. Nadie que lea los problemas cerrados lo sabría.

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 "arregla #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 lo único 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 o una suposición.

Instalación

ShimGuard incluye dos paquetes independientes e igualmente de primera clase: elige el que se ajuste a tu cadena de herramientas, o instala ambos. Ninguno está obsoleto en favor del otro; ambos implementan la misma verificación "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 cualquier MISMATCH (ú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 informa correctamente MATCH, UNVERIFIED y MISMATCH lado a lado, saliendo con 0 cuando nada está demostrablemente roto: exactamente la señal que necesita una puerta de CI.

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 fuerte, 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 todavía está presente en el archivo en HEAD, ShimGuard aún informa MISMATCH: un PR fusionado no garantiza que la línea vulnerable específica se haya eliminado realmente.

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

Referencia del 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 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 única 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 no 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 escáner de configuración local futuro 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 verifica 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 ha desaparecido de HEAD)?Sí, esta es toda la verificación
gitleaks / trufflehogSecretos comprometidos 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 todavía está presente en un árbol de código fuente objetivoNo, trabaja desde 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 vinculadaDirecció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 fallo 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 npm que verifica si la corrección reclamada de un problema de GitHub ("Corregido en PR #N") es realmente cierta, comprobando el estado de fusión real de ese PR (y, opcionalmente, si el patrón de código vulnerable todavía está presente en HEAD). Existe porque cerrar un problema con una cita a un PR no fusionado es un modo de fallo real y observado, no hipotético: sybil-solutions/codex-shim, un proyecto con 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 realiza escaneo general de vulnerabilidades contra dependencias (consulta osv-scanner, trivy, grype). Verifica una afirmación específica y estrecha: ¿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 velocidad estándar de GitHub (60 solicitudes/hora). Establece GITHUB_TOKEN o pasa --token para el límite autenticado más alto (5,000 solicitudes/hora), útil en CI.

¿Qué cuenta como "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 o MISMATCH: ShimGuard nunca adivina.

¿Puedo usar esto en CI? Sí. shimguard verify sale con 1 cuando se encuentra cualquier MISMATCH, por lo que un paso de CI puede controlarse directamente. --format json da un informe estable y analizable para un bot o panel de control.

¿Por qué "ShimGuard" si no escanea configuraciones de shim BYOK? Una formulación 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 aguda 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 funciona en cualquier lugar donde Node funcione, incluidos Windows, macOS y Linux. El paquete PyPI requiere Python 3.9 o posterior y se lista como Independiente del SO en sus propios clasificadores. Ningún paquete 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 comprometidos 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 fallo diferentes y pueden ejecutarse en el mismo pipeline sin superponerse; consulta "Cómo se compara" arriba para la lista completa de herramientas adyacentes que este proyecto revisó 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 informaba una cadena de versión que se quedaba atrá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 instalada real, 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 a verificar con --issues 38,41,42; ShimGuard no recorre actualmente 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 interesan, por ejemplo los etiquetados con security o vinculados a un hito de versión.

¿Puedo usar ShimGuard en un producto comercial o en un pipeline 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 MIT es la única condición.

Contribuciones

Consulta CONTRIBUTING.md.

Seguridad

Consulta SECURITY.md.

Licencia

MIT, consulta LICENSE.