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 @@ ...@@ -6,7 +6,6 @@
#include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContext.h"
#include "core/frame/UseCounter.h" #include "core/frame/UseCounter.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/ConsoleTypes.h" #include "core/inspector/ConsoleTypes.h"
namespace blink { namespace blink {
...@@ -37,9 +36,20 @@ void SubresourceIntegrityHelper::DoReport( ...@@ -37,9 +36,20 @@ void SubresourceIntegrityHelper::DoReport(
for (auto feature : report_info.UseCounts()) { for (auto feature : report_info.UseCounts()) {
UseCounter::Count(&execution_context, GetWebFeature(feature)); 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()) { for (const auto& message : report_info.ConsoleErrorMessages()) {
execution_context.AddConsoleMessage(ConsoleMessage::Create( messages->push_back(ConsoleMessage::Create(kSecurityMessageSource,
kSecurityMessageSource, kErrorMessageLevel, message)); kErrorMessageLevel, message));
} }
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define SubresourceIntegrityHelper_h #define SubresourceIntegrityHelper_h
#include "core/CoreExport.h" #include "core/CoreExport.h"
#include "core/inspector/ConsoleMessage.h"
#include "platform/loader/SubresourceIntegrity.h" #include "platform/loader/SubresourceIntegrity.h"
#include "platform/wtf/Allocator.h" #include "platform/wtf/Allocator.h"
...@@ -19,6 +20,9 @@ class CORE_EXPORT SubresourceIntegrityHelper final { ...@@ -19,6 +20,9 @@ class CORE_EXPORT SubresourceIntegrityHelper final {
public: public:
static void DoReport(ExecutionContext&, static void DoReport(ExecutionContext&,
const SubresourceIntegrity::ReportInfo&); const SubresourceIntegrity::ReportInfo&);
static void GetConsoleMessages(const SubresourceIntegrity::ReportInfo&,
HeapVector<Member<ConsoleMessage>>*);
}; };
} // namespace blink } // namespace blink
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContext.h"
#include "core/inspector/ConsoleMessage.h" #include "core/inspector/ConsoleMessage.h"
#include "core/loader/SubresourceIntegrityHelper.h"
#include "platform/loader/fetch/FetchUtils.h" #include "platform/loader/fetch/FetchUtils.h"
#include "platform/network/mime/MIMETypeRegistry.h" #include "platform/network/mime/MIMETypeRegistry.h"
...@@ -21,8 +22,15 @@ bool WasModuleLoadSuccessful( ...@@ -21,8 +22,15 @@ bool WasModuleLoadSuccessful(
DCHECK(error_messages); DCHECK(error_messages);
if (resource) {
SubresourceIntegrityHelper::GetConsoleMessages(
resource->IntegrityReportInfo(), error_messages);
}
// - response's type is "error" // - response's type is "error"
if (!resource || resource->ErrorOccurred()) { if (!resource || resource->ErrorOccurred() ||
resource->IntegrityDisposition() !=
ResourceIntegrityDisposition::kPassed) {
return false; return false;
} }
......
...@@ -100,10 +100,6 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request, ...@@ -100,10 +100,6 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
// [SMSR] // [SMSR]
// https://html.spec.whatwg.org/multipage/webappapis.html#set-up-the-module-script-request // 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, ..." // [SMSR] "... its parser metadata to options's parser metadata, ..."
// [spec text] // [spec text]
options.parser_disposition = options_.ParserState(); options.parser_disposition = options_.ParserState();
...@@ -122,6 +118,12 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request, ...@@ -122,6 +118,12 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
// Note: |options| should not be modified after here. // Note: |options| should not be modified after here.
FetchParameters fetch_params(resource_request, options); 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 // [SMSR] "Set request's cryptographic nonce metadata to options's
// cryptographic nonce, ..." [spec text] // cryptographic nonce, ..." [spec text]
fetch_params.SetContentSecurityPolicyNonce(options_.Nonce()); fetch_params.SetContentSecurityPolicyNonce(options_.Nonce());
......
...@@ -344,16 +344,26 @@ void ModuleTreeLinker::FetchDescendants(ModuleScript* module_script) { ...@@ -344,16 +344,26 @@ void ModuleTreeLinker::FetchDescendants(ModuleScript* module_script) {
return; 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. // procedure should be performed in parallel to each other.
for (size_t i = 0; i < urls.size(); ++i) { 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. ... // procedure given ... with the top-level module fetch flag unset. ...
ModuleScriptFetchRequest request(urls[i], module_script->FetchOptions(), ModuleScriptFetchRequest request(
module_script->BaseURL().GetString(), urls[i], options, module_script->BaseURL().GetString(), positions[i]);
positions[i]);
InitiateInternalModuleScriptGraphFetching( InitiateInternalModuleScriptGraphFetching(
request, ModuleGraphLevel::kDependentModuleFetch); 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