mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 22:03:36 +00:00
[PM-27103] Add URL Check to Send (#17056)
* add dangerousPatters check to api service
This commit is contained in:
@@ -689,6 +689,32 @@ describe("Utils Service", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("invalidUrlPatterns", () => {
|
||||||
|
it("should return false if no invalid patterns are found", () => {
|
||||||
|
const urlString = "https://www.example.com/api/my/account/status";
|
||||||
|
|
||||||
|
const actual = Utils.invalidUrlPatterns(urlString);
|
||||||
|
|
||||||
|
expect(actual).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true if an invalid pattern is found", () => {
|
||||||
|
const urlString = "https://www.example.com/api/%2e%2e/secret";
|
||||||
|
|
||||||
|
const actual = Utils.invalidUrlPatterns(urlString);
|
||||||
|
|
||||||
|
expect(actual).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true if an invalid pattern is found in a param", () => {
|
||||||
|
const urlString = "https://www.example.com/api/history?someToken=../secret";
|
||||||
|
|
||||||
|
const actual = Utils.invalidUrlPatterns(urlString);
|
||||||
|
|
||||||
|
expect(actual).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("getUrl", () => {
|
describe("getUrl", () => {
|
||||||
it("assumes a http protocol if no protocol is specified", () => {
|
it("assumes a http protocol if no protocol is specified", () => {
|
||||||
const urlString = "www.exampleapp.com.au:4000";
|
const urlString = "www.exampleapp.com.au:4000";
|
||||||
|
|||||||
@@ -612,6 +612,55 @@ export class Utils {
|
|||||||
return path.normalize(decodeURIComponent(denormalizedPath)).replace(/^(\.\.(\/|\\|$))+/, "");
|
return path.normalize(decodeURIComponent(denormalizedPath)).replace(/^(\.\.(\/|\\|$))+/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an url checking against invalid patterns
|
||||||
|
* @param url
|
||||||
|
* @returns true if invalid patterns found, false if safe
|
||||||
|
*/
|
||||||
|
static invalidUrlPatterns(url: string): boolean {
|
||||||
|
const invalidUrlPatterns = ["..", "%2e", "\\", "%5c"];
|
||||||
|
|
||||||
|
const decodedUrl = decodeURIComponent(url.toLocaleLowerCase());
|
||||||
|
|
||||||
|
// Check URL for invalidUrl patterns across entire URL
|
||||||
|
if (invalidUrlPatterns.some((p) => decodedUrl.includes(p))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for additional invalid patterns inside URL params
|
||||||
|
if (decodedUrl.includes("?")) {
|
||||||
|
const hasInvalidParams = this.validateQueryParameters(decodedUrl);
|
||||||
|
if (hasInvalidParams) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates query parameters for additional invalid patterns
|
||||||
|
* @param url - The URL containing query parameters
|
||||||
|
* @returns true if invalid patterns found, false if safe
|
||||||
|
*/
|
||||||
|
private static validateQueryParameters(url: string): boolean {
|
||||||
|
try {
|
||||||
|
let queryString: string;
|
||||||
|
|
||||||
|
if (url.includes("?")) {
|
||||||
|
queryString = url.split("?")[1];
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramInvalidPatterns = ["/", "%2f", "#", "%23"];
|
||||||
|
|
||||||
|
return paramInvalidPatterns.some((p) => queryString.includes(p));
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Error validating query parameters: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static isMobile(win: Window) {
|
private static isMobile(win: Window) {
|
||||||
let mobile = false;
|
let mobile = false;
|
||||||
((a) => {
|
((a) => {
|
||||||
|
|||||||
@@ -1588,8 +1588,16 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
);
|
);
|
||||||
apiUrl = Utils.isNullOrWhitespace(apiUrl) ? env.getApiUrl() : apiUrl;
|
apiUrl = Utils.isNullOrWhitespace(apiUrl) ? env.getApiUrl() : apiUrl;
|
||||||
|
|
||||||
// Prevent directory traversal from malicious paths
|
|
||||||
const pathParts = path.split("?");
|
const pathParts = path.split("?");
|
||||||
|
// Check for path traversal patterns from any URL.
|
||||||
|
const fullUrlPath = apiUrl + pathParts[0] + (pathParts.length > 1 ? `?${pathParts[1]}` : "");
|
||||||
|
|
||||||
|
const isInvalidUrl = Utils.invalidUrlPatterns(fullUrlPath);
|
||||||
|
if (isInvalidUrl) {
|
||||||
|
throw new Error("The request URL contains dangerous patterns.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent directory traversal from malicious paths
|
||||||
const requestUrl =
|
const requestUrl =
|
||||||
apiUrl + Utils.normalizePath(pathParts[0]) + (pathParts.length > 1 ? `?${pathParts[1]}` : "");
|
apiUrl + Utils.normalizePath(pathParts[0]) + (pathParts.length > 1 ? `?${pathParts[1]}` : "");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user