Trust at Arteros

We hold your OAuth tokens.
Here's what we do with them.

Arteros is the runtime that AI agents use to act on your customer systems — HubSpot, Gmail, Notion, Stripe, AWS, and so on. We hold the OAuth tokens that let them. We take that responsibility seriously, and we'd rather tell you what we do and don't do than ask you to trust a logo wall.

This page is the current honest state of our security posture. It includes what we haven't built yet and what's on the roadmap. We update it when something ships, not when something is decided.

Last updated: 2026-05-27 · security@arteros.ai
Philosophy

How we think about it

Three principles drive everything below.

Defence in depth.

No single layer can be the only thing standing between your data and an attacker. Auth, tenant isolation, encryption, and observability all backstop each other.

Honest gaps.

A trust page that claims everything is solved is selling you fiction. The gaps section is real and the items there are tracked publicly.

Composio-class blast radius.

When a runtime that holds many customers' OAuth tokens is compromised, the blast radius is everyone's upstream systems. We design assuming a sophisticated attacker eventually probes us, and we treat public incidents in our space — like Composio's November 2025 breach — as information about our own threat model.

01

Tenant isolation

Arteros is multi-tenant. Every record in our database belongs to exactly one organization, and every read or write of that data passes through a per-tenant data accessor that hard-binds the tenant ID at the SQL WHERE clause.

Schema. Every tenant-scoped table has a non-nullable organization_id column with cascade-on-delete and an index. Caches use a composite unique index on (organization_id, cache_key) so two tenants can compute the same cache key without ever colliding in storage.
Application layer. Production code reaches data through an OrgScoped wrapper. The wrapper is constructed with an org ID at request time and inserts that ID into every query. Pinned by an automated regression test that walks the repo and fails CI if any production file imports a tenant-scoped schema table and queries it directly.
Plan execution. Plan submissions are authenticated and bound to the submitting tenant before any step dispatches. Forged tenant identifiers and cross-tenant references reject at the submission boundary.
Coming next
Postgres row-level security policies on every tenant-scoped table. Today's protection is app-layer; RLS adds a second backstop at the database itself.
02

Credential storage

When you connect HubSpot, Gmail, or any upstream, the OAuth access and refresh tokens are encrypted with AES-256-GCM before they hit the database. The encryption key never appears in any log, response, or error message.

At-rest. Tokens are encrypted column-side. The encrypted blobs are per-connection and per-tenant.
In-flight. TLS 1.3 between you, our gateway, and every upstream API. We do not retain decrypted tokens in memory beyond the request that needs them.
In logs. Our structured logger has a redaction layer covering *.token, *.accessToken, *.refreshToken, *.password, *.apiKey and their variants, recursively to depth 3. A regression test asserts that no token-shaped string ever escapes the redaction layer.
Honest gap
Today the master encryption key is a single value held in our deployment environment, the same value for all tenants. That is a Composio-class single point of failure: anyone who compromises our deployment environment can decrypt every customer's tokens. We are migrating to per-tenant data encryption keys derived from a KMS / HSM-backed master that never materialises in application environment variables. Tracked publicly in our backlog; required before any enterprise contract.
03

Auth and access control

Customer sign-in. Email + password with email verification, sessions in Postgres, via Better Auth. No magic-link auth. We don't ship magicLink, emailOTP, or any passwordless plugin — magic-link auth turns your email account into a master key for ours, which was the Composio entry vector.
API access from agents. OIDC access tokens issued by our authorization server, plus a legacy bearer-token path with revocation. Every plan submission verifies tenant identity before dispatch.
Founder accounts. Hardware MFA on every credential-bearing account we use to operate Arteros — Gmail, GitHub, Railway, Cloudflare, Anthropic console, domain registrar, password manager. SMS as a 2FA fallback is removed everywhere.
Internal access. The list of human operators with access to production infrastructure is short, audited, and posted in our security backlog. We do not have a separate "staging" environment that shares production credentials — that's the textbook Composio lateral-movement path, and we closed it by absence.
04

Adapter safety

Every third-party API Arteros talks to has an adapter. Adapters are the most likely place for an injection bug, so we hold them to a specific standard:

No shell, no eval, no template engines, no raw SQL. Adapters are pure HTTP. We removed entire CVE classes (CVE-2024-8864/8865 style) by structural choice. A scan across all adapters confirms zero hits for child_process, eval, new Function, filesystem write operations, or templating libraries.
URL construction. Adapters use new URL() and encodeURIComponent for every interpolated path or query segment. Adapter inputs are validated by Zod schemas with concrete format constraints — bucket names match S3 naming rules, region codes match AWS region format — so attacker-supplied metacharacters can't break out of the intended host or path. SSRF regression tests run every adapter's input validators against a corpus of host- and path-injection payloads.
Adapters are not eval'd. Adapters are part of the Arteros source tree and reviewed in PR. We do not load adapter code from a customer-controlled registry or evaluate JavaScript supplied at runtime.
Honest gap
Some adapter base URLs read connection metadata fields (subdomains, Atlassian cloud IDs, Twilio account SIDs) that we set at OAuth completion. We're adding storage-time format validation for those fields so a malicious operator can't connect their own account with a subdomain that redirects requests to a host they control. Tracked in the backlog.
05

Audit logging and observability

Every credential read, every connection create / revoke / rename, every plan execution is written to an immutable audit_events table with the actor, the target, and the action. Structured logs are JSON, level-controlled, and emitted to Railway's log infrastructure with PII redaction.

Honest gap
Audit events currently live in the same Postgres instance as the application. An attacker who compromises the application could delete their tracks. We are wiring an append-only off-platform sink (separate cloud account, separate provider) so the audit trail survives a platform compromise. Tracked publicly; required for SOC 2.
06

Vulnerability disclosure

We want to hear about it. If you find a security issue in Arteros:

Email: security@arteros.ai (private — replies within 1 business day)

We commit to:

  1. Acknowledging your report within one business day.
  2. Treating reports in good faith — we won't pursue legal action against research conducted in line with this policy.
  3. Coordinated disclosure: we'll work with you on a fix timeline and credit you in the changelog if you'd like to be named.

A formal bug bounty programme is on our roadmap. Until it launches, we will acknowledge significant reports with a public thank-you and (where appropriate) a discretionary reward.

07

The Composio incident — what we did

In November 2025, Composio — a SaaS gateway in our space — disclosed a breach in which an attacker chained a compromised Gmail OAuth account, a magic-link sign-in on a staging environment, lateral movement to production, and access to customer OAuth tokens. The public post-mortem includes 24 attacker IP addresses and root-cause notes that map cleanly onto categories every runtime in this space should review.

What we did within 72 hours:

  1. Reviewed every category against our own architecture. Where Composio's exact mechanism didn't apply to us (we have no API keys, no separate staging environment), we wrote that down and accepted the framing. Where it did apply (encryption key custody, founder MFA, adapter injection), we treated it as immediate work.
  2. Shipped a critical fix. The S3 bucket and region fields in our AWS adapter were unconstrained strings interpolated into the URL host — exactly the URL-injection / SSRF shape that the Composio CVE-2024-8864/65 advisories warned about. We added format validation across 43 input fields and shipped 299 regression tests in packages/services/src/aws/ssrf.test.ts.
  3. Hardened operator accounts. Hardware MFA + magic-link disable across every credential-bearing account.
  4. Documented honestly. Every gap surfaced by the review is on this page as an "Honest gap" with what we're doing about it.
  5. IOC sweep. Cross-checking our edge logs against the published attacker IP list. Results will be reflected here.

We will keep updating this page as we ship.

Questions, concerns, or you spotted something we got wrong?

We answer security mail within one business day.