csp_validator_unittest.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <stddef.h>
  5. #include "base/strings/string_piece.h"
  6. #include "base/strings/string_split.h"
  7. #include "base/strings/string_util.h"
  8. #include "base/strings/stringprintf.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "extensions/common/csp_validator.h"
  11. #include "extensions/common/error_utils.h"
  12. #include "extensions/common/install_warning.h"
  13. #include "extensions/common/manifest_constants.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. using extensions::csp_validator::ContentSecurityPolicyIsLegal;
  16. using extensions::csp_validator::GetEffectiveSandoxedPageCSP;
  17. using extensions::csp_validator::SanitizeContentSecurityPolicy;
  18. using extensions::csp_validator::ContentSecurityPolicyIsSandboxed;
  19. using extensions::csp_validator::OPTIONS_NONE;
  20. using extensions::csp_validator::OPTIONS_ALLOW_UNSAFE_EVAL;
  21. using extensions::csp_validator::OPTIONS_ALLOW_INSECURE_OBJECT_SRC;
  22. using extensions::ErrorUtils;
  23. using extensions::InstallWarning;
  24. using extensions::Manifest;
  25. namespace {
  26. std::string InsecureValueWarning(
  27. const std::string& directive,
  28. const std::string& value,
  29. const std::string& manifest_key =
  30. extensions::manifest_keys::kContentSecurityPolicy) {
  31. return ErrorUtils::FormatErrorMessage(
  32. extensions::manifest_errors::kInvalidCSPInsecureValueIgnored,
  33. manifest_key, value, directive);
  34. }
  35. std::string MissingSecureSrcWarning(const std::string& manifest_key,
  36. const std::string& directive) {
  37. return ErrorUtils::FormatErrorMessage(
  38. extensions::manifest_errors::kInvalidCSPMissingSecureSrc, manifest_key,
  39. directive);
  40. }
  41. bool CSPEquals(const std::string& csp1, const std::string& csp2) {
  42. std::vector<std::string> csp1_parts = base::SplitString(
  43. csp1, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  44. std::sort(csp1_parts.begin(), csp1_parts.end());
  45. std::vector<std::string> csp2_parts = base::SplitString(
  46. csp2, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  47. std::sort(csp2_parts.begin(), csp2_parts.end());
  48. return csp1_parts == csp2_parts;
  49. }
  50. struct SanitizedCSPResult {
  51. std::string csp;
  52. std::vector<InstallWarning> warnings;
  53. };
  54. SanitizedCSPResult SanitizeCSP(const std::string& policy, int options) {
  55. SanitizedCSPResult result;
  56. result.csp = SanitizeContentSecurityPolicy(
  57. policy, extensions::manifest_keys::kContentSecurityPolicy, options,
  58. &result.warnings);
  59. return result;
  60. }
  61. SanitizedCSPResult SanitizeSandboxPageCSP(const std::string& policy) {
  62. SanitizedCSPResult result;
  63. result.csp = GetEffectiveSandoxedPageCSP(
  64. policy, extensions::manifest_keys::kSandboxedPagesCSP, &result.warnings);
  65. return result;
  66. }
  67. testing::AssertionResult CheckCSP(
  68. const SanitizedCSPResult& actual,
  69. const std::string& expected_csp,
  70. const std::vector<std::string>& expected_warnings) {
  71. if (!CSPEquals(expected_csp, actual.csp)) {
  72. return testing::AssertionFailure()
  73. << "SanitizeContentSecurityPolicy returned an unexpected CSP.\n"
  74. << "Expected CSP: " << expected_csp << "\n"
  75. << " Actual CSP: " << actual.csp;
  76. }
  77. if (expected_warnings.size() != actual.warnings.size()) {
  78. testing::Message msg;
  79. msg << "Expected " << expected_warnings.size() << " warnings, but got "
  80. << actual.warnings.size();
  81. for (size_t i = 0; i < actual.warnings.size(); ++i)
  82. msg << "\nWarning " << i << " " << actual.warnings[i].message;
  83. return testing::AssertionFailure() << msg;
  84. }
  85. for (size_t i = 0; i < expected_warnings.size(); ++i) {
  86. if (expected_warnings[i] != actual.warnings[i].message)
  87. return testing::AssertionFailure()
  88. << "Unexpected warning from SanitizeContentSecurityPolicy.\n"
  89. << "Expected warning[" << i << "]: " << expected_warnings[i]
  90. << " Actual warning[" << i << "]: " << actual.warnings[i].message;
  91. }
  92. return testing::AssertionSuccess();
  93. }
  94. testing::AssertionResult CheckCSP(const SanitizedCSPResult& actual) {
  95. return CheckCSP(actual, actual.csp, std::vector<std::string>());
  96. }
  97. testing::AssertionResult CheckCSP(const SanitizedCSPResult& actual,
  98. const std::string& expected_csp) {
  99. std::vector<std::string> expected_warnings;
  100. return CheckCSP(actual, expected_csp, expected_warnings);
  101. }
  102. testing::AssertionResult CheckCSP(const SanitizedCSPResult& actual,
  103. const std::string& expected_csp,
  104. const std::string& warning1) {
  105. std::vector<std::string> expected_warnings(1, warning1);
  106. return CheckCSP(actual, expected_csp, expected_warnings);
  107. }
  108. testing::AssertionResult CheckCSP(const SanitizedCSPResult& actual,
  109. const std::string& expected_csp,
  110. const std::string& warning1,
  111. const std::string& warning2) {
  112. std::vector<std::string> expected_warnings(1, warning1);
  113. expected_warnings.push_back(warning2);
  114. return CheckCSP(actual, expected_csp, expected_warnings);
  115. }
  116. testing::AssertionResult CheckCSP(const SanitizedCSPResult& actual,
  117. const std::string& expected_csp,
  118. const std::string& warning1,
  119. const std::string& warning2,
  120. const std::string& warning3) {
  121. std::vector<std::string> expected_warnings(1, warning1);
  122. expected_warnings.push_back(warning2);
  123. expected_warnings.push_back(warning3);
  124. return CheckCSP(actual, expected_csp, expected_warnings);
  125. }
  126. } // namespace
  127. TEST(ExtensionCSPValidator, IsLegal) {
  128. EXPECT_TRUE(ContentSecurityPolicyIsLegal("foo"));
  129. EXPECT_TRUE(ContentSecurityPolicyIsLegal(
  130. "default-src 'self'; script-src http://www.google.com"));
  131. EXPECT_FALSE(ContentSecurityPolicyIsLegal(
  132. "default-src 'self';\nscript-src http://www.google.com"));
  133. EXPECT_FALSE(ContentSecurityPolicyIsLegal(
  134. "default-src 'self';\rscript-src http://www.google.com"));
  135. EXPECT_FALSE(ContentSecurityPolicyIsLegal(
  136. "default-src 'self';,script-src http://www.google.com"));
  137. }
  138. TEST(ExtensionCSPValidator, IsSecure) {
  139. auto missing_secure_src_warning = [](const std::string& directive) {
  140. return MissingSecureSrcWarning(
  141. extensions::manifest_keys::kContentSecurityPolicy, directive);
  142. };
  143. EXPECT_TRUE(CheckCSP(SanitizeCSP(std::string(), OPTIONS_ALLOW_UNSAFE_EVAL),
  144. "script-src 'self'; object-src 'self';",
  145. missing_secure_src_warning("script-src"),
  146. missing_secure_src_warning("object-src")));
  147. EXPECT_TRUE(CheckCSP(
  148. SanitizeCSP("img-src https://google.com", OPTIONS_ALLOW_UNSAFE_EVAL),
  149. "img-src https://google.com; script-src 'self'; object-src 'self';",
  150. missing_secure_src_warning("script-src"),
  151. missing_secure_src_warning("object-src")));
  152. EXPECT_TRUE(CheckCSP(SanitizeCSP("script-src a b", OPTIONS_ALLOW_UNSAFE_EVAL),
  153. "script-src; object-src 'self';",
  154. InsecureValueWarning("script-src", "a"),
  155. InsecureValueWarning("script-src", "b"),
  156. missing_secure_src_warning("object-src")));
  157. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src *", OPTIONS_ALLOW_UNSAFE_EVAL),
  158. "default-src;",
  159. InsecureValueWarning("default-src", "*")));
  160. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  161. "default-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL)));
  162. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  163. "default-src 'none';", OPTIONS_ALLOW_UNSAFE_EVAL)));
  164. EXPECT_TRUE(
  165. CheckCSP(SanitizeCSP("default-src 'self' ftp://google.com",
  166. OPTIONS_ALLOW_UNSAFE_EVAL),
  167. "default-src 'self';",
  168. InsecureValueWarning("default-src", "ftp://google.com")));
  169. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  170. "default-src 'self' https://google.com;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  171. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src *; default-src 'self'",
  172. OPTIONS_ALLOW_UNSAFE_EVAL),
  173. "default-src; default-src 'self';",
  174. InsecureValueWarning("default-src", "*")));
  175. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  176. "default-src 'self'; default-src *;", OPTIONS_ALLOW_UNSAFE_EVAL),
  177. "default-src 'self'; default-src;"));
  178. EXPECT_TRUE(CheckCSP(
  179. SanitizeCSP(
  180. "default-src 'self'; default-src *; script-src *; script-src 'self'",
  181. OPTIONS_ALLOW_UNSAFE_EVAL),
  182. "default-src 'self'; default-src; script-src; script-src 'self';",
  183. InsecureValueWarning("script-src", "*")));
  184. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  185. "default-src 'self'; default-src *; script-src 'self'; script-src *;",
  186. OPTIONS_ALLOW_UNSAFE_EVAL),
  187. "default-src 'self'; default-src; script-src 'self'; script-src;"));
  188. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src *; script-src 'self'",
  189. OPTIONS_ALLOW_UNSAFE_EVAL),
  190. "default-src; script-src 'self';",
  191. InsecureValueWarning("default-src", "*")));
  192. EXPECT_TRUE(
  193. CheckCSP(SanitizeCSP("default-src *; script-src 'self'; img-src 'self'",
  194. OPTIONS_ALLOW_UNSAFE_EVAL),
  195. "default-src; script-src 'self'; img-src 'self';",
  196. InsecureValueWarning("default-src", "*")));
  197. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  198. "default-src *; script-src 'self'; object-src 'self';",
  199. OPTIONS_ALLOW_UNSAFE_EVAL),
  200. "default-src; script-src 'self'; object-src 'self';"));
  201. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  202. "script-src 'self'; object-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL)));
  203. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  204. "default-src 'unsafe-eval';", OPTIONS_ALLOW_UNSAFE_EVAL)));
  205. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'unsafe-eval'", OPTIONS_NONE),
  206. "default-src;",
  207. InsecureValueWarning("default-src", "'unsafe-eval'")));
  208. EXPECT_TRUE(CheckCSP(
  209. SanitizeCSP("default-src 'unsafe-inline'", OPTIONS_ALLOW_UNSAFE_EVAL),
  210. "default-src;", InsecureValueWarning("default-src", "'unsafe-inline'")));
  211. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'unsafe-inline' 'none'",
  212. OPTIONS_ALLOW_UNSAFE_EVAL),
  213. "default-src 'none';",
  214. InsecureValueWarning("default-src", "'unsafe-inline'")));
  215. EXPECT_TRUE(
  216. CheckCSP(SanitizeCSP("default-src 'self' http://google.com",
  217. OPTIONS_ALLOW_UNSAFE_EVAL),
  218. "default-src 'self';",
  219. InsecureValueWarning("default-src", "http://google.com")));
  220. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  221. "default-src 'self' https://google.com;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  222. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  223. "default-src 'self' chrome://resources;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  224. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  225. "default-src 'self' chrome-extension://aabbcc;",
  226. OPTIONS_ALLOW_UNSAFE_EVAL)));
  227. EXPECT_TRUE(
  228. CheckCSP(SanitizeCSP("default-src 'self';", OPTIONS_ALLOW_UNSAFE_EVAL)));
  229. EXPECT_TRUE(CheckCSP(
  230. SanitizeCSP("default-src 'self' https:", OPTIONS_ALLOW_UNSAFE_EVAL),
  231. "default-src 'self';", InsecureValueWarning("default-src", "https:")));
  232. EXPECT_TRUE(CheckCSP(
  233. SanitizeCSP("default-src 'self' http:", OPTIONS_ALLOW_UNSAFE_EVAL),
  234. "default-src 'self';", InsecureValueWarning("default-src", "http:")));
  235. EXPECT_TRUE(CheckCSP(
  236. SanitizeCSP("default-src 'self' google.com", OPTIONS_ALLOW_UNSAFE_EVAL),
  237. "default-src 'self';",
  238. InsecureValueWarning("default-src", "google.com")));
  239. EXPECT_TRUE(CheckCSP(
  240. SanitizeCSP("default-src 'self' *", OPTIONS_ALLOW_UNSAFE_EVAL),
  241. "default-src 'self';", InsecureValueWarning("default-src", "*")));
  242. EXPECT_TRUE(CheckCSP(
  243. SanitizeCSP("default-src 'self' *:*", OPTIONS_ALLOW_UNSAFE_EVAL),
  244. "default-src 'self';", InsecureValueWarning("default-src", "*:*")));
  245. EXPECT_TRUE(CheckCSP(
  246. SanitizeCSP("default-src 'self' *:*/", OPTIONS_ALLOW_UNSAFE_EVAL),
  247. "default-src 'self';", InsecureValueWarning("default-src", "*:*/")));
  248. EXPECT_TRUE(CheckCSP(
  249. SanitizeCSP("default-src 'self' *:*/path", OPTIONS_ALLOW_UNSAFE_EVAL),
  250. "default-src 'self';", InsecureValueWarning("default-src", "*:*/path")));
  251. EXPECT_TRUE(CheckCSP(
  252. SanitizeCSP("default-src 'self' https://", OPTIONS_ALLOW_UNSAFE_EVAL),
  253. "default-src 'self';", InsecureValueWarning("default-src", "https://")));
  254. EXPECT_TRUE(CheckCSP(
  255. SanitizeCSP("default-src 'self' https://*:*", OPTIONS_ALLOW_UNSAFE_EVAL),
  256. "default-src 'self';",
  257. InsecureValueWarning("default-src", "https://*:*")));
  258. EXPECT_TRUE(CheckCSP(
  259. SanitizeCSP("default-src 'self' https://*:*/", OPTIONS_ALLOW_UNSAFE_EVAL),
  260. "default-src 'self';",
  261. InsecureValueWarning("default-src", "https://*:*/")));
  262. EXPECT_TRUE(
  263. CheckCSP(SanitizeCSP("default-src 'self' https://*:*/path",
  264. OPTIONS_ALLOW_UNSAFE_EVAL),
  265. "default-src 'self';",
  266. InsecureValueWarning("default-src", "https://*:*/path")));
  267. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'self' https://*.com",
  268. OPTIONS_ALLOW_UNSAFE_EVAL),
  269. "default-src 'self';",
  270. InsecureValueWarning("default-src", "https://*.com")));
  271. EXPECT_TRUE(
  272. CheckCSP(SanitizeCSP("default-src 'self' https://*.*.google.com/",
  273. OPTIONS_ALLOW_UNSAFE_EVAL),
  274. "default-src 'self';",
  275. InsecureValueWarning("default-src", "https://*.*.google.com/")));
  276. EXPECT_TRUE(CheckCSP(
  277. SanitizeCSP("default-src 'self' https://*.*.google.com:*/",
  278. OPTIONS_ALLOW_UNSAFE_EVAL),
  279. "default-src 'self';",
  280. InsecureValueWarning("default-src", "https://*.*.google.com:*/")));
  281. EXPECT_TRUE(CheckCSP(
  282. SanitizeCSP("default-src 'self' https://www.*.google.com/",
  283. OPTIONS_ALLOW_UNSAFE_EVAL),
  284. "default-src 'self';",
  285. InsecureValueWarning("default-src", "https://www.*.google.com/")));
  286. EXPECT_TRUE(CheckCSP(
  287. SanitizeCSP("default-src 'self' https://www.*.google.com:*/",
  288. OPTIONS_ALLOW_UNSAFE_EVAL),
  289. "default-src 'self';",
  290. InsecureValueWarning("default-src", "https://www.*.google.com:*/")));
  291. EXPECT_TRUE(CheckCSP(
  292. SanitizeCSP("default-src 'self' chrome://*", OPTIONS_ALLOW_UNSAFE_EVAL),
  293. "default-src 'self';",
  294. InsecureValueWarning("default-src", "chrome://*")));
  295. EXPECT_TRUE(
  296. CheckCSP(SanitizeCSP("default-src 'self' chrome-extension://*",
  297. OPTIONS_ALLOW_UNSAFE_EVAL),
  298. "default-src 'self';",
  299. InsecureValueWarning("default-src", "chrome-extension://*")));
  300. EXPECT_TRUE(
  301. CheckCSP(SanitizeCSP("default-src 'self' chrome-extension://",
  302. OPTIONS_ALLOW_UNSAFE_EVAL),
  303. "default-src 'self';",
  304. InsecureValueWarning("default-src", "chrome-extension://")));
  305. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  306. "default-src 'self' https://*.google.com;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  307. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  308. "default-src 'self' https://*.google.com:1;",
  309. OPTIONS_ALLOW_UNSAFE_EVAL)));
  310. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  311. "default-src 'self' https://*.google.com:*;",
  312. OPTIONS_ALLOW_UNSAFE_EVAL)));
  313. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  314. "default-src 'self' https://*.google.com:1/;",
  315. OPTIONS_ALLOW_UNSAFE_EVAL)));
  316. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  317. "default-src 'self' https://*.google.com:*/;",
  318. OPTIONS_ALLOW_UNSAFE_EVAL)));
  319. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  320. "default-src 'self' http://127.0.0.1;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  321. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  322. "default-src 'self' http://localhost;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  323. EXPECT_TRUE(CheckCSP(SanitizeCSP("default-src 'self' http://lOcAlHoSt;",
  324. OPTIONS_ALLOW_UNSAFE_EVAL),
  325. "default-src 'self' http://lOcAlHoSt;"));
  326. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  327. "default-src 'self' http://127.0.0.1:9999;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  328. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  329. "default-src 'self' http://localhost:8888;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  330. EXPECT_TRUE(CheckCSP(
  331. SanitizeCSP("default-src 'self' http://127.0.0.1.example.com",
  332. OPTIONS_ALLOW_UNSAFE_EVAL),
  333. "default-src 'self';",
  334. InsecureValueWarning("default-src", "http://127.0.0.1.example.com")));
  335. EXPECT_TRUE(CheckCSP(
  336. SanitizeCSP("default-src 'self' http://localhost.example.com",
  337. OPTIONS_ALLOW_UNSAFE_EVAL),
  338. "default-src 'self';",
  339. InsecureValueWarning("default-src", "http://localhost.example.com")));
  340. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  341. "default-src 'self' blob:;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  342. EXPECT_TRUE(CheckCSP(
  343. SanitizeCSP("default-src 'self' blob:http://example.com/XXX",
  344. OPTIONS_ALLOW_UNSAFE_EVAL),
  345. "default-src 'self';",
  346. InsecureValueWarning("default-src", "blob:http://example.com/XXX")));
  347. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  348. "default-src 'self' filesystem:;", OPTIONS_ALLOW_UNSAFE_EVAL)));
  349. EXPECT_TRUE(CheckCSP(
  350. SanitizeCSP("default-src 'self' filesystem:http://example.com/XX",
  351. OPTIONS_ALLOW_UNSAFE_EVAL),
  352. "default-src 'self';",
  353. InsecureValueWarning("default-src", "filesystem:http://example.com/XX")));
  354. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  355. "default-src 'self' https://*.googleapis.com;",
  356. OPTIONS_ALLOW_UNSAFE_EVAL)));
  357. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  358. "default-src 'self' https://x.googleapis.com;",
  359. OPTIONS_ALLOW_UNSAFE_EVAL)));
  360. EXPECT_TRUE(
  361. CheckCSP(SanitizeCSP("script-src 'self'; object-src *", OPTIONS_NONE),
  362. "script-src 'self'; object-src;",
  363. InsecureValueWarning("object-src", "*")));
  364. EXPECT_TRUE(CheckCSP(SanitizeCSP("script-src 'self'; object-src *",
  365. OPTIONS_ALLOW_INSECURE_OBJECT_SRC),
  366. "script-src 'self'; object-src *;"));
  367. EXPECT_TRUE(CheckCSP(
  368. SanitizeCSP("script-src 'self'; object-src http://www.example.com",
  369. OPTIONS_ALLOW_INSECURE_OBJECT_SRC)));
  370. EXPECT_TRUE(CheckCSP(
  371. SanitizeCSP("object-src http://www.example.com blob:; script-src 'self'",
  372. OPTIONS_ALLOW_INSECURE_OBJECT_SRC)));
  373. EXPECT_TRUE(
  374. CheckCSP(SanitizeCSP("script-src 'self'; object-src http://*.example.com",
  375. OPTIONS_ALLOW_INSECURE_OBJECT_SRC)));
  376. EXPECT_TRUE(CheckCSP(SanitizeCSP("script-src *; object-src *",
  377. OPTIONS_ALLOW_INSECURE_OBJECT_SRC),
  378. "script-src; object-src *",
  379. InsecureValueWarning("script-src", "*")));
  380. EXPECT_TRUE(CheckCSP(SanitizeCSP(
  381. "default-src; script-src"
  382. " 'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw='"
  383. " 'sha384-bSVm1i3sjPBRM4TwZtYTDjk9JxZMExYHWbFmP1SxDhJH4ue0Wu9OPOkY5hcqRcS"
  384. "t'"
  385. " 'sha512-440MmBLtj9Kp5Bqloogn9BqGDylY8vFsv5/zXL1zH2fJVssCoskRig4gyM+9Kqw"
  386. "vCSapSz5CVoUGHQcxv43UQg==';",
  387. OPTIONS_NONE)));
  388. // Reject non-standard algorithms, even if they are still supported by Blink.
  389. EXPECT_TRUE(CheckCSP(
  390. SanitizeCSP(
  391. "default-src; script-src 'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw=';",
  392. OPTIONS_NONE),
  393. "default-src; script-src;",
  394. InsecureValueWarning("script-src",
  395. "'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw='")));
  396. EXPECT_TRUE(CheckCSP(
  397. SanitizeCSP("default-src; script-src "
  398. "'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZ"
  399. "wBw= sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng=';",
  400. OPTIONS_NONE),
  401. "default-src; script-src;",
  402. InsecureValueWarning(
  403. "script-src", "'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw="),
  404. InsecureValueWarning(
  405. "script-src",
  406. "sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='")));
  407. }
  408. TEST(ExtensionCSPValidator, IsSandboxed) {
  409. EXPECT_FALSE(ContentSecurityPolicyIsSandboxed(std::string(),
  410. Manifest::TYPE_EXTENSION));
  411. EXPECT_FALSE(ContentSecurityPolicyIsSandboxed("img-src https://google.com",
  412. Manifest::TYPE_EXTENSION));
  413. // Sandbox directive is required.
  414. EXPECT_TRUE(ContentSecurityPolicyIsSandboxed(
  415. "sandbox", Manifest::TYPE_EXTENSION));
  416. // Additional sandbox tokens are OK.
  417. EXPECT_TRUE(ContentSecurityPolicyIsSandboxed(
  418. "sandbox allow-scripts", Manifest::TYPE_EXTENSION));
  419. // Except for allow-same-origin.
  420. EXPECT_FALSE(ContentSecurityPolicyIsSandboxed(
  421. "sandbox allow-same-origin", Manifest::TYPE_EXTENSION));
  422. // Additional directives are OK.
  423. EXPECT_TRUE(ContentSecurityPolicyIsSandboxed(
  424. "sandbox; img-src https://google.com", Manifest::TYPE_EXTENSION));
  425. // Extensions allow navigation, platform apps don't.
  426. EXPECT_TRUE(ContentSecurityPolicyIsSandboxed(
  427. "sandbox allow-top-navigation", Manifest::TYPE_EXTENSION));
  428. EXPECT_FALSE(ContentSecurityPolicyIsSandboxed(
  429. "sandbox allow-top-navigation", Manifest::TYPE_PLATFORM_APP));
  430. // Popups are OK.
  431. EXPECT_TRUE(ContentSecurityPolicyIsSandboxed(
  432. "sandbox allow-popups", Manifest::TYPE_EXTENSION));
  433. EXPECT_TRUE(ContentSecurityPolicyIsSandboxed(
  434. "sandbox allow-popups", Manifest::TYPE_PLATFORM_APP));
  435. }
  436. TEST(ExtensionCSPValidator, EffectiveSandboxedPageCSP) {
  437. auto insecure_value_warning = [](const std::string& directive,
  438. const std::string& value) {
  439. return InsecureValueWarning(directive, value,
  440. extensions::manifest_keys::kSandboxedPagesCSP);
  441. };
  442. EXPECT_TRUE(CheckCSP(
  443. SanitizeSandboxPageCSP(""),
  444. "child-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';"));
  445. EXPECT_TRUE(CheckCSP(
  446. SanitizeSandboxPageCSP("child-src http://www.google.com"),
  447. "child-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';",
  448. insecure_value_warning("child-src", "http://www.google.com")));
  449. EXPECT_TRUE(CheckCSP(
  450. SanitizeSandboxPageCSP("child-src *"),
  451. "child-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';",
  452. insecure_value_warning("child-src", "*")));
  453. EXPECT_TRUE(CheckCSP(
  454. SanitizeSandboxPageCSP("child-src 'none'"),
  455. "child-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval';"));
  456. // Directive values of 'none' and 'self' are preserved.
  457. EXPECT_TRUE(
  458. CheckCSP(SanitizeSandboxPageCSP("script-src 'none'; frame-src 'self';"),
  459. "frame-src 'self'; script-src 'none';"));
  460. EXPECT_TRUE(CheckCSP(
  461. SanitizeSandboxPageCSP(
  462. "script-src 'none'; frame-src 'self' http://www.google.com;"),
  463. "frame-src 'self'; script-src 'none';",
  464. insecure_value_warning("frame-src", "http://www.google.com")));
  465. // script-src will add 'unsafe-inline' and 'unsafe-eval' only if script-src is
  466. // not specified.
  467. EXPECT_TRUE(CheckCSP(SanitizeSandboxPageCSP("script-src 'self'"),
  468. "script-src 'self'; child-src 'self'"));
  469. EXPECT_TRUE(
  470. CheckCSP(SanitizeSandboxPageCSP(
  471. "script-src 'self' 'unsafe-inline'; child-src 'self';"),
  472. "child-src 'self'; script-src 'self' 'unsafe-inline';"));
  473. EXPECT_TRUE(
  474. CheckCSP(SanitizeSandboxPageCSP(
  475. "script-src 'self' 'unsafe-eval'; child-src 'self';"),
  476. "child-src 'self'; script-src 'self' 'unsafe-eval';"));
  477. // child-src and frame-src are handled correctly.
  478. EXPECT_TRUE(CheckCSP(
  479. SanitizeSandboxPageCSP(
  480. "script-src 'none'; frame-src 'self' http://www.google.com;"),
  481. "frame-src 'self'; script-src 'none';",
  482. insecure_value_warning("frame-src", "http://www.google.com")));
  483. EXPECT_TRUE(CheckCSP(
  484. SanitizeSandboxPageCSP(
  485. "script-src 'none'; child-src 'self' http://www.google.com;"),
  486. "child-src 'self'; script-src 'none';",
  487. insecure_value_warning("child-src", "http://www.google.com")));
  488. // Multiple insecure values.
  489. EXPECT_TRUE(CheckCSP(
  490. SanitizeSandboxPageCSP(
  491. "script-src 'none'; child-src http://bar.com 'self' http://foo.com;"),
  492. "child-src 'self'; script-src 'none';",
  493. insecure_value_warning("child-src", "http://bar.com"),
  494. insecure_value_warning("child-src", "http://foo.com")));
  495. }
  496. namespace extensions {
  497. namespace csp_validator {
  498. void PrintTo(const CSPParser::Directive& directive, ::std::ostream* os) {
  499. *os << base::StringPrintf(
  500. "[[%s] [%s] [%s]]", std::string(directive.directive_string).c_str(),
  501. directive.directive_name.c_str(),
  502. base::JoinString(directive.directive_values, ",").c_str());
  503. }
  504. } // namespace csp_validator
  505. } // namespace extensions
  506. TEST(ExtensionCSPValidator, ParseCSP) {
  507. using CSPParser = extensions::csp_validator::CSPParser;
  508. using DirectiveList = CSPParser::DirectiveList;
  509. struct TestCase {
  510. TestCase(const char* policy, DirectiveList expected_directives)
  511. : policy(policy), expected_directives(std::move(expected_directives)) {}
  512. const char* policy;
  513. DirectiveList expected_directives;
  514. };
  515. std::vector<TestCase> cases;
  516. cases.emplace_back(" \n \r \t ", DirectiveList());
  517. cases.emplace_back(" ; \n ;\r \t ;;", DirectiveList());
  518. const char* policy = R"( deFAULt-src 'self' ;
  519. img-src * ; media-src media1.com MEDIA2.com;
  520. img-src 'self';
  521. )";
  522. DirectiveList expected_directives;
  523. expected_directives.emplace_back("deFAULt-src 'self'", "default-src",
  524. std::vector<base::StringPiece>({"'self'"}));
  525. expected_directives.emplace_back("img-src *", "img-src",
  526. std::vector<base::StringPiece>({"*"}));
  527. expected_directives.emplace_back(
  528. "media-src media1.com MEDIA2.com", "media-src",
  529. std::vector<base::StringPiece>({"media1.com", "MEDIA2.com"}));
  530. expected_directives.emplace_back("img-src 'self'", "img-src",
  531. std::vector<base::StringPiece>({"'self'"}));
  532. cases.emplace_back(policy, std::move(expected_directives));
  533. for (const auto& test_case : cases) {
  534. SCOPED_TRACE(test_case.policy);
  535. CSPParser parser(test_case.policy);
  536. // Cheat and compare serialized versions of the directives.
  537. EXPECT_EQ(::testing::PrintToString(parser.directives()),
  538. ::testing::PrintToString(test_case.expected_directives));
  539. }
  540. }
  541. TEST(ExtensionCSPValidator, DoesCSPDisallowRemoteCode) {
  542. const char* kManifestKey = "dummy_key";
  543. auto insecure_value_error = [kManifestKey](const std::string& directive,
  544. const std::string& value) {
  545. return ErrorUtils::FormatErrorMessage(
  546. extensions::manifest_errors::kInvalidCSPInsecureValueError,
  547. kManifestKey, value, directive);
  548. };
  549. auto missing_secure_src_error = [kManifestKey](const std::string& directive) {
  550. return MissingSecureSrcWarning(kManifestKey, directive);
  551. };
  552. struct {
  553. const char* policy;
  554. std::string expected_error; // Empty if no error expected.
  555. } test_cases[] = {
  556. {"frame-src google.com; default-src yahoo.com; script-src 'self'; "
  557. "worker-src; object-src http://localhost:80 'none'",
  558. ""},
  559. {"worker-src http://localhost google.com; script-src; object-src 'self'",
  560. insecure_value_error("worker-src", "google.com")},
  561. {"script-src; worker-src 'self';",
  562. missing_secure_src_error("object-src")},
  563. // Duplicate directives are ignored.
  564. {"script-src; worker-src 'self'; default-src 'self'; script-src "
  565. "google.com",
  566. ""},
  567. // "object-src" falls back to "default-src".
  568. {"script-src; worker-src 'self'; default-src google.com",
  569. insecure_value_error("object-src", "google.com")},
  570. // "worker-src" falls back to "script-src".
  571. {"script-src 'self'; object-src 'none'; default-src google.com", ""},
  572. {"script-src 'unsafe-eval'; worker-src; default-src;",
  573. insecure_value_error("script-src", "'unsafe-eval'")}};
  574. for (const auto& test_case : test_cases) {
  575. SCOPED_TRACE(test_case.policy);
  576. std::u16string error;
  577. bool result = extensions::csp_validator::DoesCSPDisallowRemoteCode(
  578. test_case.policy, kManifestKey, &error);
  579. EXPECT_EQ(test_case.expected_error.empty(), result);
  580. EXPECT_EQ(base::ASCIIToUTF16(test_case.expected_error), error);
  581. }
  582. }