# Security

How to report a vulnerability in BasaltDB, and a short summary of what it protects against.

## Report a vulnerability

Do not open a public issue or pull request for a security problem. Report it privately through GitHub:

1. Open the [private vulnerability report form](https://github.com/BasaltDBHq/BasaltDB/security/advisories/new) for the BasaltDB repository. This is GitHub private vulnerability reporting. Only the maintainers can see what you send.
2. Say what is affected (the engine, the guard, the CLI, a portal page) and the commit or version.
3. Add steps or a proof of concept, and what an attacker gains.

Never put a real credential or someone else's data in a report. Use a throwaway database.

The full policy is in [SECURITY.md](https://github.com/BasaltDBHq/BasaltDB/blob/master/SECURITY.md) in the engine repository. It lists what is in scope and what to expect. The maintainers are a small team. They aim to acknowledge a report within 5 business days and give a first assessment within 14 days. These are targets, not guarantees.

## What BasaltDB protects against

The engine is the first filter and your database is the boundary. The guard is the `basalt_meta` schema inside your Postgres, with roles and triggers. It protects against an agent that makes a mistake, or is talked into one.

- **The agent holds no database password.** The engine holds a scoped credential for that agent and runs as its own OS user.
- **The agent's role cannot change tables.** It has table grants only. It cannot drop, alter or create anything, and the guard refuses more than 50 rows in one action.
- **Every write carries a reason.** Postgres refuses a write without one, even over a direct connection with the agent's credential. Old and new rows are saved in the same transaction. If the guard cannot record a write, the write fails.
- **An agent cannot approve its own change or undo.** An approval needs your passkey. Postgres checks the signature, so whatever carries it cannot forge one.
- **Old values are kept for 30 days.** An undo restores them, and leaves alone any row changed since.

## What it does not protect against

- An agent with your admin credential, your own credential or `sudo` on the engine's machine.
- A change that is valid, small and wrong. It is recorded and can be undone.
- Data an agent already read and passed on, for example through prompt injection.
- Actions outside the database, such as an email sent or a payment made on bad data.

See [What BasaltDB won't catch](/limits/) for each one and what helps, and [Architecture](/concepts/architecture/) for how the pieces fit.

## Next

- [License](/license/)
