Skip to content

Security Hardening

The following measures should be taken to make Katalogue as secure as possible in a production scenario. Coincidentially, most of these actions also reduce the management burden for Katalogue admins.

  1. Set the ENCRYPTION_KEY config variable to a long, cryptographically random string. Store it safely.
  2. Secure database user accounts:
    1. Make sure the katalogue_superuser database user only have the default permissions and a strong password.
    2. Make sure admin database users are few and have strong passwords. Ideally, avoid the default postgres username.
  3. Configure Cookies and CORS properly.
  4. Deploy Katalogue behind a VPN/firewall, never expose it to the internet.
  5. Ensure all communication between services is enforced to HTTPS.
  6. Use externally provisioned users provisioned through user groups, not local users nor individually added external users. This relieves Katalogue from storing user account passwords and automates user role assignments.
    1. Go through the security hardening steps for the app registration in Azure.
    2. Disable local user authentication (Settings -> Authentication and uncheck Enable Local Authentication). This disables the feature to create and use local user accounts in Katalogue.
    3. If local user authentication cannot be disabled, make sure to update the admin user’s default password.
  7. Restrict the user account permissions for accounts used in datasource connections to ingest metadata from source systems to only have read access to the required resources/tables.
  8. Enable password manager integration for datasource connections and store all datasource connection passwords there. This relieves Katalogue from storing user account passwords.
  9. Inject all configuration parameters that are secrets as environment variables/secrets in the startup phase of Docker containers. Do not store secrets in the appsettings.json config file. Configuration cannot be injected during the Docker build stage: the .dockerignore files exclude real appsettings files from the build context, because anything copied into an image is readable by anyone who can pull it.
  10. If the REST API service is enabled, consider using an externally provided signing key for access token signing. This relieves Katalogue from storing the private key.
  11. Review the rate limiting configuration and tighten the defaults if Katalogue is exposed to a broad or untrusted network.
  12. Limit the number of Katalogue admin users to as few as possible.
  13. Documentation & Processes:
    1. Document your deployment.
    2. Store all passwords in keyvaults or other safe places.
    3. Setup backup & restore processes for the database.
    4. Integrate logging with central logging functions.

If all of the steps above are followed, the only secrets Katalogue need to handle are the following:

  • ENCRYPTION_KEY - The Encryption key used to encrypt JWT cookies for authenticating requests from the frontend service.
  • REPOSITORY_PASSWORD - The repository database user password.
  • OIDC_CLIENT_SECRET - The Microsoft Entra Id app registration’s client secret.

Katalogue is a Node.js application and depends on packages from the public npm registry. There have been attacks that compromise a maintainer’s account, publish a poisoned version of a legitimate package, and execute malicious code on every machine that installs it.

  1. Dependency install scripts are disabled. The payload in these attacks is delivered through an npm lifecycle script — a preinstall or postinstall entry that runs automatically as part of npm install. Every Katalogue package directory carries an .npmrc with ignore-scripts=true, and both Dockerfiles pass --ignore-scripts explicitly. Nothing a compromised dependency declares will run at install time.
  2. Dependencies are installed from committed lockfiles. Builds and deployments use npm ci, which installs the exact versions recorded in package-lock.json. Resolving a newer version is a deliberate, reviewed step rather than something an install can do on its own.
  3. No secrets reach the build. All files that might contain secrets are excluded from the Docker build context, and configuration is supplied at container startup. The backend image also leaves out the utils operator tooling, so a running container carries no utility for encrypting or generating keys with its own ENCRYPTION_KEY.
  4. The frontend build runs with no network access. Disabling install scripts does not stop a bundler from executing webpack loaders and Babel plugins out of node_modules while it compiles, so a compromised build dependency does get to run at that point. Every package it needs is already installed by then, so the frontend image builds with --network=none: nothing can be sent out, and no second-stage payload can be fetched.

Installing the dependencies and changing which dependencies you have are two different operations, and they use different commands.

  • To install, always use npm ci. It installs exactly the versions recorded in package-lock.json and never resolves anything newer, so the result is reproducible. Keep the lockfile under version control, and do not use npm install for this.
  • To add or upgrade a dependency, use npm install <package>. This is the one case where npm install is correct, because npm ci cannot change the lockfile. Let the new version age first — npm install <package> --before=<date> resolves to what was published before that date. Note that --before applies to everything it resolves, not only the named package, so check what changed afterwards.
  • Review the package-lock.json diff on dependency changes. Updating everything at once produces a diff too large to read, which is exactly how an unexpected package slips through.
  • Run npm audit signatures to verify that installed packages match what the registry signed.

Understand what a successful attack would reach, because that determines what you must rotate.

ENCRYPTION_KEY protects everything Katalogue encrypts at rest. Code running inside the API process can use it to decrypt every stored datasource connection password, every setting marked as secret (OIDC_CLIENT_SECRET, MAIL_PASSWORD, REST_API_OIDC_SIGNING_KEY), and to read or forge session cookies. Local user account passwords and REST API client secrets are hashed rather than encrypted, and are not recoverable.

This is the reason for two recommendations earlier on this page. Using password manager integration for datasource connections means those credentials never sit in the repository database at all. Supplying secrets as Docker secrets rather than environment variables means they are not sitting in process.env, which is the first thing an infostealer reads.

Assume that anything the affected machine could read has been taken, and that removing the package afterwards does not undo it.

  1. Treat the developer workstation, build agent or container as compromised. Rebuild it rather than cleaning it.
  2. Rotate REPOSITORY_PASSWORD, OIDC_CLIENT_SECRET and MAIL_PASSWORD, and rotate the REST API signing key from Settings.
  3. Re-provision every datasource connection password, at the source systems as well as in Katalogue.
  4. Rotate any credential that was present in the environment but not owned by Katalogue — cloud CLI tokens, container registry logins, SSH keys, CI secrets.
  5. ENCRYPTION_KEY cannot currently be rotated once encrypted data exists. If it was exposed, the encrypted values in the repository database must be treated as compromised and re-created after redeploying with a new key.
  6. Review the Katalogue audit log and your source systems for access you cannot account for.