In this section we give an overview of our security processes, designs and mitigations.

Security-first development approach


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].

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.

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.

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.

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

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.


We are aware that even when a memory-safe language like Rust is used disaster can strike nonetheless. Our services are containerized 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.