Skip to content

Security: Matgenix/datalab

Security

SECURITY.md

Security Policy

datalab is typically used to store research data - much of it unpublished, some of it commercially or academically sensitive - on infrastructure operated by the research groups and consortia that use it. This document describes how to report a vulnerability, what the software defends against, and which parts of the problem are left up to whoever deploys it.

Reporting a vulnerability

Please do not report security issues in public GitHub issues.

Report privately through either channel:

Please include the affected version, a description of the issue, and ideally a proof of concept and an assessment of impact.

What to expect:

Stage Target
Acknowledgement of your report 3 working days
Initial assessment and severity triage 10 working days
Fix or documented mitigation for high-severity issues 90 days from triage

We will keep you updated as we work, credit you in the advisory unless you would rather we didn't, and publish a GitHub Security Advisory when a fix is released, where appropriate. Severity is assessed using a risk-based approach that considers how easy the vulnerability is to exploit, what data or systems are affected, how exposed the deployment is, and whether the vulnerability is already being exploited. Critical vulnerabilities, or those known to be actively exploited, may require emergency mitigations, faster operator notification, and emergency releases. If we conclude a report is not a vulnerability, we will explain why.

datalab is maintained by a small academic-focused team (with commercial support through datalab industries ltd.), not a dedicated security organisation.

We will not pursue or support legal action against researchers who act in good faith: testing only against instances they own or have written permission to test, avoiding access to other people's data, avoiding degradation of live services, and giving us reasonable time to respond before disclosing publicly.

Do not test against instances you do not operate, including the public demo. Most deployments hold real, unpublished research data belonging to third parties.

Supported versions

Security fixes are typically issued for the latest released minor version only, though backports will be considered where there is a specific demand. datalab is pre-1.0 and under active development; operators are expected to track releases reasonably closely.

Trust model

What the software enforces

  • Authenticated access. Users authenticate via OAuth (Microsoft, Google, ORCID, GitHub), magic-link email, or API keys. Registration can be restricted by GitHub organisation membership or email domain, and accounts require admin activation by default. Administrative users are encouraged to authenticate through an identity provider with MFA enabled.
  • Per-item and per-group permissions. Every read and write is filtered by a permission query derived from the requesting user's identity, their group memberships, and any managed users. Items may inherit read access from collections they belong to; write access is never inherited. Inventory items (starting materials and equipment) are readable and editable by all users, unless restricted to one or more groups, in which case only members of those groups can access them. Deployments can set [UNGROUPED_INVENTORY][pydatalab.config.ServerConfig.UNGROUPED_INVENTORY] to warn users who create inventory items without a group, or to require one.
  • Hashed credentials at rest. API keys and item access tokens are stored as hashes, never in plaintext.
  • A write audit trail. Item edits are snapshotted as versions, attributed to the user who made them.

What it does not defend against

  • Instance administrators. An admin can read every item in the deployment via super-user mode. This is intentional but it means the operator of a shared or consortium instance can see all members' data. Consortia should establish who holds admin, and satisfy themselves about the governance around it, as an organisational control. Improved logging of administrative reads is planned.
  • Plugins. Plugins are Python packages loaded into the server process. They have full access to the database, the filesystem, and the network. Installing a plugin is therefore deployment decision with the same weight as a code change, and should be reviewed as one. There is no sandbox, and adding one is non-trivial. Operators should use an approved list of plugins, keep plugin versions fixed, verify their source and maintainers, and track plugin changes and inventory.
  • Malicious authenticated users. Users are treated as semi-trusted colleagues, but deployments should still account for risks such as stolen credentials, compromised endpoints, malicious insiders, and maliciously crafted files. Permissions constrain which data they reach, but a user who is authenticated and actively hostile has a large surface to work with, notably file uploads, which are parsed by a wide range of third-party scientific libraries which may be vulnerable to exploitation.
  • Infrastructure compromise. Host, container runtime, database, and network security are the operator's responsibility.

What the project does upstream

Practices in place in this repository today:

Dependency management

  • Dependabot covers four ecosystems monthly: Python (uv), npm, GitHub Actions, and the Docker base images.
  • Security advisories are provided by GitHub and Dependabot, and are triaged by the maintainers. Critical advisories are addressed in patch releases as soon as possible.
  • A scheduled workflow refreshes uv.lock pins monthly, so transitive dependencies don't drift and quietly retain known-vulnerable versions.
  • Server dependencies are fully pinned via uv.lock; CI and container builds install from the lockfile.
  • Aside from internal Python packages, no dependency newer than 5 days old is used in production. Security fixes may bypass this delay following maintainer review.
  • JavaScript app dependencies are pinned to exact versions in yarn.lock; yarn install --frozen-lockfile is used in CI and container builds.

Static analysis and CI

  • For server code, ruff runs with the flake8-bandit (S) security ruleset enabled, alongside mypy type checking. Both are enforced in CI through pre-commit hooks.
  • The full test suite runs against a matrix of supported Python versions on every pull request, with coverage reported.
  • The webapp is built and linted with eslint and this build is tested in CI on every pull request.
  • The web app is tested with a suite of Cypress end-to-end and component tests, run in the CI on every pull request.
  • The web app build and the plugin-installation path are both exercised in CI.

Application hardening

  • The Flask SECRET_KEY is checked for sufficient entropy at startup; the server refuses to run with a weak or absent key unless an explicit insecure-override environment variable is set.
  • Cross-origin access is split by credential type: the public API is readable from any origin using an explicit DATALAB-API-KEY header, while cookie-authenticated sessions are restricted to configured first-party origins.
  • Uploaded filenames are sanitised before being written to disk.
  • User-supplied SVG and Markdown are sanitised with DOMPurify before rendering.

Release integrity

  • PyPI releases use Trusted Publishing via OIDC, so no long-lived publishing token exists to be stolen.
  • Releases are built from tagged commits in GitHub Actions environments requiring approval.

Operator responsibilities

datalab is self-hostable, and a correctly written application on a badly configured host is not secure. The following are the deploying institution's responsibility:

  • Transport security. Terminate TLS at a reverse proxy and set BEHIND_REVERSE_PROXY. Never expose the API directly over plain HTTP.
  • Database access. MongoDB should be reachable only from the API container. Enable authentication on the database if it is reachable from anywhere else.
  • Origin configuration. Set APP_URL to the web app's URL so that cookie-authenticated requests are restricted to it.
  • Secrets. Supply PYDATALAB_SECRET_KEY and any OAuth secrets from the environment or a secrets manager, never from a file in version control.
  • Storage encryption. Enable full-disk encryption on the host volume, and encrypt backup artifacts. Note the limits of this: it protects against a stolen disk or a leaked snapshot, and not at all against compromise of a running server, since the database decrypts transparently for anyone who can connect.
  • Backups. Configure and, importantly, periodically test restoring them, ideally following the 3-2-1 rule. datalab provides a native way of creating scheduled snapshots, though this should likely be complemented with an incremental backup process (e.g., borg).
  • Remote filesystems. Scope any configured remote filesystem to the narrowest possible directory, using a dedicated account with read-only access.
  • Plugins. Review and pin them; treat additions as deployment changes.
  • Updates. Track releases and subscribe to this repository's security advisories.

There are a series of Ansible roles made available by datalab industries ltd. in datalab-ansible-terraform that cover several of these cases automatically. For example, certificate provisioning, backup scheduling and retention, monitoring and log ingestion are handled by the playbooks. See the deployment repository's own SECURITY.md for the infrastructure-side half of this policy.

Planned work

Improvements we intend to make. They are listed here so operators can see what is coming and what is not yet true; several are only meaningful in combination with a particular deployment, and none should be assumed present in a running instance.

  • A separate audit log stream. Security-relevant events (administrative reads, authentication, permission elevation) currently go to the general application log, which rotates with everything else. Emitting them on a dedicated logger would let operators retain them for longer and ship them to separate storage. The retention and destination remain a deployment choice — the software can only make the events cleanly separable.
  • Process isolation for block execution. Running block parsing in a worker with no database credentials and no network egress.
  • A rework of the existing permissions system. To enable increased flexiblility and to support more complex use cases, including the ability to delegate permissions to other users or groups across projects.

If any of these are blocking an adoption decision, please open an issue or get in touch; knowing which matter to real deployments helps us prioritise future development.

There aren't any published security advisories