Summary
Zipline allows configuration via environment variables, such as OAUTH_OIDC_CLIENT_SECRET= and OAUTH_OIDC_CLIENT_SECRET_FILE=. The server logs, on startup, the contents of sensitive data like client secrets without redaction, resulting in a leakage in logging facilities (e.g. system journal, docker logs, etc.)
Details
The code that logs the environment variables (envvar) is as below:
|
for (const [propPath, val] of Object.entries(dbEnv)) { |
|
const col = Object.entries(DATABASE_TO_PROP).find(([_colName, path]) => path === propPath)?.[0]; |
|
if (col) { |
|
database[col] = val; |
|
if (!global.__tamperedConfig__) { |
|
global.__tamperedConfig__ = []; |
|
} |
|
|
|
global.__tamperedConfig__.push(col); |
|
logger.info('overriding database value from env', { col, value: val }); |
|
} |
|
} |
The code logs the name and value of every envvar that corresponds to/overrides a database property. (As such, this does not apply to CORE_SECRET.)
No attempt at masking the contents of certain sensitive envvars is made, causing credentials to be leaked to the logs.
PoC
Assuming a Docker setup, the following steps are needed. However, the general procedure apply to something like NixOS.
- Insert credentials in
.env and a secret file:
$ cat >> .env <<EOF
OAUTH_OIDC_AUTHORIZE_URL=https://op.invalid/auth
OAUTH_OIDC_TOKEN_URL=https://op.invalid/oidc/token
OAUTH_OIDC_USERINFO_URL=https://op.invalid/oidc/userinfo
OAUTH_OIDC_CLIENT_ID=$(uuidgen)
OAUTH_OIDC_CLIENT_SECRET=$(openssl rand -base64 32)
OAUTH_DISCORD_CLIENT_ID=anything
OAUTH_DISCORD_CLIENT_SECRET_FILE=/run/secrets/discord_csecret
EOF
$ echo "from_discord_token_file" > discord_csecret
- Configure Docker to load the secret:
services:
zipline:
secrets:
- discord_csecret
secrets:
discord_csecret:
file: discord_csecret
- Observe the logs:
[2026-05-30T17:45:19 INFO server] starting zipline mode="production" version="4.6.1" argv=[]
[2026-05-30T17:45:19 INFO server] reading settings...
[2026-05-30T17:45:19 INFO config::read] overriding database value from env col="oauthDiscordClientId" value="anything"
[2026-05-30T17:45:19 INFO config::read] overriding database value from env col="oauthDiscordClientSecret" value="from_discord_token_file"
[2026-05-30T17:45:19 INFO config::read] overriding database value from env col="oauthOidcClientId" value="18329f69-64c7-4536-8116-453869fa9b64"
[2026-05-30T17:45:19 INFO config::read] overriding database value from env col="oauthOidcClientSecret" value="BQUWGM2xS+UFga19Ar5JQVtQCG+7306NXJiC8IRPEuQ="
...
Impact
An attacker with access to the logs may be able to intercept an OAuth2 callback and exchange a valid token with the client secret. Through the use of PKCE in versions >=4.6.0, this may be mitigated.
If there are other secrets available to be configured via environment variables, they will still be subject to this vulnerability.
Summary
Zipline allows configuration via environment variables, such as
OAUTH_OIDC_CLIENT_SECRET=andOAUTH_OIDC_CLIENT_SECRET_FILE=. The server logs, on startup, the contents of sensitive data like client secrets without redaction, resulting in a leakage in logging facilities (e.g. system journal, docker logs, etc.)Details
The code that logs the environment variables (envvar) is as below:
zipline/src/lib/config/read/index.ts
Lines 163 to 174 in e378944
The code logs the name and value of every envvar that corresponds to/overrides a database property. (As such, this does not apply to
CORE_SECRET.)No attempt at masking the contents of certain sensitive envvars is made, causing credentials to be leaked to the logs.
PoC
Assuming a Docker setup, the following steps are needed. However, the general procedure apply to something like NixOS.
.envand a secret file:Impact
An attacker with access to the logs may be able to intercept an OAuth2 callback and exchange a valid token with the client secret. Through the use of PKCE in versions
>=4.6.0, this may be mitigated.If there are other secrets available to be configured via environment variables, they will still be subject to this vulnerability.