url-cheatsheet
url-cheatsheet copied to clipboard
URL manipulation cheatsheet for JavaScript
url-cheatsheet
URL manipulation cheatsheet for JavaScript.
DO NOT: concat url and user input without escape
Please DO NOT concat url and user input without escape
// DO NOT
const name = "<user input>";
const url = `https://example.com/user/${name}`;
console.log(url); // => "https://example.com/user/<user input>"
This code may have directory traversal vulnerability.
You should escape the name by encodeURIComponent.
// DO
const name = "<user input>";
const url = `https://example.com/user/${encodeURIComponent(name)}`;
console.log(url); // => "https://example.com/user/%3Cuser%20input%3E"
Addtionaly, You should reject . and .. as a name.
Because encodeURIComponent("..") is .., it may have directory traversal vulnerability.
// DO
const name = "<user input>";
if (name === ".." || name === ".") {
throw new Error("Invalid name");
}
const url = `https://example.com/user/${encodeURIComponent(name)}`;
console.log(url); // => "https://example.com/user/%3Cuser%20input%3E"
- https://url.spec.whatwg.org/#example-url-parsing
- Path Traversal | OWASP Foundation
- Path Traversal and SSRF - Security, Tech, And Ramblings
DO NOT: concat parameter and user input without escape
Please DO NOT concat parameter and user input without escape
// DO NOT
const query = "<user input>";
const url = `https://example.com?q=${query}`;
console.log(url); // => "https://example.com?q=<user input>"
This example does not consider that query includes & or ? that is required to escape.
You should escape the query by encodeURIComponent.
// DO
const query = "<user input>";
const url = `https://example.com?q=${encodeURIComponent(query)}`;
console.log(url); // => "https://example.com?q=%3Cuser%20input%3E"
Or, You can use URLSearchParams() that escape each parameters automatically.
Base URL + Path
- keywords: url-join, join path
const base = "https://example.com";
const pathname = "/path/to/page";
const result = new URL(pathname, base);
console.log(result.toString()); // => "https://example.com/path/to/page"
If the pathname include user input, you should escape it by encodeURIComponent.
const base = "https://example.com/";
const name = "<user input>";
const result = new URL(`/user/${encodeURIComponent(name)}`, base);
console.log(result.toString()); // => "https://example.com/user/%3Cuser%20input%3E"
Addtionaly, You should reject . and .. as a name.
Because encodeURIComponent("..") is .., it may have directory traversal vulnerability.
// DO
const base = "https://example.com/";
const name = "<user input>";
if (name === ".." || name === ".") {
throw new Error("Invalid name");
}
const result = new URL(`/user/${encodeURIComponent(name)}`, base);
console.log(result.toString()); // => "https://example.com/user/%3Cuser%20input%3E"
- https://url.spec.whatwg.org/#example-url-parsing
- Path Traversal | OWASP Foundation
- Path Traversal and SSRF - Security, Tech, And Ramblings
Get parameter from URL
Use URL and URLSearchParams#get
const inputURL = "https://example.com/?q=query&page=1";
const url = new URL(inputURL);
const q = url.searchParams.get("q");
console.log(q); // => "query"
Get multiple parameters as array from URL
Use URL and URLSearchParams#getAll
const inputURL = "https://example.com/?q=query&lang=en_US&lang=ja_JP";
const url = new URL(inputURL);
const langs = url.searchParams.getAll("lang");
console.log(langs); // ["en_US", "ja_JP"]
Add parameters to URL
Use URLSearchParams
const q = "query";
const page = 1;
const base = "https://example.com";
const url = new URL(base);
const params = new URLSearchParams({
q,
page,
});
console.log(url + "?" + params); // => "https://example.com/?q=query&page=1"
or
const q = "query";
const page = 1;
const base = "https://example.com";
const url = new URL(base);
url.search = new URLSearchParams({
q,
page,
});
console.log(url.toString()); // => "https://example.com/?q=query&page=1"
:memo: URLSearchParams escape each parameter automtically.
const q = "<user input>";
const page = 1;
const base = "https://example.com";
const url = new URL(base);
url.search = new URLSearchParams({
q,
page,
});
console.log(url.toString()); // => "https://example.com/?q=%3Cuser+input%3E&page=1"
Update parameter of URL
Use URL's searchParams property.
const inputURL = "https://example.com/?q=query&page=1";
const url = new URL(inputURL);
url.searchParams.set("q", "update");
console.log(url.toString()); // => "https://example.com/?q=update&page=1"
Remove parameter from URL
Use URL and URLSearchParams
const inputURL = "https://example.com/?q=query&page=1";
const url = new URL(inputURL);
url.searchParams.delete("q");
console.log(url.toString()); // => "https://example.com/?page=1"
Filter parameters
Allow only a and d parameters.
- keywords: pick, white list, allow list
const base = "https://example.com/?a=1&b=2&c=3&d=4";
const url = new URL(base);
const allowedParameterNames = ["a", "d"];
url.search = new URLSearchParams(
Array.from(url.searchParams).filter(([key, value]) => {
return allowedParameterNames.includes(key);
})
);
console.log(url.toString()); // => "https://example.com/?a=1&d=4"
Check URL is Absolute-URL
new URL(urlString) throw an error when parsing relative url string.
As a result, you can use URL for checking URL is absolute-URL that starts with a schema like https:
const isValidURL = (urlString) => {
try {
new URL(urlString); // if `urlString` is invalid, throw an erorr
return true;
} catch {
return false;
}
};
console.log(isValidURL("https://example.com")); // => true
console.log(isValidURL("https/example.com")); // => false
Check URL is HTTP
Check URL's protocol property.
const isHttpURL = (urlString) => {
try {
const url = new URL(urlString); // if `urlString` is invalid, throw an erorr
return url.protocol === "http:" || url.protocol === "https:";
} catch {
return false;
}
};
console.log(isHttpURL("http://example.com")); // => true
console.log(isHttpURL("https://example.com")); // => true
console.log(isHttpURL("ftp://example.com")); // => false
console.log(isHttpURL("https/example.com")); // => false