Security overview
Who this is for: security reviewers, IT managers and procurement teams who assess Liitora.
Before you start: nothing. For more depth, read How Liitora keeps you safe.
This page summarises the security of Liitora in one place. It describes what the product does today. Liitora doesn’t hold security certifications yet.
Hosting
Section titled “Hosting”- Liitora runs at UpCloud in Finland. Our infrastructure code only accepts Finnish zones (Helsinki), so data stays in Finland.
- The planned production setup keeps the database on a private network, never on a public address, and encrypts Kubernetes storage at rest.
- In that setup, data is encrypted on every network hop. HTTPS ends inside our own cluster, not at the load balancer, and only TLS 1.3 or TLS 1.2 with modern ciphers is accepted. Traffic between servers in the cluster is encrypted too, and connections to the database and the secret store check the server’s certificate.
- Each part may only connect to the few services it needs, and everything else is blocked by default. Workflows run on separate servers from the rest of Liitora.
- Each part of Liitora runs as a separate process with its own role (API, MCP server, webhook receiver, scheduler, worker). The containers run as a non-root user with a read-only file system and no extra privileges.
- Each part also has its own database login and its own secret store identity, with only the rights it needs. The worker, which runs your workflows, can’t read API tokens, people or members, and can’t delete or list secrets. No part holds an administrator token for the secret store.
Company isolation
Section titled “Company isolation”- Every request acts for exactly one company, decided by Liitora’s own records.
- The database enforces isolation a second time with row-level security on every company table. The application’s database logins can’t bypass it and own no tables.
- Another company’s object always answers “not found”, so its existence never leaks.
Sign-in and access
Section titled “Sign-in and access”- People sign in through our OpenID Connect sign-in service with the authorization code flow and PKCE. The app keeps tokens in the browser tab’s session only.
- Tokens are checked strictly (signature, issuer, audience, expiry, allowed algorithms). Roles come from Liitora’s records on every request, never from the token.
- API tokens are stored only as a strong hash (argon2id) and shown once. Each token can do only what it was given (read-only by default), always expires (after 90 days unless you pick a date, at most a year), can be limited to IP addresses, and stops working when the sign-in account of the person who created it is turned off. Tokens start with
liitora_and carry a checksum, so secret scanners can find a leaked one. - AI assistants that connect with your own sign-in get no long-lived offline access: their access ends when your sign-in session does.
- Separation of duties: the author of a workflow version can never approve it, and only people (never AI assistants or API tokens) can approve, handle secret values, or create API tokens.
The web app and its addresses
Section titled “The web app and its addresses”- The app tells your browser to load scripts only from Liitora itself, to never show the app inside another site’s frame, and to send no address details to other sites. Links that carry a one-time token, such as invites and secret links, never leak through the browser.
- Every answer from Liitora is marked so the browser never guesses its type, and answers with your data are never cached.
- Files from your runs, and invoice exports, are always downloaded, never opened as a page. A file that contains HTML can’t run on any Liitora address.
- All Liitora addresses use HTTPS only, and browsers are told to remember that.
- The webhook address your other systems call is on a domain of its own, separate from the app’s, so nothing sent to it can reach your session in the app.
Secrets
Section titled “Secrets”- Secret values are stored in OpenBao, a dedicated secret store, under a path per company. The database holds only names and statuses.
- Values are removed from logs, outputs, errors and stored results, also in encoded forms. Credential headers are masked in HTTP logs.
- Showing a value needs the Reveal secrets permission, is written to the audit log first, and is never cached.
Running your workflows
Section titled “Running your workflows”- Scripts run in a WebAssembly sandbox with a fresh instance per run, no file system, network or environment access, and limits on CPU, memory, time and output.
- Every outbound call must use HTTPS to a public address. Private, internal and cloud metadata addresses are blocked, and connections are pinned to the checked address.
- In the planned production setup, the network blocks the same addresses a second time. Liitora’s services can only reach the egress proxy, the database and the secret store inside our network, and only the egress proxy can reach the internet. It cannot reach private, internal or cloud metadata addresses either.
- Every connection to your systems leaves through one egress proxy, from one fixed address you can allow in your firewall (shown in Settings). The proxy checks the address and port again, only lets Liitora’s own services use it, and never logs what is sent. See Allow Liitora through your firewall.
- Production runs only run the version you activated, or another version that passed its tests and was approved. Test runs of other versions use your test connections, or run as dry runs that change nothing. The worker checks this again before every run, whatever started it.
- A test run or dry run of a version no person approved reads only the secrets that the last approved version reads, sends web requests only to the hosts of its own connections, and sends no email.
- Webhooks are checked with HMAC signatures and a replay window, with rate limits and size limits. A copy of a signed delivery never starts your workflows again. Every refusal looks the same, so attackers learn nothing.
Audit and monitoring
Section titled “Audit and monitoring”- The audit log records every change, every secret shown and every staff visit, with who did it. It can’t be edited.
- Our staff enter a company only through a time-limited session with a written reason, which appears in that company’s audit log. See What “managed by us” means.
How we build it
Section titled “How we build it”- Every change passes automated tests, including tests for company isolation, a permission check for every API route, and negative tests for the security rules above.
- The script checker, the workflow parser and other input handlers are also tested with fuzzing.
- Dependencies are kept up to date automatically.
Report a security issue
Section titled “Report a security issue”Use Report a problem in the user menu (top right) in the app. Don’t include secret values.