Security
Secure by default
Your internal tools hold the keys to everything, and that is where Avo runs. We treat the security and integrity of that data as first-class work, not an afterthought. Here is how we think about it on both sides: the framework that runs inside your app, and AvoHQ.io where you manage your account.
Avo, the framework
The gem that runs inside your Rails app. Security here is about keeping your data in your hands and making sure access is gated correctly.
- Your data never leaves your app
- Avo runs inside your own Rails application, against your own database. The records you manage stay in your infrastructure, under your controls. No customer data is ever shipped to us. We collect only anonymous telemetry and usage stats about how Avo itself is used so we can improve it, never the contents of your database.
- Safe by default authorization
- The Authorization add-on, included in every bundle, runs through Pundit policies you already trust. With explicit authorization on, anything you have not deliberately allowed is denied, so a policy you forgot to write locks a record down instead of leaving it open. You whitelist what each role can do rather than trying to blacklist everything you missed.
- Integrity down to the field
- Authorization reaches every nook and cranny: resources, actions, associations, file fields, search, reorder, and preview each get their own check. The same rules gate the sidebar, the buttons, and the records, so what a user can see and change stays consistent everywhere.
- One authorization layer, every surface
- The CRUD UI, the AI chat, the MCP server, the API, and the CLI all go through the same policies. Scope the records a role can load and the attributes it can see, and that holds whether a person clicks through the admin or an agent queries it. There is no surface that reaches your data around the policy.
- A hidden field is hidden everywhere
- A policy can name the fields a role may reach, as an allowlist, a denylist, or both. A withheld field is not rendered on any view, is not in the permitted params, is not in API responses, and is not returned or written by the AI chat or over MCP. Denied means invisible and unsettable, from one list.
- Every request acts as a named person
- The AI chat acts as the person chatting, an MCP connection as the admin who approved it, and an API token as the user who created it. That identity is set by your app, never passed by the model or the client, and every call runs through that person's policies. Over MCP the admin is looked up again on each call, so a change to their role takes effect on the next one. A record outside their reach comes back as not found, the same as one that does not exist.
- Connections you approve, narrow, and revoke
- An admin approves each MCP client on a consent screen served by your own app. Read is preselected, writing and running actions are not, and access can be narrowed per resource. A connection can be changed or revoked later, and that binds its next call. Over MCP the consent is the confirmation: a client granted write or actions uses them without asking again. API tokens can be limited per resource to read, or read and write. MCP sign-in is OAuth with PKCE, access tokens last one hour, and tokens, authorization codes, and API secrets are stored only as SHA-256 digests.
- Changes through the chat wait for a person
- Updates, deletes, action runs, and CSV imports asked for in the AI chat arrive as a card and apply only when a person confirms. The model can propose a write, never perform one, and permissions are checked again at the moment of confirming. Creating a single record applies straight away. Each change keeps a before and after copy of the row, so it can be undone from the chat.
- Audit logging
- Know who did what. Audit logging, an Enterprise feature, records the actions taken in your admin against the person who took them, and names the way in when it was the AI chat, an MCP connection, or an API token. Changes to your data are traceable and you have an accountability trail when something looks off.
- Built and reviewed by people
- We use LLMs to move faster, and every release is designed, reviewed, and owned by the core team. Access control is the code you cannot afford to get subtly wrong, so it lives in the foundation, engineered and hardened across many real apps. Your agents write the policy rules on top; they never have to write the enforcement.
- No black box, no lock-in
- Avo is conventional Rails. When you hit the edge of what is provided you drop down to plain Ruby instead of trusting a vendor's closed implementation. You can read, audit, and extend exactly what runs in your app.
- Battle-tested across many teams
- Avo runs in the admins of a large number of teams, exercised well past any single app's happy path. That breadth means edge cases and security issues surface and get caught faster than they would in a one-off build only your team ever runs.
- Bugs are fixed once, for everyone
- When a security issue is found, it is our code in our domain. We fix it once and ship the fix to every app, instead of each app carrying its own version of the same bug.
Security advisories
Every vulnerability we fix in Avo is published as a GitHub Security Advisory, with the versions that carry the fix. Here is the full list, newest first. To pick up a fix, run bundle update avo.
- Authorization gaps in update, association listings, summary charts and has_one routes
- High · published 28 October 2026 · fixed in 4.3.8 and 3.33.3 · GHSA-5qcq-2vq9-62hj
- Missing authorization on the association show endpoint exposed related records
- Medium · published 22 October 2026 · fixed in 4.3.4 and 3.33.2 · GHSA-x65r-p6hf-94hv
- A request parameter could change the process-wide locale setting
- High · published 22 October 2026 · fixed in 4.3.1 and 3.33.1 · GHSA-h7x6-9mqf-vgmx
- The Media Library exposed every Active Storage blob to any signed-in Avo user
- High · published 13 August 2026 · fixed in 4.1.7 and 3.32.4 · GHSA-cff8-4h3c-9r4q
- Active Storage attachments could be deleted across tenants
- High · published 10 August 2026 · fixed in 4.1.5 and 3.32.2 · GHSA-49qj-7hqj-6whp
- Missing authorization on the association attach endpoint
- Critical · published 17 June 2026 · fixed in 4.0.0.beta.51 and 3.22.1 · GHSA-8fq9-273g-6mrg, CVE-2026-55518
- The direct upload endpoint skipped the field-level upload policy
- Medium · published 2 June 2026 · fixed in 4.0.0.beta.41 and 3.32.0 · GHSA-pqpw-cvm4-8mv9, CVE-2026-53769
- Action classes could be run across resources
- High · published 20 April 2026 · fixed in 3.32.0 · GHSA-qc5p-3mg5-9fh8, CVE-2026-42205
- Cross-site scripting through the return_to parameter
- Medium · published 17 March 2026 · fixed in 3.30.3 · GHSA-762r-27w2-q22j, CVE-2026-33209
- Stored cross-site scripting in the key_value field
- High · published 16 January 2024 · fixed in 3.3.0 and 2.47 · GHSA-ghjv-mh6x-7q6h, CVE-2024-22191
- Cross-site scripting in action messages
- Medium · published 16 January 2024 · fixed in 3.0.0 · GHSA-g8vp-2v5p-9qfh, CVE-2024-22411
- Stored cross-site scripting in HTML content fields
- High · published 5 June 2023 · fixed in 2.33.3 · GHSA-5cr9-5jx3-2g39, CVE-2023-34103
- Unsafe reflection that could cause a partial denial of service
- High · published 5 June 2023 · fixed in 2.33.3 · GHSA-86h2-2g4g-29qx, CVE-2023-34102
AvoHQ.io
Our hosted site, where you buy and manage licenses and your account. Security here is about handling the little we hold on you with care.
- We collect as little as we can
- Your AvoHQ.io account holds what we need to run your license and billing: your account details, the licenses you own, and your usage of the site. We do not need or want a copy of the data inside your own Avo app.
- Payments handled by Stripe
- Checkout and subscriptions run through Stripe. Card details go straight to Stripe and are never stored on our servers, so the most sensitive part of billing sits with a dedicated, PCI-compliant provider.
- Encrypted in transit
- Every connection to AvoHQ.io is served over HTTPS, so traffic between you and the site is encrypted end to end.
- Scoped access to your account
- Account membership and roles decide who on your team can see licenses, manage billing, and invite others. Access to your account data is gated the same way we expect you to gate your own.
- Report something
- Found a vulnerability in Avo? Report it privately on GitHub, or email us for anything else. We reply to every report within two business days. We would rather hear about it from you than read about it later.