> For the complete documentation index, see [llms.txt](https://docs.observal.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.observal.io/security/assurance-case.md).

# Security assurance case

## Claim

Observal protects registry control, authentication credentials, agent configuration, and telemetry against unauthorized disclosure or modification when operators follow the documented deployment requirements. This case records the threats, boundaries, controls, evidence, and residual risks supporting that claim.

## Assets

The primary assets are:

* User passwords, access tokens, refresh tokens, OAuth secrets, Git tokens, and signing keys
* Registry agents and their MCP, skill, hook, prompt, and sandbox configurations
* Session transcripts, traces, insights, audit events, and user identity data
* Release artifacts, release tags, and the software supply chain
* Administrative control over users, teams, policy, retention, and SSO

## Threat actors and assumptions

Relevant actors include unauthenticated internet clients, malicious authenticated users, compromised user tokens, hostile registry submissions, compromised dependencies, and network attackers between clients and a remote deployment. Administrators and host operators are trusted to protect the host, secret files, backups, and TLS termination. PostgreSQL, ClickHouse, Redis, the API, and workers are trusted only inside the deployment network.

A host-level compromise, malicious administrator, compromised identity provider, or compromised GitHub release workflow is outside the controls of the application alone. Recovery procedures and external infrastructure controls must address those events.

## Trust boundaries

1. **Client to frontend:** Untrusted browsers, CLIs, harness hooks, and integrations cross the HTTPS boundary into nginx and the API. Packaged HTTP listeners bind to loopback by default. Remote access requires an operator-selected TLS proxy or an explicit non-loopback bind.
2. **API authentication and authorization:** Requests cross from unauthenticated parsing into JWT, password, SSO, role, team, and ownership checks.
3. **Registry execution inputs:** URLs, archives, MCP metadata, prompts, and harness configuration cross from users or external repositories into scanners and config generation.
4. **Application to data services:** The API and workers cross the container network into PostgreSQL, ClickHouse, and Redis. Database ports bind to loopback in the server package by default.
5. **Secret storage:** Operator-controlled secret files and JWT or SAML key files cross into application memory. File-backed dynamic secrets are not copied into PostgreSQL or Redis.
6. **External services:** OAuth providers, source repositories, webhooks, and model providers cross outbound HTTPS and SSRF policy boundaries.
7. **Release supply chain:** Source and GitHub Actions identities cross into signed tags, built artifacts, provenance attestations, and public downloads.

## Security requirements and arguments

### Identity and least privilege

Passwords use scrypt with a per-user salt. Tokens use configurable ES256 or RS256 asymmetric signing, short-lived access tokens, refresh-token revocation, and published JWKS. Role, team, visibility, ownership, and admin dependencies enforce authorization at API boundaries. Redis-backed revocation fails closed.

Evidence: [`models/user.py`](https://github.com/BlazeUp-AI/Observal/tree/main/observal-server/models/user.py), [`services/crypto.py`](https://github.com/BlazeUp-AI/Observal/tree/main/observal-server/services/crypto.py), and [Authentication and SSO](/self-hosting/authentication.md).

### Credential and key protection

Operator credentials support bounded `NAME_FILE` inputs, direct and file values cannot be configured together, and server-package secrets are operator-owned and readable only by the configured container service group. JWT keys are persisted separately with owner-only permissions. SAML SP keys and certificates can be mounted as dedicated files. File-backed admin values are reported as externally managed and cannot be overwritten or revoked through the admin API.

End-user password hashes and issued-token metadata remain in their purpose-built database records. They are not deployer secrets and do not belong in shared host secret files.

Evidence: [`observal_shared/secrets.py`](https://github.com/BlazeUp-AI/Observal/tree/main/packages/observal-shared/observal_shared/secrets.py), [Configuration](/self-hosting/configuration.md), and [Environment variables](/reference/environment-variables.md).

### Network confidentiality

Remote deployments are expected to terminate TLS 1.2 or TLS 1.3 using Caddy, nginx, an enterprise load balancer, or a cloud ingress. Standard HTTPS clients retain certificate and hostname verification. The server package exposes HTTP and data-service ports only on loopback by default. A non-loopback plaintext listener requires an explicit bind setting.

Evidence: [Single-node deployment](/self-hosting/single-node-deploy.md), [`docker/nginx.production.conf`](https://github.com/BlazeUp-AI/Observal/tree/main/docker/nginx.production.conf), and [Requirements](/self-hosting/requirements.md).

### Untrusted input containment

Pydantic schemas, enums, length bounds, allowlists, namespace validation, and database constraints reject malformed input. Outbound URL paths use SSRF guards. Redirects, archive paths, XML, SVG, host headers, proxy headers, and request sizes receive dedicated validation. Containers add non-root execution, read-only filesystems, temporary filesystems, and `no-new-privileges` where supported.

Evidence: [Trusted proxies and network security](https://github.com/BlazeUp-AI/Observal/tree/main/docs/self-hosting/trusted-proxies.md), [`services/ssrf_guard.py`](https://github.com/BlazeUp-AI/Observal/tree/main/observal-server/services/ssrf_guard.py), and [`docker/docker-compose.yml`](https://github.com/BlazeUp-AI/Observal/tree/main/docker/docker-compose.yml).

### Cryptographic and supply-chain integrity

JWT signing can switch between ES256 and RS256 without recompilation. Algorithm changes retain old public verification keys for the token transition window and reject header or key-type confusion. Release artifacts carry GitHub keyless Sigstore provenance, and release tags are signed and verified with the release workflow's OIDC identity before publication.

Evidence: [`services/crypto.py`](https://github.com/BlazeUp-AI/Observal/tree/main/observal-server/services/crypto.py), [Release verification](/security/release-verification.md), and [the release workflow](https://github.com/BlazeUp-AI/Observal/tree/main/.github/workflows/release.yml).

### Detection and recovery

Security-sensitive administration emits audit and security events. Health checks, diagnostics, backup guidance, key backup guidance, retention controls, and vulnerability reporting support detection and recovery. Private vulnerability reports have documented acknowledgement and remediation targets.

Evidence: [Security policy](https://github.com/BlazeUp-AI/Observal/tree/main/SECURITY.md), [Backup and restore](/self-hosting/backup-and-restore.md), and [Authentication and SSO](/self-hosting/authentication.md).

## Common implementation weakness mitigations

| Weakness                             | Mitigation                                                                                            |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| Injection and malformed data         | Typed schemas, allowlists, parameterized SQLAlchemy queries, and output encoding                      |
| Broken access control                | Central role dependencies plus ownership, team, and visibility checks                                 |
| SSRF                                 | Scheme and address validation before outbound requests                                                |
| Path traversal and unsafe archives   | Resolved-path containment, archive member limits, and type checks                                     |
| Credential disclosure                | Secret redaction, encrypted sensitive settings, restricted secret files, and support-bundle filtering |
| Token forgery or algorithm confusion | Asymmetric signatures, key-derived allowlists, required key IDs, expiry, and revocation               |
| XML and browser attacks              | SAML validation, XML protections, SVG sanitization, CSP, frame denial, and content-type controls      |
| Resource exhaustion                  | Request, line, archive, query, timeout, connection-pool, and rate limits                              |
| Supply-chain substitution            | Locked dependencies, dependency scanning, signed release tags, checksums, and artifact provenance     |

## Residual risks

* Explicit non-loopback plaintext mode exposes credentials and telemetry to network interception. It is intended only for trusted private networks or an upstream TLS terminator.
* Loopback HTTP relies on the host boundary. Other privileged processes on a compromised host can observe local traffic and files.
* File-backed secrets are only as secure as host permissions, mounts, backups, and the operator's rotation process.
* A compromised administrator, host, identity provider, or canonical GitHub Actions workflow can exercise its trusted authority.
* Third-party MCP servers, hooks, skills, models, and harnesses may process data outside Observal's boundary. Operators must review and isolate them appropriately.
* Historical releases and tags created before signed-tag enforcement may not have equivalent evidence.

## Maintenance

Review this assurance case when authentication, authorization, cryptography, deployment exposure, secret storage, release signing, or a trust boundary changes. Security reports may invalidate an argument and must be reflected here after remediation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.observal.io/security/assurance-case.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
