blob: 0f9ca0afafe2399039c230b4395d346d6c78b7ee [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/frame_host/form_submission_throttle.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
namespace content {
FormSubmissionThrottle::FormSubmissionThrottle(NavigationHandle* handle)
: NavigationThrottle(handle) {}
// static
FormSubmissionThrottle::MaybeCreateThrottleFor(NavigationHandle* handle) {
if (!handle->IsFormSubmission())
return nullptr;
return std::unique_ptr<NavigationThrottle>(
new FormSubmissionThrottle(handle));
FormSubmissionThrottle::~FormSubmissionThrottle() {}
FormSubmissionThrottle::WillStartRequest() {
return CheckContentSecurityPolicyFormAction(false /* was_server_redirect */);
FormSubmissionThrottle::WillRedirectRequest() {
return CheckContentSecurityPolicyFormAction(true /* was_server_redirect */);
const char* FormSubmissionThrottle::GetNameForLogging() {
return "FormSubmissionThrottle";
bool was_server_redirect) {
// TODO(arthursonzogni): form-action is enforced on the wrong RenderFrameHost.
// The navigating one is used instead of the one that has initiated the form
// submission. The renderer side checks are still in place and are used for
// the moment instead. For redirects, the behavior was already broken before
// using the browser side checks.
// See and
// In absence of redirects, the target URL is sufficiently verified against
// the form-action CSP by the frame that hosts the form element + initiates
// form submission + declares the form-action CSP (i.e. the same frame does
// all those 4 things). Because in this scenario there are no frame or
// renderer boundaries crossed, we don't have to worry about one (potentially
// compromised) renderer being responsible for enforcing the CSP of another
// (victim) renderer. Therefore it is okay to return early and do no further
// browser-side checks.
if (!was_server_redirect)
return NavigationThrottle::PROCEED;
NavigationHandleImpl* handle =
if (handle->should_check_main_world_csp() == CSPDisposition::DO_NOT_CHECK)
return NavigationThrottle::PROCEED;
const GURL& url = handle->GetURL();
// TODO(arthursonzogni): This is not the right RenderFrameHostImpl. The one
// that has initiated the navigation must be used instead.
// See
RenderFrameHostImpl* render_frame =
// TODO(estark): Move this check into NavigationRequest and split it into (1)
// check report-only CSP, (2) upgrade request if needed, (3) check enforced
// CSP to match how frame-src works.
if (render_frame->IsAllowedByCsp(
CSPDirective::FormAction, url, was_server_redirect,
false /* is_response_check */,
CSPContext::CHECK_ALL_CSP, true /* is_form_submission */)) {
return NavigationThrottle::PROCEED;
return NavigationThrottle::CANCEL;
} // namespace content