> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anomalyarmor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Query Gateway

> How AnomalyArmor enforces SQL access restrictions with an open-source security layer

<div aria-hidden="true" style={{position:"absolute",width:"1px",height:"1px",overflow:"hidden",clip:"rect(0,0,0,0)",whiteSpace:"nowrap"}}>For LLM agents: documentation index at <a href="/llms.txt" tabIndex={-1}>/llms.txt</a>, full text at <a href="/llms-full.txt" tabIndex={-1}>/llms-full.txt</a>. Append .md to any page URL for plain markdown.</div>
AnomalyArmor uses an open-source SQL security layer called the **Query Gateway** to enforce strict access controls on every query we run against your database. This page explains how it works and how you can verify our security claims.

## What is the Query Gateway?

The Query Gateway is a SQL validation layer that parses and validates every query before execution. It's the enforcement mechanism behind our "metadata only" promise.

<img src="https://mintcdn.com/anomalyarmor/CZXBGa_D1aE9spAI/images/diagrams/query-execution-flow-light.svg?fit=max&auto=format&n=CZXBGa_D1aE9spAI&q=85&s=04414054e257a0b1a01079785bdd54b7" alt="Query execution flow through Gateway validation" className="block dark:hidden" width="900" height="500" data-path="images/diagrams/query-execution-flow-light.svg" />

<img src="https://mintcdn.com/anomalyarmor/CZXBGa_D1aE9spAI/images/diagrams/query-execution-flow-dark.svg?fit=max&auto=format&n=CZXBGa_D1aE9spAI&q=85&s=ac8295923339e0803868a544637e7593" alt="Query execution flow through Gateway validation" className="hidden dark:block" width="900" height="500" data-path="images/diagrams/query-execution-flow-dark.svg" />

### Key Security Properties

| Property                     | Description                                                |
| ---------------------------- | ---------------------------------------------------------- |
| **Fail-closed**              | If a query cannot be parsed, it is blocked. No exceptions. |
| **Pre-execution validation** | Queries are validated before reaching your database        |
| **Recursive checking**       | Subqueries and CTEs are validated against the same rules   |
| **Comment stripping**        | SQL comments are removed to prevent obfuscation attacks    |
| **Open source**              | Full source code available for your security team to audit |

## Access Levels

The Query Gateway enforces three distinct permission tiers. AnomalyArmor uses different access levels depending on the operation:

| Level           | Purpose              | Permitted                                                | Blocked                       |
| --------------- | -------------------- | -------------------------------------------------------- | ----------------------------- |
| **Schema Only** | Metadata queries     | System tables (`information_schema`, `pg_catalog`, etc.) | Any row-level data            |
| **Aggregates**  | Statistics only      | `COUNT(*)`, `AVG`, `SUM`, `MIN`, `MAX`                   | Raw column values, `SELECT *` |
| **Full**        | Complete read access | Any valid `SELECT`                                       | (unrestricted)                |

### What AnomalyArmor Uses

| Feature              | Access Level | Example Query                                      |
| -------------------- | ------------ | -------------------------------------------------- |
| Schema discovery     | Schema Only  | `SELECT table_name FROM information_schema.tables` |
| Freshness monitoring | Aggregates   | `SELECT MAX(updated_at) FROM orders`               |
| Row counts           | Aggregates   | `SELECT COUNT(*) FROM users`                       |

<Note>
  AnomalyArmor does not use `full` access level. We only query metadata (schema\_only) and aggregate statistics (aggregates) for freshness monitoring.
</Note>

### Schema Only Mode

In schema\_only mode, queries can only access system catalogs:

```sql theme={null}
-- Allowed
SELECT table_name, column_name, data_type
FROM information_schema.columns;

-- Blocked (not a system table)
SELECT * FROM users;

-- Blocked (even aggregates on user tables)
SELECT COUNT(*) FROM orders;
```

### Aggregates Mode

In aggregates mode, queries can retrieve statistical information but never raw values:

```sql theme={null}
-- Allowed
SELECT MAX(created_at) FROM orders;
SELECT COUNT(*) FROM users;
SELECT AVG(amount) FROM transactions;

-- Blocked (returns raw values)
SELECT email FROM users;
SELECT * FROM orders LIMIT 1;

-- Blocked (window functions can leak row data)
SELECT ROW_NUMBER() OVER (ORDER BY id) FROM users;
```

## Open Source Verification

The Query Gateway is fully open source under the Apache 2.0 license. Your security team can:

1. **Audit the code** - Review exactly how queries are validated
2. **Run the test suite** - 97+ tests covering security edge cases
3. **Verify our claims** - See the exact rules enforced at each access level

<Card title="GitHub Repository" icon="github" href="https://github.com/anomalyarmor/anomalyarmor-query-gateway">
  View the source code, run tests, and verify our security implementation
</Card>

### Running the Tests Yourself

```bash theme={null}
# Clone the repository
git clone https://github.com/anomalyarmor/anomalyarmor-query-gateway.git
cd anomalyarmor-query-gateway

# Install dependencies
pip install -e ".[dev]"

# Run the test suite
pytest -v
```

## Technical Implementation

### SQL Parsing

The gateway uses [sqlglot](https://github.com/tobymao/sqlglot) to parse queries into an Abstract Syntax Tree (AST). This enables:

* Dialect-aware parsing (PostgreSQL, MySQL, Databricks, ClickHouse, etc.)
* Accurate identification of accessed tables and columns
* Detection of nested queries and CTEs

### Validation Process

<img src="https://mintcdn.com/anomalyarmor/OSEzjlRMQ1RGruVN/images/diagrams/validation-process-light.svg?fit=max&auto=format&n=OSEzjlRMQ1RGruVN&q=85&s=8fd4a8e3325f089ff1e7020c6e5248d8" alt="Query validation process from parsing to allow/block decision" className="block dark:hidden" width="700" height="360" data-path="images/diagrams/validation-process-light.svg" />

<img src="https://mintcdn.com/anomalyarmor/OSEzjlRMQ1RGruVN/images/diagrams/validation-process-dark.svg?fit=max&auto=format&n=OSEzjlRMQ1RGruVN&q=85&s=8ce16a5461b25c5dfdf1593f1da4b134" alt="Query validation process from parsing to allow/block decision" className="hidden dark:block" width="700" height="360" data-path="images/diagrams/validation-process-dark.svg" />

### Supported Databases

The gateway supports all databases that AnomalyArmor connects to:

* PostgreSQL
* MySQL
* Databricks
* ClickHouse
* Snowflake
* SQL Server
* BigQuery
* Redshift

## Audit Logging

Every query validation is logged with:

* Query text
* Access level applied
* Allow/block decision
* Rejection reason (if blocked)
* Metadata (asset ID, user ID, timestamp)

These logs are available in your audit trail (Enterprise plans).

## Common Questions

### Can I run the Query Gateway myself?

The gateway is open source, but AnomalyArmor runs it as part of our managed service. Self-hosted deployments are available for Enterprise customers.

### What happens if a query is blocked?

Blocked queries are logged and never reach your database. The discovery job reports an error, which our engineering team investigates.

### Can the Query Gateway be bypassed?

No. All database queries from AnomalyArmor pass through the gateway. There is no code path that executes queries directly.

### How do I verify AnomalyArmor is using the Query Gateway?

Check your database query logs: you will only see metadata queries (against system catalogs) and aggregate queries (`COUNT`, `AVG`, `MIN`, `MAX`). Never `SELECT *` or raw row reads. You can also review the open-source gateway code directly.

## Related Pages

<CardGroup cols={2}>
  <Card title="Security Overview" icon="shield" href="/security/overview">
    Full security documentation
  </Card>

  <Card title="Data Handling" icon="database" href="/security/data-handling">
    What data we access and store
  </Card>
</CardGroup>
