Security & Trust Centre

How Triazz keeps itself in bounds

Everything below describes the product as it works today, with its limits stated. Self-hosted, auditable, and built so that no single component has to be trusted blindly.

Self-hostedTamper-evident logAES-256-GCM at restShadow Mode by default

Firewall & redaction

An always-on firewall scans text before it is stored or reaches a model. It removes secrets such as tokens, keys and credentials, drops health information, and replaces what it caught with a labelled marker so you can see what was removed. It runs whichever model provider handles the job.

Limit: it is a pattern scanner, not a compliance certification, and it can miss a secret in a format it does not know.

Tamper-evident audit log

Every action the bot takes is written to a SHA-256 hash-chained activity log: each entry commits to the one before it, so editing or inserting a row breaks the chain from that point on. With a master key configured (the normal case), each entry also carries a keyed MAC, so someone who can write to the database but does not hold the key cannot edit an entry and recompute the hashes after it without being caught.

A hash chain alone cannot catch someone quietly deleting the newest entries. Hourly signed anchors close that gap: the latest chain hash is signed and written to an append-only file you can verify, and optionally sent to an external log collector you run. The log records metadata only and is kept for the life of the bot; the separate record of tool calls is kept for 90 days, and message text is erased after 90 days by default.

Limit: it is tamper-evident, not immutable. Someone who holds the whole data folder and the key could re-key it, and the anchors only protect fully if they are sent to a collector outside the server.

Credential storage

Connection credentials (Outlook, Gmail, Slack, Jira, model API keys and the rest) and saved logins are stored encrypted at rest (AES-256-GCM in the encrypted secrets file, or the macOS Keychain on a single-person Mac), never in plain text. No AI, report or log ever holds the value of a saved login. The master key can be rotated with one command, which proves the old key against everything first and restores everything if anything fails.

Bot isolation

Each person's bot is an independent silo with its own database. One colleague's bot can ask yours a question only if you turned sharing on and named them, only a text answer ever leaves, and your yes is the default. Access is re-checked on every request, so taking someone off your list or off the server stops them at once. An administrator cannot read a private bot through the product: a token made for someone cannot reach their private bot until they claim it.

Mail, chats, web pages and files are treated as data. They cannot start a task or change a setting.

Human approval, by default

Every bot starts in Shadow Mode, which reads and drafts only, so nothing is sent until you choose otherwise. Risky abilities (sending email, sending chat messages, hosted models, task commands, task file writes, reading code, meetings) are off by default. Per action you choose Do, Ask or Never, and a kill switch stops everything outward. Going Live is your own confirmed choice; the learning scorecard gives you evidence for it.

A task works on its own branch of a repository, with your own files and branch untouched, and any command it wants to run, including the tests, waits for you to approve that exact command. There is deliberately no tool that approves a command on its own. Known deploy, database-migration and git push commands are refused, and every other command waits for your approval.

On a shared server an administrator can set baseline rules and ceilings that people cannot loosen, and a second factor can protect sensitive changes.

Deployment model

Run it as a packaged container behind your own Docker Compose stack (or, set up with us, as a single Node.js app), fully inside your own infrastructure. You choose the model per job (free local Ollama, the Anthropic API, the OpenAI API, or Claude Code on the same computer) and nothing requires the application itself to contact our servers. Cloud models stay blocked until Hosted Models is switched on (on a shared server, an administrator unlocks it first). Where an organisation uses licence checks, the licence key is supplied at runtime through your own environment configuration and is never baked into the container image.

What leaves your network

There is no telemetry, no usage reporting, and no address of ours built into the code. Triazz connects outside your server only for:

  • The services you connect: Microsoft, Google, Slack, Jira and your git host, as any client of theirs would.
  • A cloud AI model, only after Hosted Models is switched on. It receives the text for one job, after the firewall has removed secrets. Messages with health information never reach any model.
  • A daily licence check, where your organisation uses one. It downloads the list of active licences and sends nothing. If a key is limited to a number of servers, a daily check-in sends the licence key and a random install id, and nothing about your people or data.
  • A one-time download of the public playbook library from GitHub on first start, which can be switched off.
  • Only if you set them up: model tracing (Langfuse: prompts and answers after the firewall, or timings only if you choose), audit anchors (a signed hash, no content) and notification email.

You can confirm all of this from your own egress logs or firewall.

Governed MCP access

Almost everything in the dashboard is also reachable as an MCP server from Claude Code, Claude Desktop and other MCP apps: 183 tools in total, 133 on by default and 50 that change things opt-in, over stdio or HTTP. An AI app gets the same memory, repositories, tasks and skills the dashboard has; it cannot send or approve directly (if you allow it, it can switch auto-reply on for a limited time).

Monitoring

Every model call is counted: counts, failures by cause, p95 and average latency, cache hits and fallback events. You can see this on the dashboard's Models screen, over MCP, and as a standard Prometheus /metrics endpoint for your own monitoring. Counts and timings only, never call content.

What we don't claim

Task isolation is opt-in and is not a hardened boundary. Running task commands inside a container is optional; the default mode runs them on the host, and the official Docker image cannot run task commands safely without a separate runner. Even in a container, do not rely on it as the only thing between an executed task and the host.

Start small. We recommend starting with one pilot user and widening from there.

Scale and availability. A shared server is one process by default on SQLite files, designed for roughly 50 to 100 people (larger organisations run one server per team), with no managed high availability. Sign-in is through your Microsoft or Google account; there is no other SSO, and backups are a command (triazz db backup) plus a restore script, not a scheduled or managed service.

We would rather say this plainly than overclaim.

Report a vulnerability

Email contact@triazz.com with “Security” in the subject: what you found, how to reproduce it, and the version or image digest you tested. We reply within 3 working days and keep you updated until it is fixed. Please give us a reasonable time to release a fix (we aim for 90 days at most) before publishing anything.

We will not take legal action against research done in good faith that respects people’s privacy, does not degrade service for others, and stops at proving the issue. Please don’t test against systems you don’t own or against a customer’s installation. We’re glad to credit you when the fix ships.

Machine-readable contact details: security.txt.

Questions, a security review or a pilot?

Tell us what you need to check and we will answer directly. Security teams evaluating Triazz for their company can also review the source code under NDA.

contact@triazz.com