hyperdxio / hyperdxio/hyperdx

HyperDX Uses a Public Default Express Session Secret

Open
#3,089 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug external
Dominant language
TypeScript
Stars
9.9k
Forks
471
Avg merge
2d 4h
Merged PRs (30d)
117

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;

Source: config.ts

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));

Source: api-app.ts

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);
  });
});

Source: passport.ts

Protected routes rely on req.isAuthenticated():

if (req.isAuthenticated()) {
  return next();
}
res.sendStatus(401);

Source: auth.ts

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/me

Expected 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/api/src/config.ts and packages/api/src/api-app.ts to trace the session secret fallback and Express session setup, then review packages/api/src/utils/passport.ts and packages/api/src/middleware/auth.ts for authentication behavior. Done means authenticated deployments no longer use the public placeholder, missing or unsafe secrets fail closed, and existing sessions are rotated or invalidated as described.

Written by the indexing model from the issue text.

Assessment

Tech stack
express, mongodb, typescript
Domain
authentication, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.