Skip to content

Commit

Permalink
Check context before installing Solana provider
Browse files Browse the repository at this point in the history
  • Loading branch information
bbondy committed Jun 30, 2022
1 parent 9f487cf commit f6dae30
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 77 deletions.
120 changes: 84 additions & 36 deletions browser/brave_wallet/solana_provider_renderer_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1093,63 +1093,103 @@ IN_PROC_BROWSER_TEST_F(SolanaProviderRendererTest, NonConfigurable) {
.ExtractBool());
}

IN_PROC_BROWSER_TEST_F(SolanaProviderRendererTest, Block3PIframe) {
GURL top_url(https_server_.GetURL("a.com", "/iframe.html"));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), top_url));

IN_PROC_BROWSER_TEST_F(SolanaProviderRendererTest, Iframe3P) {
constexpr char kEvalSolanaUndefined[] =
R"(typeof window.braveSolana === 'undefined')";

GURL secure_top_url(https_server_.GetURL("a.com", "/iframe.html"));
GURL insecure_top_url =
embedded_test_server()->GetURL("a.com", "/iframe.html");
GURL data_top_url = GURL(
"data:text/html;,<html><body><iframe id='test'></iframe></body></html>");
GURL iframe_url_1p(https_server_.GetURL("a.com", "/simple.html"));
GURL iframe_url_3p(https_server_.GetURL("b.a.com", "/simple.html"));
content::RenderFrameHost* main_frame =
web_contents(browser())->GetMainFrame();
auto* iframe_rfh = ChildFrameAt(main_frame, 0);
ASSERT_TRUE(iframe_rfh);
GURL data_simple_url = GURL("data:text/html;,<html><body></body></html>");

const struct {
std::string script;
GURL top_url;
GURL iframe_url;
} solana_undefined_cases[] =
{
// 3p iframe
{"true", iframe_url_3p},
// 1st party iframe with allow="solana 'none'"
{
R"(
{// 3p iframe
{"true", secure_top_url, iframe_url_3p},
// 1st party iframe with allow="solana 'none'"
{
R"(
document.querySelector('iframe').setAttribute('allow', 'solana \'none\'');
true
)",
iframe_url_1p},
// 1st party iframe with sandbox="allow-scripts"
{
R"(
secure_top_url, iframe_url_1p},
// 1st party iframe with sandbox="allow-scripts"
{
R"(
document.querySelector('iframe').removeAttribute('allow');
document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts');
true
)",
iframe_url_1p},
// 3p iframe with sandbox="allow-scripts allow-same-origin"
{
R"(
secure_top_url, iframe_url_1p},
// 3p iframe with sandbox="allow-scripts allow-same-origin"
{
R"(
document.querySelector('iframe').removeAttribute('allow');
document.querySelector('iframe')
.setAttribute('sandbox', 'allow-scripts allow-same-origin');
true
)",
iframe_url_3p},
// 3p iframe with allow="ethereum"
{
R"(
secure_top_url, iframe_url_3p},
// 3p iframe with allow="ethereum"
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe').setAttribute('allow', 'ethereum');
true
)",
iframe_url_3p},
secure_top_url, iframe_url_3p},

// 3p iframe with allow="solana; ethereum" but insecure top level
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe')
.setAttribute('allow', 'solana; ethereum');
true
)",
insecure_top_url, iframe_url_3p},

// 3p iframe with allow="solana; ethereum" but insecure top level (data
// URI)
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe')
.setAttribute('allow', 'solana; ethereum');
true
)",
data_top_url, iframe_url_3p},

// 3p iframe with allow="solana; ethereum" but insecure iframe
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe')
.setAttribute('allow', 'solana; ethereum');
true
)",
secure_top_url, data_simple_url},
// insecure top level and insecure iframe allow="solana; ethereum"
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe')
.setAttribute('allow', 'solana; ethereum');
true
)",
data_top_url, data_simple_url}

},
solana_defined_cases[] = {
// 1st party iframe
{"true", iframe_url_1p},
{"true", secure_top_url, iframe_url_1p},
// 1st party iframe sandbox="allow-scripts allow-same-origin"
{
R"(
Expand All @@ -1158,47 +1198,55 @@ IN_PROC_BROWSER_TEST_F(SolanaProviderRendererTest, Block3PIframe) {
.setAttribute('sandbox', 'allow-scripts allow-same-origin');
true
)",
iframe_url_1p},
secure_top_url, iframe_url_1p},
// 3p iframe with allow="solana"
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe').setAttribute('allow', 'solana');
true
)",
iframe_url_3p},
secure_top_url, iframe_url_3p},
// 3p iframe with allow="ethereum; solana"
{
R"(
document.querySelector('iframe').removeAttribute('sandbox');
document.querySelector('iframe').setAttribute('allow', 'ethereum; solana');
true
)",
iframe_url_3p},
secure_top_url, iframe_url_3p},
// 3rd party iframe with sandbox="allow-scripts" allow="solana"
{
R"(
document.querySelector('iframe').setAttribute('allow', 'solana');
document.querySelector('iframe').setAttribute('sandbox', 'allow-scripts');
true
)",
iframe_url_3p},
};
secure_top_url, iframe_url_3p}};

for (auto& c : solana_undefined_cases) {
SCOPED_TRACE(testing::Message() << c.script << c.iframe_url);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), c.top_url));
content::RenderFrameHost* main_frame =
web_contents(browser())->GetMainFrame();
EXPECT_TRUE(content::EvalJs(main_frame, c.script).ExtractBool());
EXPECT_TRUE(
NavigateIframeToURL(web_contents(browser()), "test", c.iframe_url));
EXPECT_TRUE(
content::EvalJs(iframe_rfh, kEvalSolanaUndefined).ExtractBool());
content::EvalJs(ChildFrameAt(main_frame, 0), kEvalSolanaUndefined)
.ExtractBool());
}
for (auto& c : solana_defined_cases) {
SCOPED_TRACE(testing::Message() << c.script << c.iframe_url);
SCOPED_TRACE(testing::Message() << c.script << c.top_url << c.iframe_url);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), c.top_url));
content::RenderFrameHost* main_frame =
web_contents(browser())->GetMainFrame();
EXPECT_TRUE(content::EvalJs(main_frame, c.script).ExtractBool());
EXPECT_TRUE(
NavigateIframeToURL(web_contents(browser()), "test", c.iframe_url));
EXPECT_FALSE(
content::EvalJs(iframe_rfh, kEvalSolanaUndefined).ExtractBool());
content::EvalJs(ChildFrameAt(main_frame, 0), kEvalSolanaUndefined)
.ExtractBool());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ bool ChromePermissionsClient::BraveCanBypassEmbeddingOriginCheck(
// exposing the API which can request permission when the origin is 3p and
// the feature policy is not allowed explicitly. We ensure that the correct
// handling is covered via the browser tests:
// SolanaProviderRendererTest.Block3PIframe and
// JSEthereumProviderBrowserTest.Block3PIframe
// SolanaProviderRendererTest.Iframe3P and
// JSEthereumProviderBrowserTest.Iframe3P
if (type == ContentSettingsType::BRAVE_ETHEREUM ||
type == ContentSettingsType::BRAVE_SOLANA) {
return true;
Expand Down
15 changes: 11 additions & 4 deletions renderer/brave_wallet/brave_wallet_render_frame_observer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ void BraveWalletRenderFrameObserver::DidCreateScriptContext(

bool is_main_world = world_id == content::ISOLATED_WORLD_ID_GLOBAL;
auto dynamic_params = get_dynamic_params_callback_.Run();
v8::Isolate* isolate = blink::MainThreadIsolate();
if (render_frame()->GetWebFrame()->GetDocument().IsDOMFeaturePolicyEnabled(
isolate->GetCurrentContext(), "ethereum")) {
render_frame()->GetWebFrame()->MainWorldScriptContext(),
"ethereum")) {
if (!js_ethereum_provider_) {
js_ethereum_provider_.reset(new JSEthereumProvider(
render_frame(), dynamic_params.brave_use_native_wallet));
Expand All @@ -86,12 +86,19 @@ void BraveWalletRenderFrameObserver::DidClearWindowObject() {
return;

v8::Isolate* isolate = blink::MainThreadIsolate();
v8::MicrotasksScope microtasks(isolate,
v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::HandleScope handle_scope(isolate);
auto* web_frame = render_frame()->GetWebFrame();
v8::Local<v8::Context> context = web_frame->MainWorldScriptContext();
if (context.IsEmpty())
return;

if (base::FeatureList::IsEnabled(
brave_wallet::features::kBraveWalletSolanaFeature) &&
base::FeatureList::IsEnabled(
brave_wallet::features::kBraveWalletSolanaProviderFeature) &&
render_frame()->GetWebFrame()->GetDocument().IsDOMFeaturePolicyEnabled(
isolate->GetCurrentContext(), "solana")) {
web_frame->GetDocument().IsDOMFeaturePolicyEnabled(context, "solana")) {
auto dynamic_params = get_dynamic_params_callback_.Run();
JSSolanaProvider::Install(
dynamic_params.allow_overwrite_window_web3_provider, render_frame());
Expand Down
Loading

0 comments on commit f6dae30

Please sign in to comment.