# Agent security

An agent with a mailbox and a phone line is not a chatbot with extra features — it is an application holding credentials to systems your business depends on, acting on content written by strangers. The threat model has four parts: who may sign in, what the credentials can reach, what the agent may do once persuaded, and whether anyone can tell afterwards.

- **Status:** Reference
- **Audience:** both, developer
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/technology/agent-security/

## Who may sign in

**Google OAuth is the only sign-in. There is no password login at all**, which removes credential stuffing, reused passwords, weak reset flows and the database of hashes that makes a breach worth having. The cost is honest and worth stating: sign-in depends on Google, and an account without a Google identity cannot be created.

Signing in as somebody else ends the session it replaced **on that browser** — and only that one, never that person's other devices. The distinction is deliberate: a shared machine should not become a way to sign a colleague out of their phone.

## What the credentials can reach

**Provider credentials** — Sealed by `settings_store` on every save and never echoed back to a screen. A screen that can display a secret is a screen that can leak one.
**The database password** — Not in `.env`. RDS manages the master credential and rotates it into Secrets Manager; `MAYA_MAIL_DB_SECRET_ARN` names the secret and boot reads the password from it.
**Workspace data** — Filtered three times — the `customer_safe` allowlist in the middleware, the SQLAlchemy workspace kernel, and PostgreSQL row-level security. Independent layers, so one mistake is not a breach.
**The application's own API description** — `/openapi.json`, `/docs` and `/redoc` are closed and stay closed. The public description is published separately and deliberately.

> **Careful** A stale copy of a rotated password is the failure mode that reads as something else entirely. It survives until the next restart and then authenticates as nobody, which looks like a bad deploy rather than a credential problem — see [a copy of a password somebody else rotates](/research/stale-credentials/).

## Does Connect use these boundaries?

**Used**, all of them, and the isolation is the part worth being specific about because it is the one a tenant is trusting. `tenantAdapt` in the browser rewrites an Owner path to its customer equivalent, and **anything it does not recognise becomes a blocked path that returns 403** rather than falling through to something. Separately, `customer_safe` in `main.py` is an allowlist that refuses any API a customer session is not permitted to call. Then the kernel filters the query, and then row-level security filters the rows.

The rule that keeps the third layer honest is operational: **a new scoped table needs its row-level security applied in the same release**. The table itself appears at boot; the policy comes from a hardening script. A table with a `workspace_id` that is missing from the scoped list is scoped by nothing at all — a defect that looks correct in every code review, because the column is right there. [Three independent layers of tenant isolation](/research/three-layers-of-isolation/) goes through it.

On the agent's own authority: tools run under the session's workspace and permissions, and the Assistant's rights are deliberately **narrower than a person's** — no pricing, no clearing a do-not-contact entry. Withholding a capability is the only control that survives a persuasive attacker, which is why it is used for the two cases where being wrong is worst.

## The threats particular to agents

| Threat | Why an agent makes it worse | What bounds it |
|---|---|---|
| Instructions inside content | The agent reads mail from anyone, by design | Actions are tools with their own checks — see [prompt injection](/docs/technology/prompt-injection/) |
| Over-broad provider scope | One consent can grant far more than reading mail | Request the narrowest scope that does the job, and know which you granted |
| Irreversible action at speed | A person sends one wrong reply; a loop sends many | Autonomy modes, daily allowances, and refusals recorded as decisions |
| Data leaving in a summary | Summaries move content into places the original never reached | Workspace scoping applies to the summary as much as the source |
| Silent partial failure | A step that half-succeeded looks finished | Evidence stored per action rather than one success flag |

Connect holds no certification, and this page does not imply one. What it describes are mechanisms you can check: the sign-in method, the three isolation layers, sealed credentials, the closed endpoints, and a trail that records refusals as well as actions.

## Questions

### What is the blast radius if the model is completely fooled?

Bounded by what the workspace already permits. A fooled model can propose only actions that exist as tools, in the session's own workspace, subject to autonomy and to the withheld capabilities. It cannot reach another workspace, because no argument selects one.

### Can Connect read mail we have not connected?

No. Access comes from a mailbox a workspace connects, with the provider's consent flow and the scopes granted there. Disconnecting the mailbox ends the access, and a stored credential is never displayed back to a screen at any point.

### Is customer data used to train a model?

No. Material is read at answer time and nothing is trained on it. That is also why deleting a source or a memory takes effect on the next answer rather than at some future retraining.

## Related

- [Security and isolation](https://connectbyjbrh.com/docs/security/)
- [Three independent layers of tenant isolation](https://connectbyjbrh.com/research/three-layers-of-isolation/)
- [Prompt injection](https://connectbyjbrh.com/docs/technology/prompt-injection/)
- [Secret management](https://connectbyjbrh.com/docs/technology/secret-management/)
- [Authorisation models](https://connectbyjbrh.com/docs/technology/authorization-models/)

## What this page is based on

- Connect architecture source pack — docs-source/sources/GENERAL.md §2, §3 and §10, isolation, scoped tables and security
- Connect capability registry (docs-source/facts.py) — rls_isolation, google_sign_in, password_sign_in, session_replacement
- `backend/app/workspace_kernel.py`, `main.py`, `webapp/src/services/tenant-adapt.js`
