Skip to content

Commit 6045b1e

Browse files
chore(deps): update (#5444)
1 parent ffd0b86 commit 6045b1e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+4691
-2997
lines changed

.cspell.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@
7070
"commitlint",
7171
"eslintcache",
7272
"hono",
73-
"privkey"
73+
"privkey",
74+
"geomanist"
7475
],
7576
"ignorePaths": [
7677
"CHANGELOG.md",

client-src/socket.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ let maxRetries = 10;
2222
// eslint-disable-next-line import/no-mutable-exports
2323
export let client = null;
2424

25+
let timeout;
26+
2527
/**
2628
* @param {string} url
2729
* @param {{ [handler: string]: (data?: any, params?: any) => any }} handlers
@@ -33,6 +35,10 @@ const socket = function initSocket(url, handlers, reconnect) {
3335
client.onOpen(() => {
3436
retries = 0;
3537

38+
if (timeout) {
39+
clearTimeout(timeout);
40+
}
41+
3642
if (typeof reconnect !== "undefined") {
3743
maxRetries = reconnect;
3844
}
@@ -57,7 +63,7 @@ const socket = function initSocket(url, handlers, reconnect) {
5763

5864
log.info("Trying to reconnect...");
5965

60-
setTimeout(() => {
66+
timeout = setTimeout(() => {
6167
socket(url, handlers, reconnect);
6268
}, retryInMs);
6369
}

examples/.assets/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ table {
7474
code {
7575
background-color: rgba(70, 94, 105, 0.06);
7676
border-radius: 3px;
77-
font-family: "Source Code Pro", Consolas, "Liberation Mono", Menlo, Courier,
78-
monospace;
77+
font-family:
78+
"Source Code Pro", Consolas, "Liberation Mono", Menlo, Courier, monospace;
7979
font-size: 1.44rem;
8080
margin: 0;
8181
max-width: 100%;

lib/Server.js

Lines changed: 142 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ function useFn(route, fn) {
307307
return /** @type {BasicApplication} */ ({});
308308
}
309309

310+
const DEFAULT_ALLOWED_PROTOCOLS = /^(file|.+-extension):/i;
311+
310312
/**
311313
* @typedef {Object} BasicApplication
312314
* @property {typeof useFn} use
@@ -1961,7 +1963,7 @@ class Server {
19611963
(req.headers);
19621964
const headerName = headers[":authority"] ? ":authority" : "host";
19631965

1964-
if (this.checkHeader(headers, headerName, true)) {
1966+
if (this.isValidHost(headers, headerName)) {
19651967
next();
19661968
return;
19671969
}
@@ -2668,8 +2670,9 @@ class Server {
26682670

26692671
if (
26702672
!headers ||
2671-
!this.checkHeader(headers, "host", true) ||
2672-
!this.checkHeader(headers, "origin", false)
2673+
!this.isValidHost(headers, "host") ||
2674+
!this.isValidHost(headers, "origin") ||
2675+
!this.isSameOrigin(headers)
26732676
) {
26742677
this.sendMessage([client], "error", "Invalid Host/Origin header");
26752678

@@ -2703,7 +2706,8 @@ class Server {
27032706

27042707
if (
27052708
this.options.client &&
2706-
/** @type {ClientConfiguration} */ (this.options.client).reconnect
2709+
/** @type {ClientConfiguration} */
2710+
(this.options.client).reconnect
27072711
) {
27082712
this.sendMessage(
27092713
[client],
@@ -2718,9 +2722,9 @@ class Server {
27182722
/** @type {ClientConfiguration} */
27192723
(this.options.client).overlay
27202724
) {
2721-
const overlayConfig = /** @type {ClientConfiguration} */ (
2722-
this.options.client
2723-
).overlay;
2725+
const overlayConfig =
2726+
/** @type {ClientConfiguration} */
2727+
(this.options.client).overlay;
27242728

27252729
this.sendMessage(
27262730
[client],
@@ -3106,106 +3110,182 @@ class Server {
31063110

31073111
/**
31083112
* @private
3109-
* @param {{ [key: string]: string | undefined }} headers
3110-
* @param {string} headerToCheck
3111-
* @param {boolean} allowIP
3113+
* @param {string} value
31123114
* @returns {boolean}
31133115
*/
3114-
checkHeader(headers, headerToCheck, allowIP) {
3116+
isHostAllowed(value) {
3117+
const { allowedHosts } = this.options;
3118+
31153119
// allow user to opt out of this security check, at their own risk
31163120
// by explicitly enabling allowedHosts
3121+
if (allowedHosts === "all") {
3122+
return true;
3123+
}
3124+
3125+
// always allow localhost host, for convenience
3126+
// allow if value is in allowedHosts
3127+
if (Array.isArray(allowedHosts) && allowedHosts.length > 0) {
3128+
for (let hostIdx = 0; hostIdx < allowedHosts.length; hostIdx++) {
3129+
/** @type {string} */
3130+
const allowedHost = allowedHosts[hostIdx];
3131+
3132+
if (allowedHost === value) {
3133+
return true;
3134+
}
3135+
3136+
// support "." as a subdomain wildcard
3137+
// e.g. ".example.com" will allow "example.com", "www.example.com", "subdomain.example.com", etc
3138+
if (allowedHost[0] === ".") {
3139+
// "example.com" (value === allowedHost.substring(1))
3140+
// "*.example.com" (value.endsWith(allowedHost))
3141+
if (
3142+
value === allowedHost.substring(1) ||
3143+
/** @type {string} */
3144+
(value).endsWith(allowedHost)
3145+
) {
3146+
return true;
3147+
}
3148+
}
3149+
}
3150+
}
3151+
3152+
// Also allow if `client.webSocketURL.hostname` provided
3153+
if (
3154+
this.options.client &&
3155+
typeof (
3156+
/** @type {ClientConfiguration} */
3157+
(this.options.client).webSocketURL
3158+
) !== "undefined"
3159+
) {
3160+
return (
3161+
/** @type {WebSocketURL} */
3162+
(/** @type {ClientConfiguration} */ (this.options.client).webSocketURL)
3163+
.hostname === value
3164+
);
3165+
}
3166+
3167+
return false;
3168+
}
3169+
3170+
/**
3171+
* @private
3172+
* @param {{ [key: string]: string | undefined }} headers
3173+
* @param {string} headerToCheck
3174+
* @returns {boolean}
3175+
*/
3176+
isValidHost(headers, headerToCheck) {
31173177
if (this.options.allowedHosts === "all") {
31183178
return true;
31193179
}
31203180

31213181
// get the Host header and extract hostname
31223182
// we don't care about port not matching
3123-
const hostHeader = headers[headerToCheck];
3183+
const header = headers[headerToCheck];
31243184

3125-
if (!hostHeader) {
3185+
if (!header) {
31263186
return false;
31273187
}
31283188

3129-
if (/^(file|.+-extension):/i.test(hostHeader)) {
3189+
if (DEFAULT_ALLOWED_PROTOCOLS.test(header)) {
31303190
return true;
31313191
}
31323192

31333193
// use the node url-parser to retrieve the hostname from the host-header.
31343194
const hostname = url.parse(
3135-
// if hostHeader doesn't have scheme, add // for parsing.
3136-
/^(.+:)?\/\//.test(hostHeader) ? hostHeader : `//${hostHeader}`,
3195+
// if header doesn't have scheme, add // for parsing.
3196+
/^(.+:)?\/\//.test(header) ? header : `//${header}`,
31373197
false,
31383198
true,
31393199
).hostname;
31403200

3141-
// allow requests with explicit IPv4 or IPv6-address if allowIP is true.
3142-
// Note that IP should not be automatically allowed for Origin headers,
3143-
// otherwise an untrusted remote IP host can send requests.
3144-
//
3201+
if (hostname === null) {
3202+
return false;
3203+
}
3204+
3205+
if (this.isHostAllowed(hostname)) {
3206+
return true;
3207+
}
3208+
3209+
// always allow requests with explicit IPv4 or IPv6-address.
31453210
// A note on IPv6 addresses:
3146-
// hostHeader will always contain the brackets denoting
3211+
// header will always contain the brackets denoting
31473212
// an IPv6-address in URLs,
31483213
// these are removed from the hostname in url.parse(),
31493214
// so we have the pure IPv6-address in hostname.
31503215
// For convenience, always allow localhost (hostname === 'localhost')
31513216
// and its subdomains (hostname.endsWith(".localhost")).
31523217
// allow hostname of listening address (hostname === this.options.host)
31533218
const isValidHostname =
3154-
(allowIP &&
3155-
hostname !== null &&
3156-
(ipaddr.IPv4.isValid(hostname) || ipaddr.IPv6.isValid(hostname))) ||
3219+
ipaddr.IPv4.isValid(hostname) ||
3220+
ipaddr.IPv6.isValid(hostname) ||
31573221
hostname === "localhost" ||
3158-
(hostname !== null && hostname.endsWith(".localhost")) ||
3222+
hostname.endsWith(".localhost") ||
31593223
hostname === this.options.host;
31603224

31613225
if (isValidHostname) {
31623226
return true;
31633227
}
31643228

3165-
const { allowedHosts } = this.options;
3229+
// disallow
3230+
return false;
3231+
}
31663232

3167-
// always allow localhost host, for convenience
3168-
// allow if hostname is in allowedHosts
3169-
if (Array.isArray(allowedHosts) && allowedHosts.length > 0) {
3170-
for (let hostIdx = 0; hostIdx < allowedHosts.length; hostIdx++) {
3171-
/** @type {string} */
3172-
const allowedHost = allowedHosts[hostIdx];
3233+
/**
3234+
* @private
3235+
* @param {{ [key: string]: string | undefined }} headers
3236+
* @returns {boolean}
3237+
*/
3238+
isSameOrigin(headers) {
3239+
if (this.options.allowedHosts === "all") {
3240+
return true;
3241+
}
31733242

3174-
if (allowedHost === hostname) {
3175-
return true;
3176-
}
3243+
const originHeader = headers.origin;
31773244

3178-
// support "." as a subdomain wildcard
3179-
// e.g. ".example.com" will allow "example.com", "www.example.com", "subdomain.example.com", etc
3180-
if (allowedHost[0] === ".") {
3181-
// "example.com" (hostname === allowedHost.substring(1))
3182-
// "*.example.com" (hostname.endsWith(allowedHost))
3183-
if (
3184-
hostname === allowedHost.substring(1) ||
3185-
/** @type {string} */ (hostname).endsWith(allowedHost)
3186-
) {
3187-
return true;
3188-
}
3189-
}
3190-
}
3245+
if (!originHeader) {
3246+
return this.options.allowedHosts === "all";
31913247
}
31923248

3193-
// Also allow if `client.webSocketURL.hostname` provided
3194-
if (
3195-
this.options.client &&
3196-
typeof (
3197-
/** @type {ClientConfiguration} */ (this.options.client).webSocketURL
3198-
) !== "undefined"
3199-
) {
3200-
return (
3201-
/** @type {WebSocketURL} */
3202-
(/** @type {ClientConfiguration} */ (this.options.client).webSocketURL)
3203-
.hostname === hostname
3204-
);
3249+
if (DEFAULT_ALLOWED_PROTOCOLS.test(originHeader)) {
3250+
return true;
32053251
}
32063252

3207-
// disallow
3208-
return false;
3253+
const origin = url.parse(originHeader, false, true).hostname;
3254+
3255+
if (origin === null) {
3256+
return false;
3257+
}
3258+
3259+
if (this.isHostAllowed(origin)) {
3260+
return true;
3261+
}
3262+
3263+
const hostHeader = headers.host;
3264+
3265+
if (!hostHeader) {
3266+
return this.options.allowedHosts === "all";
3267+
}
3268+
3269+
if (DEFAULT_ALLOWED_PROTOCOLS.test(hostHeader)) {
3270+
return true;
3271+
}
3272+
3273+
const host = url.parse(
3274+
// if hostHeader doesn't have scheme, add // for parsing.
3275+
/^(.+:)?\/\//.test(hostHeader) ? hostHeader : `//${hostHeader}`,
3276+
false,
3277+
true,
3278+
).hostname;
3279+
3280+
if (host === null) {
3281+
return false;
3282+
}
3283+
3284+
if (this.isHostAllowed(host)) {
3285+
return true;
3286+
}
3287+
3288+
return origin === host;
32093289
}
32103290

32113291
/**

0 commit comments

Comments
 (0)