mirror of
https://github.com/bitwarden/browser
synced 2025-12-12 14:23:32 +00:00
[CSA-28] Use path normalization in API requests (#4580)
* Use path normalization in API requests * Remove CLI webpack config change that's unneeded * Add additional tests
This commit is contained in:
@@ -209,7 +209,7 @@ const mainConfig = {
|
|||||||
util: require.resolve("util/"),
|
util: require.resolve("util/"),
|
||||||
url: require.resolve("url/"),
|
url: require.resolve("url/"),
|
||||||
fs: false,
|
fs: false,
|
||||||
path: false,
|
path: require.resolve("path-browserify"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
|||||||
@@ -355,9 +355,9 @@ const webpackConfig = {
|
|||||||
util: require.resolve("util/"),
|
util: require.resolve("util/"),
|
||||||
assert: false,
|
assert: false,
|
||||||
url: false,
|
url: false,
|
||||||
path: false,
|
|
||||||
fs: false,
|
fs: false,
|
||||||
process: false,
|
process: false,
|
||||||
|
path: require.resolve("path-browserify"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
|||||||
@@ -326,4 +326,24 @@ describe("Utils Service", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("normalizePath", () => {
|
||||||
|
it("removes a single traversal", () => {
|
||||||
|
expect(Utils.normalizePath("../test")).toBe("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes deep traversals", () => {
|
||||||
|
expect(Utils.normalizePath("../../test")).toBe("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes intermediate traversals", () => {
|
||||||
|
expect(Utils.normalizePath("test/../test")).toBe("test");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes multiple encoded traversals", () => {
|
||||||
|
expect(
|
||||||
|
Utils.normalizePath("api/sends/access/..%2f..%2f..%2fapi%2fsends%2faccess%2fsendkey")
|
||||||
|
).toBe("api/sends/access/sendkey");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
/* eslint-disable no-useless-escape */
|
/* eslint-disable no-useless-escape */
|
||||||
|
import * as path from "path";
|
||||||
|
|
||||||
import { getHostname, parse } from "tldts";
|
import { getHostname, parse } from "tldts";
|
||||||
import { Merge } from "type-fest";
|
import { Merge } from "type-fest";
|
||||||
|
|
||||||
@@ -498,6 +500,15 @@ export class Utils {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes a path for defense against attacks like traversals
|
||||||
|
* @param denormalizedPath
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static normalizePath(denormalizedPath: string): string {
|
||||||
|
return path.normalize(decodeURIComponent(denormalizedPath)).replace(/^(\.\.(\/|\\|$))+/, "");
|
||||||
|
}
|
||||||
|
|
||||||
private static isMobile(win: Window) {
|
private static isMobile(win: Window) {
|
||||||
let mobile = false;
|
let mobile = false;
|
||||||
((a) => {
|
((a) => {
|
||||||
|
|||||||
@@ -1962,11 +1962,8 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
apiUrl = Utils.isNullOrWhitespace(apiUrl) ? this.environmentService.getApiUrl() : apiUrl;
|
apiUrl = Utils.isNullOrWhitespace(apiUrl) ? this.environmentService.getApiUrl() : apiUrl;
|
||||||
|
|
||||||
const requestUrl = apiUrl + path;
|
|
||||||
// Prevent directory traversal from malicious paths
|
// Prevent directory traversal from malicious paths
|
||||||
if (new URL(requestUrl).href !== requestUrl) {
|
const requestUrl = apiUrl + Utils.normalizePath(path);
|
||||||
return Promise.reject("Invalid request url path.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const headers = new Headers({
|
const headers = new Headers({
|
||||||
"Device-Type": this.deviceType,
|
"Device-Type": this.deviceType,
|
||||||
|
|||||||
Reference in New Issue
Block a user