LibWeb: Restrict weird about:foo URIs

This commit:
- Prevents path traversal via the about: scheme
- Prevents loading about:inspector
- Requires about: URIs to be opaque paths
- Prevents crashes with invalid percent encoded paths
This commit is contained in:
Gingeh 2025-03-12 13:28:07 +11:00 committed by Sam Atkins
commit 5838c73a72
Notes: github-actions[bot] 2025-03-12 10:42:15 +00:00
5 changed files with 42 additions and 9 deletions

View file

@ -272,18 +272,25 @@ void ResourceLoader::load(LoadRequest& request, GC::Root<SuccessCallback> succes
// FIXME: Implement timing info for about requests. // FIXME: Implement timing info for about requests.
Requests::RequestTimingInfo fixme_implement_timing_info {}; Requests::RequestTimingInfo fixme_implement_timing_info {};
auto serialized_path = URL::percent_decode(url.serialize_path());
// About version page // About version page
if (url.path_segment_at_index(0) == "version") { if (serialized_path == "version") {
success_callback->function()(MUST(load_about_version_page()).bytes(), fixme_implement_timing_info, response_headers, {}, {}); success_callback->function()(MUST(load_about_version_page()).bytes(), fixme_implement_timing_info, response_headers, {}, {});
return; return;
} }
// Other about static HTML pages // Other about static HTML pages
auto resource = Core::Resource::load_from_uri(MUST(String::formatted("resource://ladybird/{}.html", url.path_segment_at_index(0)))); auto target_file = ByteString::formatted("{}.html", serialized_path);
if (!resource.is_error()) {
auto data = resource.value()->data(); auto about_directory = MUST(Core::Resource::load_from_uri("resource://ladybird/about-pages"_string));
success_callback->function()(data, fixme_implement_timing_info, response_headers, {}, {}); if (about_directory->children().contains_slow(target_file.view())) {
return; auto resource = Core::Resource::load_from_uri(ByteString::formatted("resource://ladybird/about-pages/{}", target_file));
if (!resource.is_error()) {
auto data = resource.value()->data();
success_callback->function()(data, fixme_implement_timing_info, response_headers, {}, {});
return;
}
} }
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(m_heap, [success_callback, response_headers = move(response_headers), fixme_implement_timing_info = move(fixme_implement_timing_info)] { Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(m_heap, [success_callback, response_headers = move(response_headers), fixme_implement_timing_info = move(fixme_implement_timing_info)] {

View file

@ -154,6 +154,7 @@ executable("ladybird_executable") {
deps += [ "//Userland/Libraries/LibThreading" ] deps += [ "//Userland/Libraries/LibThreading" ]
} else { } else {
data_deps += [ data_deps += [
":ladybird_copy_about_pages",
":ladybird_copy_cacert", ":ladybird_copy_cacert",
":ladybird_copy_config_resources", ":ladybird_copy_config_resources",
":ladybird_copy_fonts", ":ladybird_copy_fonts",
@ -265,11 +266,14 @@ themes = [
] ]
web_resources = [ web_resources = [
"//Base/res/ladybird/about.html",
"//Base/res/ladybird/inspector.css", "//Base/res/ladybird/inspector.css",
"//Base/res/ladybird/inspector.html", "//Base/res/ladybird/inspector.html",
"//Base/res/ladybird/inspector.js", "//Base/res/ladybird/inspector.js",
"//Base/res/ladybird/newtab.html", ]
about_pages = [
"//Base/res/ladybird/about-pages/about.html",
"//Base/res/ladybird/about-pages/newtab.html",
] ]
web_templates = [ web_templates = [
@ -327,6 +331,13 @@ if (current_os != "mac") {
outputs = [ "$root_out_dir/share/Lagom/ladybird/{{source_file_part}}" ] outputs = [ "$root_out_dir/share/Lagom/ladybird/{{source_file_part}}" ]
} }
copy("ladybird_copy_about_pages") {
sources = about_pages
outputs = [
"$root_out_dir/share/Lagom/ladybird/about-pages/{{source_file_part}}",
]
}
copy("ladybird_copy_web_templates") { copy("ladybird_copy_web_templates") {
sources = web_templates sources = web_templates
outputs = outputs =
@ -477,6 +488,12 @@ if (current_os != "mac") {
outputs = [ "{{bundle_resources_dir}}/ladybird/{{source_file_part}}" ] outputs = [ "{{bundle_resources_dir}}/ladybird/{{source_file_part}}" ]
} }
bundle_data("ladybird_about_pages") {
sources = about_pages
outputs =
[ "{{bundle_resources_dir}}/ladybird/about-pages/{{source_file_part}}" ]
}
bundle_data("ladybird_web_templates") { bundle_data("ladybird_web_templates") {
sources = web_templates sources = web_templates
outputs = outputs =
@ -537,6 +554,7 @@ if (current_os != "mac") {
bundle_executable_dir = "$bundle_contents_dir/MacOS" bundle_executable_dir = "$bundle_contents_dir/MacOS"
deps = [ deps = [
":ladybird_about_pages",
":ladybird_bundle_executables", ":ladybird_bundle_executables",
":ladybird_bundle_info_plist", ":ladybird_bundle_info_plist",
":ladybird_bundle_libs", ":ladybird_bundle_libs",

View file

@ -63,10 +63,12 @@ list(TRANSFORM 128x128_ICONS PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/icons/128x
list(TRANSFORM BROWSER_ICONS PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/icons/browser/") list(TRANSFORM BROWSER_ICONS PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/icons/browser/")
set(WEB_RESOURCES set(WEB_RESOURCES
about.html
inspector.css inspector.css
inspector.html inspector.html
inspector.js inspector.js
)
set(ABOUT_PAGES
about.html
newtab.html newtab.html
) )
set(WEB_TEMPLATES set(WEB_TEMPLATES
@ -75,6 +77,7 @@ set(WEB_TEMPLATES
version.html version.html
) )
list(TRANSFORM WEB_RESOURCES PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/ladybird/") list(TRANSFORM WEB_RESOURCES PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/ladybird/")
list(TRANSFORM ABOUT_PAGES PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/ladybird/about-pages/")
list(TRANSFORM WEB_TEMPLATES PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/ladybird/templates/") list(TRANSFORM WEB_TEMPLATES PREPEND "${LADYBIRD_SOURCE_DIR}/Base/res/ladybird/templates/")
set(THEMES set(THEMES
@ -163,6 +166,10 @@ function(copy_resources_to_build base_directory bundle_target)
DESTINATION ${base_directory} TARGET ${bundle_target} DESTINATION ${base_directory} TARGET ${bundle_target}
) )
copy_resource_set(ladybird/about-pages RESOURCES ${ABOUT_PAGES}
DESTINATION ${base_directory} TARGET ${bundle_target}
)
copy_resource_set(ladybird/templates RESOURCES ${WEB_TEMPLATES} copy_resource_set(ladybird/templates RESOURCES ${WEB_TEMPLATES}
DESTINATION ${base_directory} TARGET ${bundle_target} DESTINATION ${base_directory} TARGET ${bundle_target}
) )
@ -186,6 +193,7 @@ function(install_ladybird_resources destination component)
install(FILES ${BROWSER_ICONS} DESTINATION "${destination}/icons/browser" COMPONENT ${component}) install(FILES ${BROWSER_ICONS} DESTINATION "${destination}/icons/browser" COMPONENT ${component})
install(FILES ${THEMES} DESTINATION "${destination}/themes" COMPONENT ${component}) install(FILES ${THEMES} DESTINATION "${destination}/themes" COMPONENT ${component})
install(FILES ${WEB_RESOURCES} DESTINATION "${destination}/ladybird" COMPONENT ${component}) install(FILES ${WEB_RESOURCES} DESTINATION "${destination}/ladybird" COMPONENT ${component})
install(FILES ${ABOUT_PAGES} DESTINATION "${destination}/ladybird/about-pages" COMPONENT ${component})
install(FILES ${WEB_TEMPLATES} DESTINATION "${destination}/ladybird/templates" COMPONENT ${component}) install(FILES ${WEB_TEMPLATES} DESTINATION "${destination}/ladybird/templates" COMPONENT ${component})
install(FILES ${CONFIG_RESOURCES} DESTINATION "${destination}/ladybird/default-config" COMPONENT ${component}) install(FILES ${CONFIG_RESOURCES} DESTINATION "${destination}/ladybird/default-config" COMPONENT ${component})
install(FILES ${DOWNLOADED_RESOURCES} DESTINATION "${destination}/ladybird" COMPONENT ${component}) install(FILES ${DOWNLOADED_RESOURCES} DESTINATION "${destination}/ladybird" COMPONENT ${component})