Add origin checks to web sockets (#6048)
* Move splitOnFirstEquals to util I will be making use of this to parse the forwarded header. * Type splitOnFirstEquals with two items Also add some test cases. * Check origin header on web sockets * Update changelog with origin check * Fix web sockets not closing with error code
This commit is contained in:
@ -1,55 +1,118 @@
|
||||
import { getMockReq } from "@jest-mock/express"
|
||||
import { constructRedirectPath, relativeRoot } from "../../../src/node/http"
|
||||
import * as http from "../../../src/node/http"
|
||||
import { mockLogger } from "../../utils/helpers"
|
||||
|
||||
describe("http", () => {
|
||||
it("should construct a relative path to the root", () => {
|
||||
expect(relativeRoot("/")).toStrictEqual(".")
|
||||
expect(relativeRoot("/foo")).toStrictEqual(".")
|
||||
expect(relativeRoot("/foo/")).toStrictEqual("./..")
|
||||
expect(relativeRoot("/foo/bar ")).toStrictEqual("./..")
|
||||
expect(relativeRoot("/foo/bar/")).toStrictEqual("./../..")
|
||||
beforeEach(() => {
|
||||
mockLogger()
|
||||
})
|
||||
})
|
||||
|
||||
describe("constructRedirectPath", () => {
|
||||
it("should preserve slashes in queryString so they are human-readable", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
})
|
||||
const mockQueryParams = { folder: "/Users/jp/dev/coder" }
|
||||
const mockTo = ""
|
||||
const actual = constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./?folder=/Users/jp/dev/coder"
|
||||
expect(actual).toBe(expected)
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
it("should use an empty string if no query params", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
})
|
||||
const mockQueryParams = {}
|
||||
const mockTo = ""
|
||||
const actual = constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./"
|
||||
expect(actual).toBe(expected)
|
||||
|
||||
it("should construct a relative path to the root", () => {
|
||||
expect(http.relativeRoot("/")).toStrictEqual(".")
|
||||
expect(http.relativeRoot("/foo")).toStrictEqual(".")
|
||||
expect(http.relativeRoot("/foo/")).toStrictEqual("./..")
|
||||
expect(http.relativeRoot("/foo/bar ")).toStrictEqual("./..")
|
||||
expect(http.relativeRoot("/foo/bar/")).toStrictEqual("./../..")
|
||||
})
|
||||
it("should append the 'to' path relative to the originalUrl", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
|
||||
describe("origin", () => {
|
||||
;[
|
||||
{
|
||||
origin: "",
|
||||
host: "",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
origin: "http://localhost:8080",
|
||||
host: "",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
origin: "http://localhost:8080",
|
||||
host: "localhost:8080",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
origin: "http://localhost:8080",
|
||||
host: "localhost:8081",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
origin: "localhost:8080",
|
||||
host: "localhost:8080",
|
||||
expected: false, // Gets parsed as host: localhost and path: 8080.
|
||||
},
|
||||
{
|
||||
origin: "test.org",
|
||||
host: "localhost:8080",
|
||||
expected: false, // Parsing fails completely.
|
||||
},
|
||||
].forEach((test) => {
|
||||
;[
|
||||
["host", test.host],
|
||||
["x-forwarded-host", test.host],
|
||||
["forwarded", `for=127.0.0.1, host=${test.host}, proto=http`],
|
||||
["forwarded", `for=127.0.0.1;proto=http;host=${test.host}`],
|
||||
["forwarded", `proto=http;host=${test.host}, for=127.0.0.1`],
|
||||
].forEach(([key, value]) => {
|
||||
it(`${test.origin} -> [${key}: ${value}]`, () => {
|
||||
const req = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
headers: {
|
||||
origin: test.origin,
|
||||
[key]: value,
|
||||
},
|
||||
})
|
||||
expect(http.authenticateOrigin(req)).toBe(test.expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
const mockQueryParams = {}
|
||||
const mockTo = "vscode"
|
||||
const actual = constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./vscode"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
it("should append append queryParams after 'to' path", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
|
||||
describe("constructRedirectPath", () => {
|
||||
it("should preserve slashes in queryString so they are human-readable", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
})
|
||||
const mockQueryParams = { folder: "/Users/jp/dev/coder" }
|
||||
const mockTo = ""
|
||||
const actual = http.constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./?folder=/Users/jp/dev/coder"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
it("should use an empty string if no query params", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
})
|
||||
const mockQueryParams = {}
|
||||
const mockTo = ""
|
||||
const actual = http.constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
it("should append the 'to' path relative to the originalUrl", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
})
|
||||
const mockQueryParams = {}
|
||||
const mockTo = "vscode"
|
||||
const actual = http.constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./vscode"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
it("should append append queryParams after 'to' path", () => {
|
||||
const mockReq = getMockReq({
|
||||
originalUrl: "localhost:8080",
|
||||
})
|
||||
const mockQueryParams = { folder: "/Users/jp/dev/coder" }
|
||||
const mockTo = "vscode"
|
||||
const actual = http.constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./vscode?folder=/Users/jp/dev/coder"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
const mockQueryParams = { folder: "/Users/jp/dev/coder" }
|
||||
const mockTo = "vscode"
|
||||
const actual = constructRedirectPath(mockReq, mockQueryParams, mockTo)
|
||||
const expected = "./vscode?folder=/Users/jp/dev/coder"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user