1. Checklist Summary
Use this checklist to track your hardening progress. Each area links to the detailed section below.2. TLS / HTTPS Everywhere
All traffic to and within the KaireonAI platform must be encrypted in transit.2.1 Ingress TLS Termination
Use an AWS ALB or nginx-ingress controller with TLS certificates managed by cert-manager. nginx-ingress with cert-manager:2.2 Internal Service TLS
For service-to-service communication within the cluster, consider a service mesh (Istio or Linkerd) for automatic mTLS. At minimum, ensure no sensitive data traverses unencrypted paths.3. Security Headers
Configure the following HTTP security headers on all responses. These can be set at the ingress level or in the Next.js application middleware.3.1 Ingress-Level Configuration (nginx)
3.2 Content Security Policy
Apply CSP to prevent XSS and data injection attacks. Adjustscript-src and style-src directives based on your CDN and third-party integrations.
unsafe-inline and unsafe-eval in script-src are necessary for Next.js in production. Use nonce-based CSP if your deployment supports it.
3.3 Header Reference
4. Rate Limiting
Protect API endpoints from abuse and denial-of-service attacks.4.1 nginx-ingress Rate Limiting
4.2 Per-Endpoint Rate Limits
For granular control, implement rate limiting in the application layer using the Redis-backed rate limiter.
Authentication endpoints (SOC 2 Phase 0, shipped).
/api/auth/* is
excluded from the Edge middleware’s config.matcher entirely (NextAuth
needs the Node runtime), so it enforces its own limit rather than relying
on a middleware-level rule: POST /api/auth/callback/credentials (the
credentials login endpoint) and the verify action of
POST /api/v1/auth/mfa are both rate-limited per IP, 10 attempts / 5
minutes by default, Redis-backed (pool-wide across all instances) —
configurable via AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW_MS (see
env-vars). The client IP is
taken from the rightmost X-Forwarded-For entry (the edge-appended
real client IP), not the leftmost client-supplied one, so a spoofed
X-Forwarded-For cannot rotate the attacker into a fresh bucket. The
Redis-outage posture differs by surface: login fails open (degrades
gracefully — a Redis outage will not deny all logins, and the per-account
lockout below still limits targeted brute-force during the window; Redis is
not required for login to function), while MFA verify fails closed.
This is layered on top of, not instead of, the pre-existing per-account
lockout (5 failed attempts locks that account for 15 minutes, lib/auth.ts)
and the MFA verify endpoint’s own per-user limit (3 attempts / 60s,
fail-closed). POST /api/v1/auth/register has its own separate per-IP limit
(5/hour) unrelated to AUTH_RATE_LIMIT_MAX.
4.3 Response Headers
Include rate limit information in responses to help clients self-regulate:5. Secret Management
5.1 AWS Secrets Manager + External Secrets Operator (ESO)
Never store secrets in Kubernetes manifests, Helm values, or environment variable files in source control. ExternalSecret resource:5.2 Secret Rotation Policy
5.3 Rotation Procedure
- Create the new secret value in AWS Secrets Manager.
- Update the External Secrets Operator’s external-secret resource if the remote ref path changed.
- Wait for ESO to sync (up to
refreshInterval), or force sync:kubectl annotate externalsecret kaireon-secrets force-sync=$(date +%s) --overwrite. - Perform a rolling restart:
kubectl rollout restart deployment/kaireon-app -n kaireon. - Verify application health after restart.
- Remove the old secret version from Secrets Manager after confirming stability.
6. Network Policies
Restrict pod-to-pod communication to only what is necessary.6.1 Default Deny All
6.2 Allow Application Traffic
7. Pod Security Standards
Apply Kubernetes Pod Security Standards to prevent privilege escalation.7.1 Namespace Label (Restricted)
7.2 Pod Security Context
8. Database SSL
8.1 RDS SSL Configuration
Ensure all database connections use SSL by appendingsslmode=require (or sslmode=verify-full) to the connection string.
8.2 Certificate Bundle
Download the RDS CA certificate bundle and mount it into application pods:8.3 In-Cluster PostgreSQL
For the Startup tier running in-cluster PostgreSQL, enable SSL in the Helm values:9. Audit Log Retention
9.1 Application Audit Logs
KaireonAI emits structured audit log entries for all state-changing API operations. These logs include:- Timestamp (ISO 8601)
- User identity (user ID, email, IP address)
- Action performed (CREATE, UPDATE, DELETE)
- Resource type and identifier
- Request body hash (not the body itself, for sensitive data protection)
- Response status code
9.2 Retention Policy
9.3 Log Forwarding
Use Fluent Bit as a DaemonSet to ship logs from pods to CloudWatch Logs or an external SIEM:9.4 Tamper Protection
- Enable CloudWatch Logs log group data protection for PII detection.
- Use S3 Object Lock (compliance mode) for long-term audit log archives.
- Enable CloudTrail for AWS API audit trail.
10. RBAC and Least-Privilege Access
10.1 Kubernetes RBAC
Create dedicated ServiceAccounts for each component. Do not use thedefault ServiceAccount.
10.2 IAM Roles for Service Accounts (IRSA)
Map Kubernetes ServiceAccounts to IAM roles with minimal permissions:10.3 Database Access Control
- Create separate database roles for the application and workers with the minimum required privileges.
- The application role should have SELECT, INSERT, UPDATE, DELETE on application tables.
- The worker role should have SELECT, INSERT, UPDATE on pipeline-related tables only.
- No role should have DROP, CREATE, or ALTER privileges in production. Schema migrations run as a separate CI/CD step with a privileged role.
11. Additional Hardening
11.1 Dependency and Static Analysis Scanning
- Run
npm auditin CI pipelines. Fail builds on critical or high severity vulnerabilities. (KaireonAI’s own CI does this, plus a blocking Trivy filesystem scan and weekly Dependabot update PRs.) - Run SAST on every pull request. KaireonAI’s CI runs Semgrep (OSS mode, blocking on ERROR-severity findings) across the platform, Shopify, website, and ML worker code.
- Use Snyk or Trivy for container image scanning before pushing to ECR.
- Enable Amazon ECR image scanning on push.
- All shipped KaireonAI container images run as a non-root user (
nextjsin the platform image,workerin the queue worker,appuserin the ML worker).
11.2 Image Provenance
- Use specific image tags, never
latest. - Sign container images with cosign and verify signatures in admission controllers.
- Pull images only from trusted registries (ECR, Docker Hub official images).
11.3 Runtime Protection
- Deploy Falco for runtime anomaly detection (unexpected process execution, file access).
- Enable AWS GuardDuty for EKS runtime threat detection.
- Set
readOnlyRootFilesystem: trueon all containers (writable paths via emptyDir mounts).
12. API Key Authentication
KaireonAI supports API key authentication as an alternative to JWT Bearer tokens.How It Works
- API keys are passed via the
X-API-Keyheader - Keys are stored as SHA-256 hashes in the
api_keysdatabase table (never in plaintext) - Each key has:
name,hashedKey,prefix(first 12 chars of the raw key, for display),tenantId,scopes(per-key scope array; empty = data-plane-only — recommend/respond;["control-plane"]grants management access),expiresAt,lastUsedAt,revokedAt - Keys use the
krn_prefix for easy identification in logs
Production Checklist
- Rotate API keys every 90 days
- Set
expiresAton all keys — never issue non-expiring keys in production - Monitor
kaireon_http_request_duration_secondsfiltered by API key usage patterns - Revoke keys immediately when team members leave (set
revokedAt) - Use separate keys per integration (never share keys across services)
Key Management API
13. Connector Credential Encryption
All connector authentication configurations (authConfig field) are encrypted at rest using AES-256-GCM.
Configuration
Set theCONNECTOR_ENCRYPTION_KEY environment variable to a 32-byte hex string:
How It Works
- On
POST /api/v1/connectors(create) andPUT /api/v1/connectors(update —idis passed in the JSON body), theauthConfigJSON is encrypted before storage - On
GET /api/v1/connectors, credentials are decrypted for display (masked in list view, full in detail for admins) - Each encrypted value includes a random 12-byte IV and 16-byte auth tag
- If
CONNECTOR_ENCRYPTION_KEYis not set, credentials are stored in plaintext (development only)
Production Checklist
- Set
CONNECTOR_ENCRYPTION_KEYin all environments - Store the key in AWS Secrets Manager (see Section 5)
- Rotate the key annually — re-encrypt all connectors after rotation
- Never log or expose the encryption key in application logs