Skip to content

Commit 3b50bfc

Browse files
committed
fix: sanitize password and cookie key
1 parent deaa224 commit 3b50bfc

File tree

6 files changed

+30
-6
lines changed

6 files changed

+30
-6
lines changed

ci/build/build-standalone-release.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ set -euo pipefail
33

44
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
55
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
6-
npm_config_build_from_source=true
6+
export npm_config_build_from_source=true
77

88
main() {
99
cd "$(dirname "${0}")/../.."

ci/build/npm-postinstall.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ detect_arch() {
2020
ARCH="${NPM_CONFIG_ARCH:-$(detect_arch)}"
2121
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
2222
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
23-
npm_config_build_from_source=true
23+
export npm_config_build_from_source=true
2424

2525
main() {
2626
# Grabs the major version of node from $npm_config_user_agent which looks like

src/node/http.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { normalize, Options } from "../common/util"
77
import { AuthType, DefaultedArgs } from "./cli"
88
import { commit, rootPath } from "./constants"
99
import { Heart } from "./heart"
10-
import { getPasswordMethod, IsCookieValidArgs, isCookieValid } from "./util"
10+
import { getPasswordMethod, IsCookieValidArgs, isCookieValid, sanitizeString } from "./util"
1111

1212
declare global {
1313
// eslint-disable-next-line @typescript-eslint/no-namespace
@@ -72,7 +72,7 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {
7272
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
7373
const isCookieValidArgs: IsCookieValidArgs = {
7474
passwordMethod,
75-
cookieKey: req.cookies.key as string,
75+
cookieKey: sanitizeString(req.cookies.key),
7676
passwordFromArgs: req.args.password || "",
7777
hashedPasswordFromArgs: req.args["hashed-password"],
7878
}

src/node/routes/login.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { RateLimiter as Limiter } from "limiter"
44
import * as path from "path"
55
import { rootPath } from "../constants"
66
import { authenticated, getCookieDomain, redirect, replaceTemplates } from "../http"
7-
import { getPasswordMethod, handlePasswordValidation, humanPath } from "../util"
7+
import { getPasswordMethod, handlePasswordValidation, humanPath, sanitizeString } from "../util"
88

99
export enum Cookie {
1010
Key = "key",
@@ -61,7 +61,7 @@ router.get("/", async (req, res) => {
6161
})
6262

6363
router.post("/", async (req, res) => {
64-
const password = req.body.password
64+
const password = sanitizeString(req.body.password)
6565
const hashedPasswordFromArgs = req.args["hashed-password"]
6666

6767
try {

src/node/util.ts

+11
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,17 @@ export async function isCookieValid(isCookieValidArgs: IsCookieValidArgs): Promi
274274
return isValid
275275
}
276276

277+
/** Ensures that the input is sanitized by checking
278+
* - it's a string
279+
* - greater than 0 characters
280+
* - trims whitespace
281+
*/
282+
export function sanitizeString(str: string): string {
283+
// Very basic sanitization of string
284+
// Credit: https://stackoverflow.com/a/46719000/3015595
285+
return typeof str === "string" && str.trim().length > 0 ? str.trim() : ""
286+
}
287+
277288
const mimeTypes: { [key: string]: string } = {
278289
".aac": "audio/x-aac",
279290
".avi": "video/x-msvideo",

test/unit/node/util.test.ts

+13
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
hashLegacy,
88
isHashLegacyMatch,
99
isCookieValid,
10+
sanitizeString,
1011
} from "../../../src/node/util"
1112

1213
describe("getEnvPaths", () => {
@@ -382,3 +383,15 @@ describe.only("isCookieValid", () => {
382383
expect(isValid).toBe(false)
383384
})
384385
})
386+
387+
describe.only("sanitizeString", () => {
388+
it("should return an empty string if passed a type other than a string", () => {
389+
expect(sanitizeString({} as string)).toBe("")
390+
})
391+
it("should trim whitespace", () => {
392+
expect(sanitizeString(" hello ")).toBe("hello")
393+
})
394+
it("should always return an empty string", () => {
395+
expect(sanitizeString(" ")).toBe("")
396+
})
397+
})

0 commit comments

Comments
 (0)