Zero Trust for a small SaaS team: the flaws to test for
The underlying flaw: implicit trust
A small SaaS team builds fast, and security often rests on unwritten assumptions: "only our front end calls this route", "this service is not exposed", "only developers have this link". Every one of those assumptions is an open door the day it stops being true. Here are the five forms we see most.
1. So-called internal APIs
An admin endpoint, a cron job called over HTTP, a processing webhook: they are often deployed on the same domain as the app, with no authentication, on the basis that nobody knows the URL. URLs leak through the JavaScript bundle, sitemaps, a third-party tool's logs or a simple scan.
A common variant: a check based on a header the client can forge (X-Forwarded-For: 127.0.0.1, X-Internal: true) or on the source IP behind a proxy.
2. A shared service key
Supabase's service_role key, an admin AWS key or a database token copied into every developer's .env, into CI and sometimes into the front end. That key ignores every authorization rule. One leaked copy is enough. See NEXT_PUBLIC variables that expose secrets and secrets in Git history.
3. Standing production access
Every developer has direct, open-ended access to the production database. A laptop compromised by an infostealer then means full access to customer data.
4. Environments that trust each other
Staging or preview deployments use the same database, keys or identity provider as production, but with weaker protections (no authentication, debug mode).
5. Tool accounts without MFA
GitHub, the hosting provider, the Supabase or Firebase dashboard, email: a single one of those accounts without a second factor hands over the infrastructure.
How to test it
These tests need a browser, curl and your admin consoles:
- Route mapping. Extract every API URL from your front-end bundle (search for
/api/in the served.jsfiles). Call each one with no session. Any response other than 401 or 403 on a route that touches data is a flaw. - Trust headers. Replay a refused request with
X-Forwarded-For: 127.0.0.1,X-Real-IP: 127.0.0.1or an internal header your code reads. If the result changes, authorization depends on client-controlled data. - Key hunt. Search the front-end bundle, repositories and CI for
service_role,AKIA,sk_live,postgres://. A service key in the front end is a critical flaw. - Production access inventory. List the people and tokens that can read the production database. Compare with who actually needs it this week.
- Staging. Open a preview URL while logged out. Check that it does not use the production database or keys.
- Tool MFA. In GitHub, your host and your cloud provider, export the member list and check that the second factor is enforced at organisation level.
- Logs. Run a test export from the production database and check that the event shows up in a log someone actually reads.
How to fix it
- Authenticate every route, including crons and webhooks (shared secret, HMAC signature, narrowly scoped service token). Never base an access decision on an IP or a forgeable header.
- Take service keys off laptops. Keep them in a secrets manager (Doppler, Infisical, your cloud vault), server-side only, and rotate them.
- On-demand production access: one or two people by default, approved temporary access for the rest, using a tool such as Teleport or a home-grown script.
- Really separate environments: distinct databases, keys and projects, previews behind authentication.
- Enforce MFA at organisation level on every tool. See also IAM mistakes on AWS, GCP and Azure.
- Quarterly access review, revoking whatever is no longer used.
What changes when an AI agent joins the team
An AI agent with access to the repository, ticketing, database or email is a new actor that often gets maximum implicit trust: an admin key "to make it work", tools that execute whatever the model asks with no further check. Yet the model reads outside content (emails, tickets, web pages, documents) that can carry hidden instructions.
Zero Trust therefore applies to the agent just as it does to a contractor: its own identity, minimal rights per tool, no service key, authorization checked inside the tool rather than in the prompt, human confirmation for irreversible actions, and logging of every call. Our article on the function calling attack surface goes into these points.
To check that an agent does not slip past those barriers, the Agent Red Team Express attacks it for five days with the injection techniques used in the wild.
Does your product ship an AI agent? CleanIssue tests what a stranger can make it do with the Agent Red Team Express (5 days, €1,900), or a custom red team for several agents and MCP servers. First step: a free 30-minute discovery call.
Related articles
Three adjacent analyses to keep exploring the same attack surface.
Argo CD CVE-2025-55190: repository credentials exposed
CVE-2025-55190 (CVSS 9.9): an Argo CD token with plain get rights on a project can read Git repository credentials. Versions, testing and the fix.
Excessive Agency (LLM06): limit what an AI agent can do
Excessive Agency (OWASP LLM06:2025): reduce an AI agent's functions, permissions and autonomy, with a concrete test plan you can run today.
DGFiP ZeroBytes breach: France's 2026 tax data leak flaws
DGFiP 2026 breach: hijacked agent credentials, a VPN without blanket MFA, overly broad rights, undetected extraction. The flaws and tests.
Sources
Related services
If this topic maps to a real risk in your stack, these are the most relevant CleanIssue audits.