Skip to content

Commit b95f4ab

Browse files
wyattjohztanner
authored andcommitted
[i18n] Routing fix (#70761)
This fixes a bug where an incorrectly sanitized query parameter would cause an invalid routing condition resulting in the wrong route being served to users. This currently requires some specific edge conditions in order to trigger such as missing i18n configuration, self-hosted, specifically crafted query parameter, and a path-based middleware for authorization.
1 parent bb3f580 commit b95f4ab

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

packages/next/src/server/base-server.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,14 @@ export default abstract class Server<ServerOptions extends Options = Options> {
908908
req.headers['x-forwarded-proto'] ??= isHttps ? 'https' : 'http'
909909
req.headers['x-forwarded-for'] ??= originalRequest.socket?.remoteAddress
910910

911+
// Validate that if i18n isn't configured or the passed parameters are not
912+
// valid it should be removed from the query.
913+
if (!this.i18nProvider?.validateQuery(parsedUrl.query)) {
914+
delete parsedUrl.query.__nextLocale
915+
delete parsedUrl.query.__nextDefaultLocale
916+
delete parsedUrl.query.__nextInferredLocaleFromDefault
917+
}
918+
911919
// This should be done before any normalization of the pathname happens as
912920
// it captures the initial URL.
913921
this.attachRequestMeta(req, parsedUrl)

packages/next/src/server/future/helpers/i18n-provider.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,37 @@ export class I18NProvider {
134134
}
135135
}
136136

137+
/**
138+
* Validates that the locale is valid.
139+
*
140+
* @param locale The locale to validate.
141+
* @returns `true` if the locale is valid, `false` otherwise.
142+
*/
143+
private validate(locale: string): boolean {
144+
return this.lowerCaseLocales.includes(locale.toLowerCase())
145+
}
146+
147+
/**
148+
* Validates that the locales in the query object are valid.
149+
*
150+
* @param query The query object to validate.
151+
* @returns `true` if the locale is valid, `false` otherwise.
152+
*/
153+
public validateQuery(query: NextParsedUrlQuery) {
154+
if (query.__nextLocale && !this.validate(query.__nextLocale)) {
155+
return false
156+
}
157+
158+
if (
159+
query.__nextDefaultLocale &&
160+
!this.validate(query.__nextDefaultLocale)
161+
) {
162+
return false
163+
}
164+
165+
return true
166+
}
167+
137168
/**
138169
* Analyzes the pathname for a locale and returns the pathname without it.
139170
*

packages/next/src/server/lib/router-utils/resolve-routes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ export function getResolveRoutes(
214214
parsedUrl.pathname = maybeAddTrailingSlash(parsedUrl.pathname)
215215
}
216216
}
217+
} else {
218+
// As i18n isn't configured we remove the locale related query params.
219+
delete parsedUrl.query.__nextLocale
220+
delete parsedUrl.query.__nextDefaultLocale
221+
delete parsedUrl.query.__nextInferredLocaleFromDefault
217222
}
218223

219224
const checkLocaleApi = (pathname: string) => {

0 commit comments

Comments
 (0)