Skip to content

Commit f39aa3e

Browse files
conorluddyclaude
andcommitted
fix(security): explicit JWT algorithm; body size limit
Restrict JWT sign/verify to HS256 explicitly β€” prevents algorithm confusion attacks if the library ever changes its default or an attacker crafts a token with alg:none. Add express.json({ limit: '10kb' }) to make the default body size limit explicit and prevent oversized payload abuse. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f100368 commit f39aa3e

6 files changed

Lines changed: 8 additions & 7 deletions

File tree

β€Ž.github/type-coverage.jsonβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
"succeeded": true,
33
"atLeast": 90,
44
"atLeastFailed": false,
5-
"correctCount": 6491,
5+
"correctCount": 6494,
66
"percent": 98.54,
77
"percentString": "98.54",
8-
"totalCount": 6587
8+
"totalCount": 6590
99
}

β€Žpackage-lock.jsonβ€Ž

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

β€Žpackage.jsonβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "residents",
3-
"version": "0.3.8",
3+
"version": "0.3.9",
44
"author": "Conor Luddy <conorluddy@gmail.com>",
55
"license": "MIT",
66
"description": "Residents is a Node.js Express back-end foundation designed for bootstrapping new projects quickly and efficiently. Its main goal is to set up a robust infrastructure for user management, because users are the core of any application. These users are your Residents. It leverages a robust stack including Postgres, Drizzle ORM, JWT, PassportJS, Docker and Swagger to streamline development and deployment processes.",

β€Žsrc/index.tsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ if (process.env.NODE_ENV === 'development') {
4242
app.disable('x-powered-by')
4343
app.use(helmet())
4444
app.use(rateLimiter)
45-
app.use(express.json())
45+
app.use(express.json({ limit: '10kb' }))
4646

4747
// Health check
4848
app.get('/health', (_req, res) => {

β€Žsrc/middleware/auth/jsonWebTokens.tsβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const authenticateToken = (req: ResidentRequest, _res: Response<ResidentR
2020
throw new InternalServerError(MESSAGES.JWT_SECRET_NOT_DEFINED)
2121
}
2222

23-
jwt.verify(token, secret, (err, user) => {
23+
jwt.verify(token, secret, { algorithms: ['HS256'] }, (err, user) => {
2424
if (err) {
2525
throw new UnauthorizedError(MESSAGES.TOKEN_INVALID)
2626
}

β€Žsrc/utils/generateJwt.tsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const generateJwtFromUser = (user: User | SafeUser | PublicUser, expiryOv
1212
throw new Error(MESSAGES.JWT_SECRET_NOT_FOUND)
1313
}
1414
return jwt.sign(userToPublicUser(user), JWT_TOKEN_SECRET, {
15+
algorithm: 'HS256',
1516
expiresIn: (expiryOverride ?? EXPIRATION_JWT_TOKEN ?? DEFAULT_EXPIRATION) as StringValue,
1617
})
1718
}

0 commit comments

Comments
Β (0)