TEST_F(ContentSecurityPolicyTest, NonceInline) { struct TestCase { const char* policy; const char* nonce; bool allowed; } cases[] = { { "'unsafe-inline'", "", true }, { "'unsafe-inline'", "yay", true }, { "'nonce-yay'", "", false }, { "'nonce-yay'", "yay", true }, { "'unsafe-inline' 'nonce-yay'", "", false }, { "'unsafe-inline' 'nonce-yay'", "yay", true }, }; String contextURL; String content; WTF::OrdinalNumber contextLine; for (const auto& test : cases) { SCOPED_TRACE(testing::Message() << "Policy: `" << test.policy << "`, Nonce: `" << test.nonce << "`"); unsigned expectedReports = test.allowed ? 0u : 1u; // Enforce 'script-src' Persistent<ContentSecurityPolicy> policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(String("script-src ") + test.policy, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_EQ(test.allowed, policy->allowInlineScript(contextURL, String(test.nonce), contextLine, content)); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Enforce 'style-src' policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(String("style-src ") + test.policy, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_EQ(test.allowed, policy->allowInlineStyle(contextURL, String(test.nonce), contextLine, content)); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Report 'script-src' policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(String("script-src ") + test.policy, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_TRUE(policy->allowInlineScript(contextURL, String(test.nonce), contextLine, content)); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Report 'style-src' policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(String("style-src ") + test.policy, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_TRUE(policy->allowInlineStyle(contextURL, String(test.nonce), contextLine, content)); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); } }
TEST_F(ContentSecurityPolicyTest, NonceSinglePolicy) { struct TestCase { const char* policy; const char* url; const char* nonce; bool allowed; } cases[] = { { "script-src 'nonce-yay'", "https://example.com/js", "", false }, { "script-src 'nonce-yay'", "https://example.com/js", "yay", true }, { "script-src https://example.com", "https://example.com/js", "", true }, { "script-src https://example.com", "https://example.com/js", "yay", true }, { "script-src https://example.com 'nonce-yay'", "https://not.example.com/js", "", false }, { "script-src https://example.com 'nonce-yay'", "https://not.example.com/js", "yay", true }, }; for (const auto& test : cases) { SCOPED_TRACE(testing::Message() << "Policy: `" << test.policy << "`, URL: `" << test.url << "`, Nonce: `" << test.nonce << "`"); KURL resource = KURL(KURL(), test.url); unsigned expectedReports = test.allowed ? 0u : 1u; // Single enforce-mode policy should match `test.expected`: Persistent<ContentSecurityPolicy> policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(test.policy, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_EQ(test.allowed, policy->allowScriptFromSource(resource, String(test.nonce))); // If this is expected to generate a violation, we should have sent a report. EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Single report-mode policy should always be `true`: policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(test.policy, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_TRUE(policy->allowScriptFromSource(resource, String(test.nonce))); // If this is expected to generate a violation, we should have sent a report, even though // we don't deny access in `allowScriptFromSource`: EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); } }
TEST_F(ContentSecurityPolicyTest, NonceMultiplePolicy) { struct TestCase { const char* policy1; const char* policy2; const char* url; const char* nonce; bool allowed1; bool allowed2; } cases[] = { // Passes both: { "script-src 'nonce-yay'", "script-src 'nonce-yay'", "https://example.com/js", "yay", true, true }, { "script-src https://example.com", "script-src 'nonce-yay'", "https://example.com/js", "yay", true, true }, { "script-src 'nonce-yay'", "script-src https://example.com", "https://example.com/js", "yay", true, true }, { "script-src https://example.com 'nonce-yay'", "script-src https://example.com 'nonce-yay'", "https://example.com/js", "yay", true, true }, { "script-src https://example.com 'nonce-yay'", "script-src https://example.com 'nonce-yay'", "https://example.com/js", "", true, true }, { "script-src https://example.com", "script-src https://example.com 'nonce-yay'", "https://example.com/js", "yay", true, true }, { "script-src https://example.com 'nonce-yay'", "script-src https://example.com", "https://example.com/js", "yay", true, true }, // Fails one: { "script-src 'nonce-yay'", "script-src https://example.com", "https://example.com/js", "", false, true }, { "script-src 'nonce-yay'", "script-src 'none'", "https://example.com/js", "yay", true, false }, { "script-src 'nonce-yay'", "script-src https://not.example.com", "https://example.com/js", "yay", true, false }, // Fails both: { "script-src 'nonce-yay'", "script-src https://example.com", "https://not.example.com/js", "", false, false }, { "script-src https://example.com", "script-src 'nonce-yay'", "https://not.example.com/js", "", false, false }, { "script-src 'nonce-yay'", "script-src 'none'", "https://not.example.com/js", "boo", false, false }, { "script-src 'nonce-yay'", "script-src https://not.example.com", "https://example.com/js", "", false, false }, }; for (const auto& test : cases) { SCOPED_TRACE(testing::Message() << "Policy: `" << test.policy1 << "`/`" << test.policy2 << "`, URL: `" << test.url << "`, Nonce: `" << test.nonce << "`"); KURL resource = KURL(KURL(), test.url); unsigned expectedReports = test.allowed1 != test.allowed2 ? 1u : (test.allowed1 ? 0u : 2u); // Enforce / Report Persistent<ContentSecurityPolicy> policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(test.policy1, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); policy->didReceiveHeader(test.policy2, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_EQ(test.allowed1, policy->allowScriptFromSource(resource, String(test.nonce))); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Report / Enforce policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(test.policy1, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); policy->didReceiveHeader(test.policy2, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_EQ(test.allowed2, policy->allowScriptFromSource(resource, String(test.nonce))); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Enforce / Enforce policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(test.policy1, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); policy->didReceiveHeader(test.policy2, ContentSecurityPolicyHeaderTypeEnforce, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_EQ(test.allowed1 && test.allowed2, policy->allowScriptFromSource(resource, String(test.nonce))); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); // Report / Report policy = ContentSecurityPolicy::create(); policy->bindToExecutionContext(document.get()); policy->didReceiveHeader(test.policy1, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); policy->didReceiveHeader(test.policy2, ContentSecurityPolicyHeaderTypeReport, ContentSecurityPolicyHeaderSourceHTTP); EXPECT_TRUE(policy->allowScriptFromSource(resource, String(test.nonce))); EXPECT_EQ(expectedReports, policy->m_violationReportsSent.size()); } }