v0.4.0Iris v0.4 — LLM-as-Judge + citation verify + OTel + 9 MCP tools

Security

Last updated: April 23, 2026

Iris stores a lot of signal about your agents — inputs, outputs, tool calls, eval results. This page explains the concrete controls in place, the threat model we design against, and how to verify each claim for yourself.

Data location

Self-hosted (OSS): every trace, span, eval result, and audit entry is written to a SQLite database on your machine (default: ~/.iris/iris.db). No data ever leaves your environment. Iris does not phone home. There is no telemetry.

Cloud tier (v0.4+): data is stored in a per-tenant logical partition in our managed backend, which runs on hardened US-region infrastructure. Encryption at rest (AES-256) + encryption in transit (TLS 1.3) are table stakes. Cross-tenant isolation is enforced at four independent layers — see the architecture guide for the technical detail.

Tenant isolation

Every row in every data table carries a tenant_id column. Reads, writes, updates, and deletes require a tenant context parameter — there is no “get all traces” query path in the codebase. The four-layer defense:

  1. Type system. TenantId is a branded TypeScript type. Forgetting to pass tenant context is a compile error.
  2. Runtime guard. Every storage method calls assertTenant() which throws if the tenant is missing — even if the type checker was bypassed.
  3. SQL scope. Every SQL statement carries an explicit WHERE tenant_id = ? clause.
  4. Composite indexes. Every hot-path index leads with tenant_id so cross-tenant scans are physically impossible in the planner’s fast path.

In Cloud mode the tenant ID is resolved server-side from your auth token’s claims — never from a client-supplied query parameter or header. Regression coverage lives in tests/unit/storage/sqlite-adapter.test.ts (cross-tenant isolation) and migration-tenant.test.ts (upgrade path).

Supply-chain transparency

Every Iris release produces artifacts you can independently verify:

  • npm provenance. Every published tarball carries a GitHub-signed attestation linking it to the source commit and workflow run. Verify with npm audit signatures.
  • SPDX SBOMs. A Software Bill of Materials ships with every release, covering direct and transitive dependencies for both the npm package and the Docker image. Attached to the GitHub release page as iris-npm-sbom.spdx.json and iris-docker-sbom.spdx.json.
  • Cosign signatures. Docker images are signed with Sigstore cosign using GitHub OIDC (no long-lived signing key). Verify with:
    cosign verify ghcr.io/iris-eval/mcp-server:vX.Y.Z \
      --certificate-identity-regexp='https://github.com/iris-eval/mcp-server' \
      --certificate-oidc-issuer='https://token.actions.githubusercontent.com'
  • SLSA build provenance. Both artifacts carry GitHub-signed attest-build-provenance attestations. Inspect with gh attestation verify.

Runtime defenses

  • Helmet headers on the dashboard API (HSTS, X-Frame-Options, X-Content-Type-Options, strict CSP).
  • Bearer-token auth on HTTP mode with crypto.timingSafeEqual-based comparison to block timing side-channels.
  • Rate limiting: 20 req/min on MCP endpoints, 100 req/min on dashboard APIs, standard RateLimit headers.
  • Zod input validation on every MCP tool and REST endpoint. Invalid requests fail fast with structured errors.
  • ReDoS protection: custom regex rules are validated with safe-regex2 and length-capped at 1,000 characters before compilation.
  • Request size limit (1 MB default) to prevent memory-exhaustion attacks.

Threat model

We maintain an internal STRIDE threat model covering ingestion, storage, dashboard API, auth, file I/O, and multi-tenant boundaries. The summary:

  • In scope: data confidentiality, tenant isolation, supply chain integrity, DoS resistance on the API surface, audit log tamper detection, prompt-injection-aware eval rules.
  • Out of scope: physical access to the host machine (self-hosted), insider threats at the hosting provider, compromise of your LLM provider’s infrastructure, social engineering of your developers.

The full threat model is a private document reviewed and updated quarterly. We share redacted excerpts with enterprise customers under NDA on request.

Reporting a vulnerability

If you believe you’ve found a security issue, please email security@iris-eval.com. Please do not open a public GitHub issue for security matters.

We commit to:

  • Acknowledge your report within 2 business days.
  • Provide a preliminary assessment (confirmed / not a vulnerability / need more info) within 7 days.
  • Coordinate a disclosure timeline with you — we ask for 90 days by default, negotiable for high-severity or widely-exploited issues.
  • Credit you in the release notes and the SECURITY.md hall-of-thanks unless you prefer to remain anonymous.

Compliance roadmap

Iris is pre-SOC-2 today. For enterprise buyers asking about compliance posture:

  • Today: security-by-design architecture, signed releases, SBOMs, internal STRIDE threat model.
  • Cloud GA (v0.5): formal SOC 2 Type I readiness, independent penetration test, incident response playbook.
  • Enterprise tier: single-tenant isolation option, custom data-residency, BAA/DPA support, SOC 2 Type II within 18 months of Cloud GA.

Related reading