Security
In this section we give an overview of our security processes, designs and mitigations.
Security-first Development Policies
Development Collaboration Platform
Gitlab is our development collaboration platform where all our development policies are enforced, continuous integration checks are run and dependency management tools are integrated.
Access rights to developers are granted conservatively, i.e. developers cannot change policies but need to request those changes from upper management.
Rust
We use Rust as our backend development language. Rust is a memory-safe language that compiles to machine code and thus doesn't compromise on performance while eliminating the primary source for security-related bugs [1][2][3].
Rust has seen growing adoption in both critical open source software [4] [5] [6] [7] and at Fortune 500 companies [8] [9] [10] [11].
Rust's safety guarantees are softened when using so-called unsafe
blocks. Our
policy is to forbid unsafe
code blocks which is enforced through a dedicated
compiler setting.
Code Review
We have strict code review policies in place that demand that every change to the source code needs to be reviewed and approved by another developer. Only then it can be merged into master. Among other aspects the reviewer is asked to focus on security. As a side-effect of our code review practices, know-how is spread across the team that shares the responsibility for the source code. This eliminates malware injection or sabotage from malicious insiders.
The code review policy is enforced by Gitlab.
Continuous Integration
Our continuous integration pipeline runs tests, linter checks and builds. Only if all tasks run successfully a change can be merged into master.
This continuous integration check policy is enforced by Gitlab.
Employing a security-in-depth approach, we use the cargo-audit
[12] vulnerability scanner to automatically scan our entire
dependency tree for versions with reported security vulnerabilities. This is
also run by the continuous integration system and hence, will block offending
changes from being merged into master. If issues arise on the master branch then
all merge requests will we blocked until the issue has been fixed on master.
This continuous integration check policy is enforced by Gitlab.
Dependency Management
We use tools that monitor our dependencies (libraries, docker images, etc.) and open merge requests once newer versions of dependencies become available. After they pass our continuous integration they are reviewed and can be confidently merged into master without introducing regressions or breaking the build. Updates that fail continuous integration are handled manually to ensure a quick update.
Having an efficient and effortless dependency management process enables us to constantly ship up-to-date software to our customers.
Security by Design
On-premise/Self-hosted solution
Our products are on-premise/self-hosted solutions, i.e. the software runs in the customer's data centre or cloud provider of the customer's choice.
21 Analytics has no means to access your deployment. In particular, 21 Analytics cannot access PII data, logging data or configuration data. In case of support requests the customer needs to grant access to 21 Analytics (e.g. via screen sharing during a video call) or share logging information (e.g. via upload to our help desk) such that we can provide them with advice.
Secure Architecture
Separation of Concerns
We have designed a micro service architecture where we apply the separation of concerns [13] principle. APIs accessible from the public internet are exposed in different micro services than APIs that interface with the custodial system.
In our reference deployment [14] those logical separations are enforced with a configuration that also splits them on a network level.
Principle of least privilege
Our services are stateless and use a database for persistence. We use database roles and permissions in accordance to the principle of least privilege [15] to refuse one microservice from accessing another's data.
Mitigation
We are aware that even when a memory-safe language like Rust is used disaster can strike nonetheless. Our services are containerised to isolate them from the host system. Furthermore, we statically compile our binaries which allows us to run them in empty containers. This significantly limits the attack surface in case of a successful memory-corruption exploit. For example, an attacker could not even gain access to libc or any binary useful for escalating the exploit chain like e.g. a shell.
Vendored Software
Our products don't comprise of vendored software components.
Open-source Software with Track Record
We use some off-the-shelf open-source software components with a high track record and are well-established in enterprise computing. The complete list of those components is as follows:
Resources
[1]
https://www.chromium.org/Home/chromium-security/memory-safety/
[2]
https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/
[3]
https://security.googleblog.com/2021/02/mitigating-memory-safety-issues-in-open.html
[4]
https://daniel.haxx.se/blog/2021/02/09/curl-supports-rustls/
[5]
https://security.googleblog.com/2021/04/rust-in-linux-kernel.html
[6]
https://security.googleblog.com/2021/04/rust-in-android-platform.html
[7]
https://www.abetterinternet.org/post/preparing-rustls-for-wider-adoption/
[8]
https://learn.microsoft.com/en-us/windows/dev-environment/rust/rust-for-windows
[9]
https://engineering.fb.com/2021/04/29/developer-tools/rust/
[10]
https://aws.amazon.com/blogs/opensource/why-aws-loves-rust-and-how-wed-like-to-help/
[11]
https://aws.amazon.com/blogs/opensource/sustainability-with-rust/
[12] https://rustsec.org/
[13]
https://en.wikipedia.org/wiki/Separation_of_concerns
[14]
https://docs.21analytics.ch/deployment/deployment.html
[15]
https://en.wikipedia.org/wiki/Principle_of_least_privilege