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.
Security Hardening Checklist
Section titled “Security Hardening Checklist”- Set the
ENCRYPTION_KEYconfig variable to a long, cryptographically random string. Store it safely. - Secure database user accounts:
- Make sure the katalogue_superuser database user only have the default permissions and a strong password.
- Make sure admin database users are few and have strong passwords. Ideally, avoid the default postgres username.
- Configure Cookies and CORS properly.
- Deploy Katalogue behind a VPN/firewall, never expose it to the internet.
- Ensure all communication between services is enforced to HTTPS.
- 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.
- Go through the security hardening steps for the app registration in Azure.
- Disable local user authentication (Settings -> Authentication and uncheck Enable Local Authentication). This disables the feature to create and use local user accounts in Katalogue.
- If local user authentication cannot be disabled, make sure to update the admin user’s default password.
- 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.
- Enable password manager integration for datasource connections and store all datasource connection passwords there. This relieves Katalogue from storing user account passwords.
- 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.jsonconfig file. Configuration cannot be injected during the Docker build stage: the.dockerignorefiles exclude realappsettingsfiles from the build context, because anything copied into an image is readable by anyone who can pull it. - 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.
- Review the rate limiting configuration and tighten the defaults if Katalogue is exposed to a broad or untrusted network.
- Limit the number of Katalogue admin users to as few as possible.
- Documentation & Processes:
- Document your deployment.
- Store all passwords in keyvaults or other safe places.
- Setup backup & restore processes for the database.
- 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.
Supply Chain Security
Section titled “Supply Chain Security”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.
What Katalogue does
Section titled “What Katalogue does”- Dependency install scripts are disabled. The payload in these attacks is delivered through an npm lifecycle script — a
preinstallorpostinstallentry that runs automatically as part ofnpm install. Every Katalogue package directory carries an.npmrcwithignore-scripts=true, and bothDockerfiles pass--ignore-scriptsexplicitly. Nothing a compromised dependency declares will run at install time. - Dependencies are installed from committed lockfiles. Builds and deployments use
npm ci, which installs the exact versions recorded inpackage-lock.json. Resolving a newer version is a deliberate, reviewed step rather than something an install can do on its own. - 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
utilsoperator tooling, so a running container carries no utility for encrypting or generating keys with its ownENCRYPTION_KEY. - 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_moduleswhile 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.
If you maintain a Katalogue deployment
Section titled “If you maintain a Katalogue deployment”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 inpackage-lock.jsonand never resolves anything newer, so the result is reproducible. Keep the lockfile under version control, and do not usenpm installfor this. - To add or upgrade a dependency, use
npm install <package>. This is the one case wherenpm installis correct, becausenpm cicannot change the lockfile. Let the new version age first —npm install <package> --before=<date>resolves to what was published before that date. Note that--beforeapplies to everything it resolves, not only the named package, so check what changed afterwards. - Review the
package-lock.jsondiff 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 signaturesto verify that installed packages match what the registry signed.
Blast radius
Section titled “Blast radius”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.
If you were affected
Section titled “If you were affected”Assume that anything the affected machine could read has been taken, and that removing the package afterwards does not undo it.
- Treat the developer workstation, build agent or container as compromised. Rebuild it rather than cleaning it.
- Rotate
REPOSITORY_PASSWORD,OIDC_CLIENT_SECRETandMAIL_PASSWORD, and rotate the REST API signing key from Settings. - Re-provision every datasource connection password, at the source systems as well as in Katalogue.
- Rotate any credential that was present in the environment but not owned by Katalogue — cloud CLI tokens, container registry logins, SSH keys, CI secrets.
ENCRYPTION_KEYcannot 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.- Review the Katalogue audit log and your source systems for access you cannot account for.