Actionable coding and operational rules for securing relational databases (PostgreSQL, MySQL, SQL Server) using a Zero-Trust approach, end-to-end encryption, strict RBAC and continuous monitoring.
Your database holds your organization's most valuable data. One SQL injection, one misconfigured privilege, or one unpatched vulnerability can cost millions in ransoms, regulatory fines, and lost trust. Traditional perimeter security isn't enough anymore—you need defense in depth with Zero Trust principles baked into every query, connection, and configuration change.
Modern database threats don't knock on the front door—they exploit the gaps between application code and database configuration, leverage privilege escalation, and hide in legitimate traffic patterns. Consider these real attack vectors hitting production systems daily:
Traditional database security approaches fail because they treat the database as a trusted component inside a secure perimeter. But insider threats, lateral movement, and supply chain compromises mean every connection, every query, and every privilege grant must be verified continuously.
These Cursor Rules implement Zero Trust Architecture (ZTA) for relational databases—treating every interaction as potentially hostile while maintaining the performance and functionality your applications demand. Instead of trusting connections from "inside" the network, you verify identity, device posture, and query context on every request.
What makes this different from standard database security:
The rules combine proven security frameworks with practical implementation patterns that scale from startup to enterprise.
# The rules prevent this dangerous pattern automatically
# Bad ❌ - Would be flagged in PR review
cur.execute(f"SELECT * FROM users WHERE email = '{email}'")
# Good ✅ - Enforced pattern
cur.execute("SELECT * FROM users WHERE email = %s", (email,))
Workflow Impact: Developers get immediate feedback on security issues during development, not during security reviews or production incidents.
-- Traditional approach: manual role assignments
GRANT SELECT ON billing.* TO service_account;
-- Zero-trust approach: contextual access
ALTER TABLE billing.invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON billing.invoices
USING (tenant_id = current_setting('app.tenant_id')::uuid);
Workflow Impact: Service accounts automatically get the minimum required access based on request context, eliminating over-privileged access without developer intervention.
When the monitoring system detects unusual query patterns:
Workflow Impact: Security incidents are contained automatically while your team sleeps, preventing lateral movement and data exfiltration.
Clone the security configuration structure:
mkdir -p db/{migrations,security,tests/security,terraform}
Enable core security extensions:
-- PostgreSQL
CREATE EXTENSION IF NOT EXISTS pgaudit;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- MySQL
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- SQL Server
ALTER SERVER AUDIT [DatabaseAudit] WITH (STATE = ON);
Configure network micro-segmentation:
# Terraform example for AWS RDS
resource "aws_security_group" "db_sg" {
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = [var.app_subnet_cidr] # Only app tier
}
}
resource "aws_db_instance" "secure_db" {
storage_encrypted = true
kms_key_id = aws_kms_key.db_key.arn
deletion_protection = true
}
Add security checks to your pipeline:
# GitHub Actions example
- name: SQL Security Scan
run: |
sqlfluff lint --dialect postgres migrations/
sqlmap --batch -u $STAGING_URL --level=5
gitleaks detect --source . --verbose
Configure real-time monitoring:
# Example webhook handler for SIEM alerts
def handle_security_alert(event):
if event['severity'] == 'critical':
revoke_active_sessions(event['user_id'])
rotate_credentials(event['service_account'])
isolate_network(event['source_ip'])
The rules transform database security from a reactive, manual process into a proactive, automated defense system. You get enterprise-grade security without the enterprise complexity—and your developers can focus on building features instead of patching vulnerabilities.
Ready to implement Zero Trust database security? These rules provide the complete framework for securing your most critical data assets while maintaining the development velocity your team demands.
# You are an expert in secure relational database engineering (PostgreSQL 14+, MySQL 8+, SQL Server 2022), SQL, Bash, and Python automation.
---
## Key Principles
- Enforce Zero Trust: continuously verify user, device, network, and query context before granting access.
- Prefer immutable infrastructure: any change is deployed via version-controlled migration scripts; never patch manually in production.
- Adopt least privilege by default; escalate temporarily via a just-in-time (JIT) workflow.
- All data must be encrypted: TLS 1.3+ in transit, AES-256-GCM or stronger at rest (including backups and replicas).
- Treat the DBMS as code: schema, roles, policies, and configuration live in Git and undergo code review + CI security checks.
- Fail secure: if a security control is unavailable, deny the request rather than allow it.
---
## SQL-Specific Rules
- Always use parameterized queries or prepared statements. NEVER concatenate SQL strings.
```python
# Bad ❌
cur.execute(f"SELECT * FROM users WHERE email = '{email}'")
# Good ✅
cur.execute("SELECT * FROM users WHERE email = %s", (email,))
```
- Disable or restrict dynamic SQL (EXEC/EXECUTE IMMEDIATE). If unavoidable, wrap inside a vetted stored procedure with strict argument validation.
- Naming
- Schemas: lower_snake_case; objects prefixed by domain (`auth_user`, `sales_invoice`).
- Roles: verb_noun (`read_analytics`, `write_billing`).
- Default privileges: `REVOKE ALL` on database, then grant granular rights per role.
- Use row-level security (RLS) / fine-grained access control:
```sql
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
CREATE POLICY org_isolation ON accounts USING (org_id = current_setting('app.org_id')::uuid);
```
- Separate write and read replicas; mark read connections `SET default_transaction_read_only = ON`.
- Turn on audit extensions/modules: `pgaudit`, SQL Server Audit, MySQL Audit Plugin. Forward logs to SIEM within 30 s.
---
## Error Handling & Validation
- Validate inputs on two layers: application and stored procedure parameter constraints (type, length, whitelist).
- In stored procedures:
- Catch exceptions (`EXCEPTION WHEN others` / `CATCH`) and re-raise with sanitized messages; never leak stack traces or internals.
- Log error code + correlation id via centralized logger table `security_event_log`.
- Always roll back on error; no partial writes.
- Use early returns on invalid state to avoid deeply nested logic:
```sql
IF _requested_rows > 1000 THEN
RAISE EXCEPTION 'Hard limit 1k rows';
END IF;
```
---
## Framework-Specific Rules
### Zero Trust Architecture (ZTA)
- Micro-segment DB network; expose DB ports only to proxy with mutual-TLS (mTLS) + certificate pinning.
- Use ZTNA gateway to enforce contextual policies (user risk score, device posture).
- Implement continuous authentication: re-evaluate MFA token validity every 15 min or upon privilege escalation.
### RBAC & Privilege Management
- Roles are never assigned directly to humans; map IdP groups ➜ DB roles via automation (e.g., Terraform + AzureAD).
- Adopt break-glass accounts stored in offline HSM; exercise quarterly.
### Monitoring & Tooling
- Enable Microsoft Defender for SQL / equivalent to receive real-time vulnerability findings.
- Schedule weekly Nessus scans on DB hosts; block new critical CVEs within 72 h or invoke emergency patch window.
- Integrate sqlmap in CI to fuzz new API endpoints for SQLi.
---
## Testing
- Pre-deployment: run containerized integration DB with anonymized data + `pgTAP`/`utPLSQL` security tests.
- Quarterly external penetration test; track findings in backlog with SLA: critical (7 days), high (30), medium (90).
- Chaos Security: simulate credential theft via fault injection; validate that alerting & MFA challenges trigger.
---
## Performance & Encryption Patterns
- Use cluster-wide Key Management Service (KMS) with envelope encryption; rotate DEK every 90 days, KEK annually.
- Prefer column-level encryption for PII to limit decryption scope; use pgcrypto, MySQL AES_ENCRYPT, SQL Server Always Encrypted.
- For IO-heavy tables, add deterministic encryption only on indexed columns (e.g., SHA-256 + salt) to retain searchability.
- Monitor CPU overhead of TDE; keep <5% by leveraging AES-NI hardware offload.
---
## Security Automation
- CI pipeline steps (fail build on first violation):
1. `sqlfluff lint --dialect postgres` with custom ruleset `L044` to prohibit `*`.
2. `sqlmap --batch -u $STAGING_URL`.
3. `gitleaks detect` to block credential commits.
- CD pipeline:
- Run `terraform plan` security policy checks (`OPA`/`Conftest`).
- Automatic drift detection: nightly `tfsec` + `cfn-nag`.
- Incident response: Webhook from SIEM triggers Lambda/Logic App to
1. revoke session tokens,
2. force rotate affected credentials,
3. quarantine subnet via firewall API.
---
## Common Pitfalls & Guards
- Pitfall: Leaving default `postgres` / `root` superuser enabled.
Guard: Create new admin role, disable password login for default, enforce cert auth.
- Pitfall: Exposing DB port to internet.
Guard: Enforce private subnets + bastion with MFA.
- Pitfall: Shared service accounts.
Guard: Unique, short-lived service principals issued by vault; rotate every 24 h.
---
## Directory & File Conventions
```
db/
├── migrations/ # Flyway/Liquibase migration scripts
├── security/
│ ├── rbac.sql # role definitions
│ ├── rls.sql # row-level security policies
│ └── audit.sql # audit config & triggers
├── tests/
│ └── security/ # pgtap/utplsql tests
└── terraform/ # infrastructure & secret rotation
```
---
End of Rules