Reviewate runs AI agents that execute code, read files, and interact with GitHub/GitLab. Because agent behavior is driven by the code being reviewed (which may contain prompt injection attempts), defense in depth matters.
This guide covers hardening options beyond the secure defaults that Reviewate ships out of the box.
Both Docker and Kubernetes backends enforce these controls automatically:
| Control | Docker | Kubernetes |
|---|---|---|
| Non-root execution (UID 1000) | Yes | Yes |
| Read-only root filesystem | Yes | Yes |
| Drop all Linux capabilities | Yes | Via PodSecurityPolicy/PSA |
| No privilege escalation | Yes | Yes |
| Memory and CPU limits | Yes | Yes |
| PID limit (256) | Yes | Via cluster defaults |
| Ephemeral containers (destroyed after review) | Yes | Yes |
/tmp as tmpfs / emptyDir | Yes | Yes (1Gi) |
| Secret scanning (gitleaks) before posting | Yes | Yes |
| Short-lived platform tokens | Yes | Yes |
| Execution timeout (10 min) | Yes | Yes |
By default, review containers have unrestricted network access. This is the most important area to harden.
Review containers need outbound access to:
api.anthropic.com (or your LLM proxy) for AI model callsapi.github.com / github.com for code review operationsgitlab.com (or your self-hosted instance) for GitLab operationsThey do not need access to your database, Redis, backend API, or other internal services. Without network restrictions, a prompt-injected agent could potentially reach these.
The recommended approach for Kubernetes. Apply these to your review jobs namespace:
# Block all incoming traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: reviewate-jobs
spec:
podSelector: {}
policyTypes:
- Ingress
ingress: []
---
# Allow only external HTTPS (block private IPs)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external-egress-only
namespace: reviewate-jobs
spec:
podSelector: {}
policyTypes:
- Egress
egress:
# DNS resolution
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# HTTPS to external IPs only
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
ports:
- protocol: TCP
port: 443
This blocks access to all cluster-internal services while allowing the agent to reach GitHub, GitLab, and the Anthropic API.
REVIEWATE_BASE_URL) or self-hosted GitLab runs on a private IP, add a specific egress rule for that address. Otherwise the agent won't be able to reach it.For Docker Compose, place review containers on a separate network that has no route to your internal services:
# docker-compose.override.yml
networks:
review-network:
driver: bridge
internal: false # allows internet egress
Then set network: review-network in your container plugin config. This prevents review containers from reaching Redis, Postgres, or the backend on the internal network.
For stricter control, use internal: true with an HTTP proxy that allowlists specific domains.
Review containers receive credentials as environment variables:
ANTHROPIC_API_KEY — LLM API accessGITHUB_TOKEN / GITLAB_TOKEN — Platform access (short-lived)On Kubernetes, these are stored in ephemeral Secrets with ownerReference (auto-deleted with the Job). On Docker, they're passed directly as env vars.
For stronger credential isolation, run an LLM proxy outside the container that injects the API key. The container sends requests to the proxy without credentials, and the proxy adds them before forwarding.
LiteLLM is the simplest option — it acts as an LLM gateway with credential injection and rate limiting:
# Run LiteLLM proxy (outside the review container)
litellm --model anthropic/claude-sonnet-4-20250514 --api_key $ANTHROPIC_API_KEY
# Configure Reviewate to use the proxy (no API key needed in container)
REVIEWATE_BASE_URL=http://litellm-proxy:4000
With this pattern, the review container never sees the Anthropic API key. Even if compromised, it can only make requests through the proxy.
The same approach works for platform tokens, though it requires a TLS-terminating proxy (like Envoy or mitmproxy) since gh and glab CLI tools communicate over HTTPS.
Review pods use a ServiceAccount (reviewate) that should have zero RBAC permissions. Verify this:
# Should return "no" for everything
kubectl auth can-i --list --as=system:serviceaccount:reviewate-jobs:reviewate
If your cluster has default ServiceAccount token mounting, disable it:
apiVersion: v1
kind: ServiceAccount
metadata:
name: reviewate
namespace: reviewate-jobs
automountServiceAccountToken: false