← Argus · Methodology · Pricing
Security
This page describes how the product actually works, not how we would like it to sound. It includes what we have not done — see the last section.
Tenant isolation
Isolation is enforced in the database, not by application code remembering to add a filter. Every tenant-owned table carries an org id and runs Postgres row-level security keyed on a per-transaction setting. Because the underlying lookup returns null when that setting is absent, a query issued outside a tenant scope matches zero rows — isolation is the default state, not something a query has to opt into. The application connects as a non-owner role that cannot bypass those policies, and the audit log is append-only at the table-privilege level (insert and select granted; update and delete revoked).
Identity and access
Human identity — passwords, social sign-in, MFA, enterprise SSO (SAML and OIDC), invitations, verified domains, JIT provisioning — is handled by Clerk. We do not store or process passwords. Roles (owner / admin / member) are held in our own database and enforced server-side on every mutation, so authorisation does not depend on a client-side claim. Deprovisioning a user in your identity provider removes their access here.
Machine access uses first-party API keys, scoped to a subset of read and write permissions and revocable at any time. Keys are shown once at creation and stored only as a SHA-256 hash with a short display prefix — we cannot recover a lost key, only replace it. Every key embeds its organisation, so the hash lookup itself runs inside that tenant’s isolation scope.
Secrets and signing
Alert webhooks are signed so you can verify a delivery came from us. The per-rule signing secret is derived from a master key and a non-secret per-rule value — it is never stored, which means a database disclosure does not reveal it. Cryptographic operations use the platform’s vetted primitives; no key, token or signing secret is ever written to a log or returned by an API.
Outbound requests
You supply the URL your alerts are delivered to, which makes that a request we make on your behalf. Targets must be HTTPS, and we resolve the hostname immediately before each delivery and refuse private, loopback, link-local and cloud-metadata addresses — a check at the moment of use, because a hostname that resolves publicly today can resolve privately tomorrow. Redirects are never followed, since a redirect would sidestep that check. Resolution failure blocks the delivery rather than allowing it.
Your data
Your assets, dependency graph, risk treatments and private events are yours. The shared global intelligence feed is read-only and identical for every customer; your own data sharpens your register and no one else’s. Synthetic demonstration data is labeled as such wherever it appears and is never presented as real intelligence. Every change to assets, dependencies, treatments, keys, alert rules and membership is recorded in an append-only activity log you can read in Settings.
Sub-processors
| Provider | Role | Data |
|---|---|---|
| Vercel | Application hosting and edge delivery | Request metadata, application logs |
| Neon | Managed Postgres database | All customer-entered data (assets, register, treatments, audit log) |
| Clerk | Identity and authentication | Account identity: name, email, authentication factors |
| Resend | Transactional email for alert delivery | Recipient address and alert contents — only when email alerts are enabled |
Application hardening
- All database access is parameterized through a query builder — no SQL is constructed from input.
- Ingested events and assets are validated against a closed vocabulary before storage; unknown values are rejected with a named error rather than coerced.
- Per-IP and per-credential rate limiting on the API, applied before authentication so it also caps credential guessing.
- Security headers including HSTS, a strict frame policy, and a nonce-based Content Security Policy.
- A small, pinned, lockfiled dependency set — audited in CI on every change — rather than a large transitive tree.
What we have not done yet
Volunteered, because you would find these anyway and we would rather you heard them from us:
- No third-party penetration test yet. Planned before the first enterprise contract.
- No SOC 2 report. We are a small team and have not begun an audit; we will say so plainly rather than imply otherwise.
- Content Security Policy is in report-only mode in production while we validate it against live sign-in flows. It reports violations but does not yet block them.
- No SCIM for automated user provisioning — SSO and JIT provisioning work today; SCIM is later.
- Outbound egress filtering is application-level. A brief window exists between our DNS check and the request itself; fully closing it requires network-level policy, which is on the infrastructure roadmap.
Reporting a vulnerability
Email bhyde@engsecsolutions.com. We will acknowledge receipt, keep you informed, and will not pursue legal action against good-faith research that respects customer data and avoids service degradation.