Skip to content

fix: protect method names from token registration collisions - #359

Open
baima365-web wants to merge 2 commits into
expressjs:masterfrom
baima365-web:fix/token-reserved-name
Open

fix: protect method names from token registration collisions#359
baima365-web wants to merge 2 commits into
expressjs:masterfrom
baima365-web:fix/token-reserved-name

Conversation

@baima365-web

Copy link
Copy Markdown

Problem

Calling morgan.token('token', fn) overwrites the morgan.token() method itself, breaking all subsequent token registrations. This is because morgan serves as both the module export (with methods token, format, compile) and the token registry.

Example:

var logger = require('morgan');
logger.token('token', function (req, res) { return 'value' });
// morgan.token is now the custom function, not the registration method
logger.token('uuid', function (req, res) { return 'uuid' }); // TypeError: tokens.uuid is not a function

Fix

Make the token, format, and compile methods non-writable using Object.defineProperties. This prevents user token registrations from overwriting the module API while maintaining full backward compatibility.

Test plan

  • Existing built-in tokens work correctly
  • Custom token registration works
  • Compiled format functions resolve tokens correctly
  • Middleware logs correctly
  • Registering reserved names (token, format, compile) now throws instead of silently breaking

ForgeCore and others added 2 commits July 7, 2026 03:50
Prevent token registration from overwriting module methods (token,
format, compile) by making them non-writable. Previously, calling
morgan.token('token', fn) would overwrite the morgan.token() method,
breaking subsequent token registrations.

Fixes expressjs#265

@UlisesGascon UlisesGascon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! WDYT @jonchurch @bjohansebas ?

@bjohansebas bjohansebas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, should we add tests?

@krzysdz krzysdz left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this prevents accidentally overwriting important functions, there are still some rather unexpected behaviours:

  1. There is completely no information that the given token or format cannot be defined (this will become clear if someone tries to use it, but may be hard to debug).
  2. Formats and tokens can overwrite each other. While overwriting a token with a different token with the same name or overwriting a format with a different format using the same name (like I have previously suggested in #303 (comment), so #377 now depends on this behaviour) is something that IMO should be possible, format-token collisions should not happen.

Would it be a breaking change if formats and tokens were not defined directly as morgan properties, but instead lived separately as morgan.tokens and morgan.formats or something similar? This would allow using any names (no conflicts with the morgan functions) and get rid of collisions.

morgan/index.js

Lines 492 to 495 in 51007f9

function format (name, fmt) {
morgan[name] = fmt
return this
}

morgan/index.js

Lines 579 to 582 in 51007f9

function token (name, fn) {
morgan[name] = fn
return this
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants