Skip to content

Commit 68ac95b

Browse files
authored
Add cookie-suffix flag (#7590)
1 parent 0de7cf5 commit 68ac95b

File tree

6 files changed

+22
-9
lines changed

6 files changed

+22
-9
lines changed

src/common/http.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ export class HttpError extends Error {
2424
}
2525
}
2626

27-
export enum CookieKeys {
28-
Session = "code-server-session",
27+
export function getCookieSessionName(suffix?: string): string {
28+
return suffix ? `code-server-session-${suffix.replace(/[^a-zA-Z0-9-]/g, "-")}` : "code-server-session"
2929
}

src/node/cli.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export interface UserProvidedCodeArgs {
5353
"disable-getting-started-override"?: boolean
5454
"disable-proxy"?: boolean
5555
"session-socket"?: string
56+
"cookie-suffix"?: string
5657
"link-protection-trusted-domains"?: string[]
5758
// locale is used by both VS Code and code-server.
5859
locale?: string
@@ -172,6 +173,12 @@ export const options: Options<Required<UserProvidedArgs>> = {
172173
"session-socket": {
173174
type: "string",
174175
},
176+
"cookie-suffix": {
177+
type: "string",
178+
description:
179+
"Adds a suffix to the cookie. This can prevent a collision of cookies for subdomains, making them explixit. \n" +
180+
"Without this flag, no suffix is used. This can also be set with CODE_SERVER_COOKIE_SUFFIX set to any string.",
181+
},
175182
"disable-file-downloads": {
176183
type: "boolean",
177184
description:
@@ -616,6 +623,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
616623
usingEnvPassword = false
617624
}
618625

626+
if (process.env.CODE_SERVER_COOKIE_SUFFIX) {
627+
args["cookie-suffix"] = process.env.CODE_SERVER_COOKIE_SUFFIX
628+
}
629+
619630
if (process.env.GITHUB_TOKEN) {
620631
args["github-auth"] = process.env.GITHUB_TOKEN
621632
}

src/node/http.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as http from "http"
44
import * as net from "net"
55
import qs from "qs"
66
import { Disposable } from "../common/emitter"
7-
import { CookieKeys, HttpCode, HttpError } from "../common/http"
7+
import { HttpCode, HttpError } from "../common/http"
88
import { normalize } from "../common/util"
99
import { AuthType, DefaultedArgs } from "./cli"
1010
import { version as codeServerVersion } from "./constants"
@@ -40,6 +40,7 @@ declare global {
4040
heart: Heart
4141
settings: SettingsProvider<CoderSettings>
4242
updater: UpdateProvider
43+
cookieSessionName: string
4344
}
4445
}
4546
}
@@ -124,7 +125,7 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {
124125
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
125126
const isCookieValidArgs: IsCookieValidArgs = {
126127
passwordMethod,
127-
cookieKey: sanitizeString(req.cookies[CookieKeys.Session]),
128+
cookieKey: sanitizeString(req.cookies[req.cookieSessionName]),
128129
passwordFromArgs: req.args.password || "",
129130
hashedPasswordFromArgs: req.args["hashed-password"],
130131
}

src/node/routes/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { promises as fs } from "fs"
55
import * as path from "path"
66
import * as tls from "tls"
77
import { Disposable } from "../../common/emitter"
8-
import { HttpCode, HttpError } from "../../common/http"
8+
import { getCookieSessionName, HttpCode, HttpError } from "../../common/http"
99
import { plural } from "../../common/util"
1010
import { App } from "../app"
1111
import { AuthType, DefaultedArgs } from "../cli"
@@ -61,6 +61,8 @@ export const register = async (
6161
const settings = new SettingsProvider<CoderSettings>(path.join(args["user-data-dir"], "coder.json"))
6262
const updater = new UpdateProvider("https://api.github.com/repos/coder/code-server/releases/latest", settings)
6363

64+
const cookieSessionName = getCookieSessionName(args["cookie-suffix"])
65+
6466
const common: express.RequestHandler = (req, _, next) => {
6567
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
6668
// it look like code-server is always in use.
@@ -75,6 +77,7 @@ export const register = async (
7577
req.heart = heart
7678
req.settings = settings
7779
req.updater = updater
80+
req.cookieSessionName = cookieSessionName
7881

7982
next()
8083
}

src/node/routes/login.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { Router, Request } from "express"
22
import { promises as fs } from "fs"
33
import { RateLimiter as Limiter } from "limiter"
44
import * as path from "path"
5-
import { CookieKeys } from "../../common/http"
65
import { rootPath } from "../constants"
76
import { authenticated, getCookieOptions, redirect, replaceTemplates } from "../http"
87
import i18n from "../i18n"
@@ -95,7 +94,7 @@ router.post<{}, string, { password?: string; base?: string } | undefined, { to?:
9594
if (isPasswordValid) {
9695
// The hash does not add any actual security but we do it for
9796
// obfuscation purposes (and as a side effect it handles escaping).
98-
res.cookie(CookieKeys.Session, hashedPassword, getCookieOptions(req))
97+
res.cookie(req.cookieSessionName, hashedPassword, getCookieOptions(req))
9998

10099
const to = (typeof req.query.to === "string" && req.query.to) || "/"
101100
return redirect(req, res, to, { to: undefined })

src/node/routes/logout.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { Router } from "express"
2-
import { CookieKeys } from "../../common/http"
32
import { getCookieOptions, redirect } from "../http"
43
import { sanitizeString } from "../util"
54

65
export const router = Router()
76

87
router.get<{}, undefined, undefined, { base?: string; to?: string }>("/", async (req, res) => {
98
// Must use the *identical* properties used to set the cookie.
10-
res.clearCookie(CookieKeys.Session, getCookieOptions(req))
9+
res.clearCookie(req.cookieSessionName, getCookieOptions(req))
1110

1211
const to = sanitizeString(req.query.to) || "/"
1312
return redirect(req, res, to, { to: undefined, base: undefined, href: undefined })

0 commit comments

Comments
 (0)