Repository navigation
Description
HyperDX Uses a Public Default Express Session Secret
Summary
HyperDX uses the public value hyperdx is cool 👋 when
EXPRESS_SESSION_SECRET is not configured:
const DEFAULT_EXPRESS_SESSION = 'hyperdx is cool 👋';
export const EXPRESS_SESSION_SECRET = (env.EXPRESS_SESSION_SECRET ||
DEFAULT_EXPRESS_SESSION) as string;The value is used as the signing secret for the express-session cookie:
const sess = {
// ...
secret: config.EXPRESS_SESSION_SECRET,
store: new MongoStore({ mongoUrl: config.MONGO_URI }),
};
app.use(session(sess));Anyone who knows the public source can generate valid signatures for arbitrary
connect.sid values. This weakens the integrity protection of the session
cookie.
Authentication flow
The Session Cookie carries a Session ID. HyperDX stores the Passport user
identifier in the corresponding server-side session, and Passport later loads
the user from MongoDB:
passport.serializeUser(function (user, done) {
done(null, (user as any)._id);
});
passport.deserializeUser(function (id, done) {
findUserById(id).then(user => {
if (user == null) return done(null, false);
done(null, user);
});
});Protected routes rely on req.isAuthenticated():
if (req.isAuthenticated()) {
return next();
}
res.sendStatus(401);Proof of concept
Run this only against a local HyperDX test instance. The following creates a
correctly signed cookie for an attacker-chosen session ID:
const signature = require('cookie-signature');
const sessionId = 'attacker-chosen-session-id';
const signed = `s:${sessionId}.${signature.sign(
sessionId,
'hyperdx is cool 👋',
)}`;
console.log(encodeURIComponent(signed));Send the result to a protected API route:
curl -i \
-H 'Cookie: connect.sid=<url-encoded-signed-cookie>' \
http://127.0.0.1:8000/meExpected result: 401 Unauthorized. The cookie signature is valid, but the
chosen session ID has no corresponding authenticated session in MongoDB.
As a positive control, log in to the local test instance, retain the returned
connect.sid cookie, and request /me. The request succeeds because Passport
can recover the user from the server-side session.
Impact
The default hyperdx is cool 👋 secret allows an attacker to sign arbitrary
session-cookie values without knowing the deployment secret.
The secret alone does not prove arbitrary user impersonation in the current
flow. A successful impersonation would additionally require a session-state
weakness, such as disclosure or fixation of a valid session ID, or the ability
to create or modify the referenced MongoDB session.
The issue is directly exploitable in deployments that omit
EXPRESS_SESSION_SECRET and also expose one of those session-state
conditions. Otherwise, the demonstrated impact is the use of a public default
for a production authentication secret.
Remediation
- Remove
hyperdx is cool 👋as the fallback in authenticated deployments. - Require a deployment-specific high-entropy
EXPRESS_SESSION_SECRET. - Fail closed at startup when the secret is missing or equals the public
placeholder. - Rotate the secret and invalidate existing sessions after applying the fix.
Activity
brandon-pereira commentedon Sep 7, 2026
Hey there, having the default is handy because it allows people to experiment with the product very easily (just run one command to spin up the product).
However, I agree with the security risk, I propose we add/make it more clear that the env variable is using the default value when the container starts up so that users can see they are using a less secure environment.
If we need to, we can move this to a required value in the future.
We are open to a contribution for this feature if you are interested/open :)
28Hus commentedon Sep 8, 2026
@brandon-pereira Thank you for your patient reply! From the perspective of product usability, this design is indeed effective. To ensure usability while enhancing security, we can first remove all fallback values and then set the key to empty by default during deployment. When the backend detects that the current deployment key value is empty, it will generate a strongly random key unless the user actively configures it. If you agree with this design, I'd be happy to submit a proposal!
brandon-pereira commentedon Sep 10, 2026
@28Hus that makes sense - we should also be very clear when this happens as it can cause auth issues if someone restarts their server. Additionally, we need to make it clear in the changeset that the env variable is now strongly recommended (and some details of the symptoms people may see when upgrading if not set)
We would appreciate a PR for this change if you have the capacity - thanks for raising the issue!
fix(api): stop signing sessions with a public default secret (ClickHo…