Commit 214d1683 authored by Hiroshige Hayashizaki's avatar Hiroshige Hayashizaki Committed by Commit Bot

Support integrity attribute for module scripts

This CL enables subresource integrity check for module scripts, by
- Clearing ScriptFetchOptions' integrity for descendant module
  scripts in ModuleTreeLinker.cpp, as specced,
- Setting FetchParameters' integrity according to ScriptFetchOptions
  in ModuleScriptLoader::Fetch(), and
- Checking the integrity check result in WasModuleLoadSuccessful()
  and reports console messages if any.
  For this, SubresourceIntegrityHelper::GetConsoleMessages() is
  introduced.

Bug: 771486, 772100
Change-Id: I3f01fd018dad625de9440fe4ab7e1d9ee7feb5ab
Reviewed-on: https://chromium-review.googlesource.com/738221
Commit-Queue: Hiroshige Hayashizaki <hiroshige@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512705}
parent c7cb3e90
This is a testharness.js-based test.
PASS The integrity attribute must have no affect on inline module scripts
PASS The integrity attribute must be verified on the top-level of a module and allow it to execute when it matches
FAIL The integrity attribute must be verified on the top-level of a module and not allow it to execute when there's a mismatch assert_array_equals: The module and its dependency must not have executed lengths differ, expected 0 got 2
Harness: the test ran to completion.
......@@ -6,7 +6,6 @@
#include "core/dom/ExecutionContext.h"
#include "core/frame/UseCounter.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/ConsoleTypes.h"
namespace blink {
......@@ -37,9 +36,20 @@ void SubresourceIntegrityHelper::DoReport(
for (auto feature : report_info.UseCounts()) {
UseCounter::Count(&execution_context, GetWebFeature(feature));
}
HeapVector<Member<ConsoleMessage>> messages;
GetConsoleMessages(report_info, &messages);
for (const auto& message : messages) {
execution_context.AddConsoleMessage(message);
}
}
void SubresourceIntegrityHelper::GetConsoleMessages(
const SubresourceIntegrity::ReportInfo& report_info,
HeapVector<Member<ConsoleMessage>>* messages) {
DCHECK(messages);
for (const auto& message : report_info.ConsoleErrorMessages()) {
execution_context.AddConsoleMessage(ConsoleMessage::Create(
kSecurityMessageSource, kErrorMessageLevel, message));
messages->push_back(ConsoleMessage::Create(kSecurityMessageSource,
kErrorMessageLevel, message));
}
}
......
......@@ -6,6 +6,7 @@
#define SubresourceIntegrityHelper_h
#include "core/CoreExport.h"
#include "core/inspector/ConsoleMessage.h"
#include "platform/loader/SubresourceIntegrity.h"
#include "platform/wtf/Allocator.h"
......@@ -19,6 +20,9 @@ class CORE_EXPORT SubresourceIntegrityHelper final {
public:
static void DoReport(ExecutionContext&,
const SubresourceIntegrity::ReportInfo&);
static void GetConsoleMessages(const SubresourceIntegrity::ReportInfo&,
HeapVector<Member<ConsoleMessage>>*);
};
} // namespace blink
......
......@@ -6,6 +6,7 @@
#include "core/dom/ExecutionContext.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/loader/SubresourceIntegrityHelper.h"
#include "platform/loader/fetch/FetchUtils.h"
#include "platform/network/mime/MIMETypeRegistry.h"
......@@ -21,8 +22,15 @@ bool WasModuleLoadSuccessful(
DCHECK(error_messages);
if (resource) {
SubresourceIntegrityHelper::GetConsoleMessages(
resource->IntegrityReportInfo(), error_messages);
}
// - response's type is "error"
if (!resource || resource->ErrorOccurred()) {
if (!resource || resource->ErrorOccurred() ||
resource->IntegrityDisposition() !=
ResourceIntegrityDisposition::kPassed) {
return false;
}
......
......@@ -100,10 +100,6 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
// [SMSR]
// https://html.spec.whatwg.org/multipage/webappapis.html#set-up-the-module-script-request
// [SMSR] "... its integrity metadata to options's integrity metadata, ..."
// [spec text]
// TODO(kouhei): Implement.
// [SMSR] "... its parser metadata to options's parser metadata, ..."
// [spec text]
options.parser_disposition = options_.ParserState();
......@@ -122,6 +118,12 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
// Note: |options| should not be modified after here.
FetchParameters fetch_params(resource_request, options);
// [SMSR] "... its integrity metadata to options's integrity metadata, ..."
// [spec text]
fetch_params.SetIntegrityMetadata(options_.GetIntegrityMetadata());
fetch_params.MutableResourceRequest().SetFetchIntegrity(
options_.GetIntegrityAttributeValue());
// [SMSR] "Set request's cryptographic nonce metadata to options's
// cryptographic nonce, ..." [spec text]
fetch_params.SetContentSecurityPolicyNonce(options_.Nonce());
......
......@@ -344,16 +344,26 @@ void ModuleTreeLinker::FetchDescendants(ModuleScript* module_script) {
return;
}
// [FD] Step 6. For each url in urls, ...
// [FD] Step 6. Let options be the descendant script fetch options for module
// script's fetch options.
// https://html.spec.whatwg.org/multipage/webappapis.html#descendant-script-fetch-options
// the descendant script fetch options are a new script fetch options whose
// items all have the same values, except for the integrity metadata, which is
// instead the empty string.
ScriptFetchOptions options(module_script->FetchOptions().Nonce(),
IntegrityMetadataSet(), String(),
module_script->FetchOptions().ParserState(),
module_script->FetchOptions().CredentialsMode());
// [FD] Step 7. For each url in urls, ...
//
// [FD] Step 6. These invocations of the internal module script graph fetching
// [FD] Step 7. These invocations of the internal module script graph fetching
// procedure should be performed in parallel to each other.
for (size_t i = 0; i < urls.size(); ++i) {
// [FD] Step 6. ... perform the internal module script graph fetching
// [FD] Step 7. ... perform the internal module script graph fetching
// procedure given ... with the top-level module fetch flag unset. ...
ModuleScriptFetchRequest request(urls[i], module_script->FetchOptions(),
module_script->BaseURL().GetString(),
positions[i]);
ModuleScriptFetchRequest request(
urls[i], options, module_script->BaseURL().GetString(), positions[i]);
InitiateInternalModuleScriptGraphFetching(
request, ModuleGraphLevel::kDependentModuleFetch);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment