Skip to main content
Glama

QueryShield

Proxy SQL seguro entre agentes de IA y bases de datos empresariales.

Los agentes llaman a un único endpoint en inglés sencillo (o SQL estructurado). QueryShield:

  1. Traduce lenguaje natural → SQL mediante Claude con almacenamiento en caché de prompts.

  2. Valida cada consulta a nivel de AST: solo se permite SELECT, no se permiten sentencias apiladas, ni funciones prohibidas, y se requiere LIMIT.

  3. Aplica seguridad a nivel de fila por agente: listas blancas de esquemas/tablas e inyección de cláusulas WHERE.

  4. Ejecuta contra la base de datos del cliente y devuelve las filas.

  5. Registra cada intento en una tabla de auditoría de solo adición: solo metadatos, nunca el contenido de las filas.

Los agentes nunca ven las cadenas de conexión.


Inicio rápido

pip install -r requirements.txt
cp .env.example .env
# Set ANTHROPIC_API_KEY, DATABASE_URL, VAULT_KEY (see below)

python -m queryshield.start

Genera una clave Fernet para VAULT_KEY una vez y no la pierdas nunca:

python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"

Flujo de extremo a extremo (curl)

# 1) Boot a tenant. Returns the admin API key — copy it.
curl -X POST localhost:8000/v1/tenants?name=Acme

# 2) Register the customer DB. Connection string is encrypted at rest.
curl -X POST localhost:8000/v1/databases \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "alias": "prod",
    "db_type": "postgresql",
    "connection_string": "postgresql://reader:secret@db.acme.internal:5432/app",
    "allowed_tables": ["users", "orders"]
  }'

# 3) Provision a scoped agent (different from admin) for your AI app.
curl -X POST localhost:8000/v1/agents \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "reporting", "tenant_id": "<tenant>" }'

# 4) Set the agent's RLS policy.
curl -X POST localhost:8000/v1/policies \
  -H 'X-Admin-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "agent_id": "<agent>",
    "database_alias": "prod",
    "allowed_tables": ["users", "orders"],
    "row_filters": { "users": "tenant_id = 42" }
  }'

# 5) The agent queries.
curl -X POST localhost:8000/v1/query \
  -H 'X-API-Key: qs_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "database_alias": "prod",
    "query": "how many active users do we have?",
    "mode": "nl",
    "max_rows": 10
  }'

Integración MCP

Listado en el Registro oficial de MCP como io.github.bch1212/queryshield.

Instala el cliente:

pip install queryshield-mcp

Luego, añade esto a tu configuración de Claude Desktop / Cursor / agente:

{
  "queryshield": {
    "command": "queryshield-mcp",
    "env": { "QUERYSHIELD_API_KEY": "qs_..." }
  }
}

El código fuente del paquete PyPI independiente se encuentra en packages/queryshield-mcp/.

Integración MCP (legado)

Añade esto a cualquier cliente compatible con MCP (Claude Desktop, Cursor, agentes personalizados):

{
  "queryshield": {
    "command": "python",
    "args": ["-m", "queryshield.mcp_server"],
    "env": {
      "QUERYSHIELD_API_KEY": "qs_...",
      "QUERYSHIELD_BASE_URL": "https://api.queryshield.io"
    }
  }
}

Herramientas expuestas:

  • query_database(database_alias, question, max_rows) — lenguaje natural

  • query_database_sql(database_alias, sql, max_rows) — SELECT preconstruido

  • get_audit_log(limit) — intentos recientes para el agente que realiza la llamada


Modelo de seguridad

Amenaza

Defensa

El agente crea un DROP TABLE

El AST de sqlglot rechaza lo que no sea SELECT

El agente cuela un ; y una segunda sentencia

El analizador rechaza len(statements) > 1

El agente usa pg_sleep, xp_cmdshell, ...

Lista de denegación de funciones a nivel de nodo AST

El agente lee tablas fuera de su alcance

Esquema RLS + lista blanca de tablas

El agente lee filas de otros inquilinos

row_filters inyectados mediante AST .where()

La cadena de conexión se filtra en trazas de pila

Cifrada con Fernet, nunca devuelta en ninguna API

El registro de auditoría se convierte en vector de exfiltración

Solo se almacenan metadatos, nunca filas

Rotación de VAULT_KEY

Recifrado de filas con la nueva clave (mediante script)

safety.py es el módulo más importante. Cada comprobación adicional que se añada allí debe incluir una prueba en tests/test_safety.py.


Precios

Nivel

Mensual

Bases de datos

Consultas / mes

Notas

Starter

$500

3

1,000,000

Pro

$1,500

10

10,000,000

exportación de auditoría

Enterprise

$3,500

ilimitado

ilimitado

SSO, webhook SIEM

Objetivo de $32.5K MRR con 15 clientes (10 Pro + 5 Enterprise).


Despliegue

El repositorio está listo para Railway. python -m queryshield.start es el punto de entrada (lee PORT mediante os.getenv, ya que Railway ejecuta el comando de inicio sin un shell). Provee Postgres + (opcionalmente) Redis desde el mercado de Railway y el resto son variables de entorno.

railway up

/health es la comprobación de actividad. /ready devuelve 503 si la base de datos de control no es accesible.


Pruebas

pip install pytest
python -m pytest tests/

42 pruebas cubren:

  • Seguridad AST (24 casos: DDL directo, comentarios, palabras clave codificadas, múltiples sentencias, funciones prohibidas, falta de LIMIT)

  • Motor RLS (6 casos: aplicación de lista blanca, inyección WHERE, conjunción con predicados existentes)

  • Proxy de extremo a extremo contra una "base de datos de cliente" SQLite (5 casos: camino feliz, DML bloqueado, filtrado de filas RLS, lista blanca de tablas, acierto de caché)

  • Integración HTTP mediante FastAPI TestClient (7 casos: aprovisionamiento completo → flujo de consulta, agente con alcance RLS, fallos de autenticación)

A
license - permissive license
-
quality - not tested
C
maintenance

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bch1212/queryshield'

If you have feedback or need assistance with the MCP directory API, please join our Discord server