Skip to content

Secure development policy

How we build, test and release our software securely. It applies to every employee who writes, reviews or deploys code for our products, and to the bots and AI tools that work for them.

Annex A controls: 5.32, 8.25, 8.26, 8.27, 8.28, 8.29, 8.31, 8.33.

  • All source code lives in GitLab. Work starts from an issue or epic; a small, obvious change can start from a merge request (GitLab workflow).
  • Changes are made on a feature branch and reach the default branch only through a merge request. The default branch of every product repository is protected: nobody pushes to it directly and only maintainers merge.
  • Every change to the default branch is reviewed and approved by at least one person other than the author, after its pipeline passes and no open threads are left (code review conventions).
  • The only exception is automated dependency updates: Renovate merges a minor or patch update on its own when its pipeline passes. AI bots never merge (helper bots).
  • Releases follow the branching strategy: the default branch deploys to staging, the release branch or a release tag deploys to production, and a hotfix lands on the default branch first.
  • New developers learn these rules in the bootcamp: they read this policy, the conventions and the OWASP Top 10, and they learn the practice of each project through code review.
  • The epic or issue for a new application, a new external interface or a feature that handles personal or customer data lists its security requirements. The Project lead approves them before development starts.
  • Every application meets these baseline requirements:
    • it serves traffic over HTTPS only;
    • it authenticates users and API clients before they reach non-public data, and checks their rights on every request;
    • it validates input from users and other systems before using it;
    • it reads secrets from its environment or a secret store, never from the repository;
    • it stores only the personal data it needs, as the information handling policy describes;
    • it reports errors to Sentry without secrets in the report.
  • For an application we buy or subscribe to, the requirements are part of the supplier check in the supplier management policy.

Architecture and engineering principles (8.27)

Section titled “Architecture and engineering principles (8.27)”
  • Applications run in the EU on servers we manage ourselves, deployed with Coolify or Ansible (deployments), without vendor lock-in.
  • Defence in depth: firewall, TLS, authentication and authorisation each protect on their own, so one failing layer does not expose a system.
  • Least privilege: people, bots and services get only the access they need. Production credentials are limited to the engineers who run production (Bitwarden collections).
  • We prefer well-maintained external libraries over custom code and lock their versions (external dependencies).
  • Every environment runs a known build: images use immutable tags (image tags and pull policy) and are built in CI (CI image builds).
  • Health checks that trigger automated reactions stay shallow, so a failing dependency cannot take a healthy service down (health checks).
  • A change to the architecture of a product is a big change and gets a security impact check, as the change management policy describes.
  • Code follows the conventions for its language and domain. Linters, formatters and type checks in the pipeline enforce them.
  • Code that handles input applies the OWASP Top 10, such as parameterised queries through the ORM and output encoding in the frontend.
  • Secrets stay out of code, images and logs: they live in Bitwarden and in the environment variables of the deployment, and image builds pass them as build secrets (CI image builds).
  • Dependencies come from their official registries with locked versions. Renovate keeps them current, waits a few days after each release before proposing it, and labels updates that fix a known vulnerability (auto-update with Renovate).
  • AI-assisted coding follows the guardrails: no secrets or confidential client data go to cloud AI services, and AI-written code gets the same human review as any other change. The AI review assistant supports the reviewer but never replaces the approval.
  • The pipeline of every merge request runs the automated tests of the project (testing) and the security scanners it uses, such as static analysis, secret scanning and container scanning. A merge request with a failing pipeline is not merged.
  • The reviewer checks the security-relevant paths of a change (authentication, authorisation, handling of personal data) and that tests cover them.
  • A change is accepted on a review environment or on staging before it reaches production. Issues that can only be verified in production stay open until they are (release verification).
  • Development (laptops and personal development containers), review (one temporary environment per merge request), staging and production are separate environments.
  • Production runs on its own servers. Staging and review environments on Coolify run on internal servers that are reachable only from the office network and the company VPN (production and staging environments).
  • Production credentials are separate from development and review credentials: they live in the Prod collections of Bitwarden and in CI variables scoped to the production environment.
  • Production is deployed by the pipeline from the release branch or a release tag. Any other change to production follows the change management policy.
  • Tests and test environments use generated or seeded data, such as seed scripts and test accounts (testing).
  • Personal or customer data from production is not copied to development, review or staging environments. When a copy is unavoidable, for example to reproduce a customer issue, the Project lead approves it in the issue, the data is reduced and anonymised as far as possible, protected like production, and deleted when the work is done.
  • Load tests replay realistic traffic without personal data.
  • Before adding a dependency, the developer checks its licence. Permissive licences such as MIT, BSD, ISC and Apache-2.0 can be used. A licence that restricts commercial use, or whose obligations the product cannot meet (such as copyleft in closed-source code), needs the approval of the Project lead.
  • Images, fonts, texts and code snippets from third parties are used only when their licence allows our use.
  • Paid software and subscriptions are bought by the company and used within their licence terms. AI subscriptions are bought centrally (AI tools).
  • Products we publish as open source state their licence in their repository.
  • The Information Security Officer owns this policy. Once a year they sample merge requests merged that year in each product to confirm that someone other than the author approved them and that their pipeline passed, and record the result as a recurring task.
  • The Project lead applies this policy in their product: security requirements, branch protection and pipeline settings, licence approvals and copies of production data.
  • Infrastructure runs the shared development tooling: CI runners, Renovate, the AI review assistant and the review and staging servers.
  • Employees who develop follow this policy; reviewers check it in every merge request.

Review: yearly by the Information Security Officer.