diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp
index d22c29618897..08198d740a48 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/feedback.cpp
@@ -9,14 +9,6 @@
 
 namespace zxcvbn {
 
-const Feedback DEFAULT_FEEDBACK = {
-  "",
-  {
-    "Use a few words, avoid common phrases",
-    "No need for symbols, digits, or uppercase letters",
-  },
-};
-
 static
 optional::optional<Feedback> get_match_feedback(const Match & match, bool is_sole_match);
 
@@ -26,7 +18,15 @@ Feedback get_dictionary_match_feedback(const Match & match, bool is_sole_match);
 Feedback get_feedback(score_t score,
                       const std::vector<Match> & sequence) {
   // starting feedback
-  if (!sequence.size()) return DEFAULT_FEEDBACK;
+  if (!sequence.size()) {
+    return {
+        "",
+        {
+            "Use a few words, avoid common phrases",
+            "No need for symbols, digits, or uppercase letters",
+        },
+    };
+  }
 
   // no feedback if score is good or great.
   if (score > 2) return {"", {}};
@@ -151,12 +151,11 @@ Feedback get_dictionary_match_feedback(const Match & match_, bool is_sole_match)
 
   std::vector<std::string> suggestions;
   auto & word = match_.token;
-  if (std::regex_search(word, START_UPPER)) {
+  if (std::regex_search(word, START_UPPER())) {
     suggestions.push_back("Capitalization doesn't help very much");
-  }
-  else if (std::regex_search(word, ALL_UPPER) and
-           // XXX: UTF-8
-           util::ascii_lower(word) == word) {
+  } else if (std::regex_search(word, ALL_UPPER()) and
+             // XXX: UTF-8
+             util::ascii_lower(word) == word) {
     suggestions.push_back("All-uppercase is almost as easy to guess as all-lowercase");
   }
 
@@ -171,4 +170,3 @@ Feedback get_dictionary_match_feedback(const Match & match_, bool is_sole_match)
 }
 
 }
-
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp
index c14e02618ec2..6d43cd2dc20b 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.cpp
@@ -19,28 +19,41 @@
 #include <utility>
 #include <unordered_set>
 
+#include "base/no_destructor.h"
+
 namespace zxcvbn {
 
 // TODO: make this a constexpr
-extern const std::vector<std::pair<std::string, std::vector<std::string>>> L33T_TABLE = {
-  {"a", {"4", "@"}},
-  {"b", {"8"}},
-  {"c", {"(", "{", "[", "<"}},
-  {"e", {"3"}},
-  {"g", {"6", "9"}},
-  {"i", {"1", "!", "|"}},
-  {"l", {"1", "|", "7"}},
-  {"o", {"0"}},
-  {"s", {"$", "5"}},
-  {"t", {"+", "7"}},
-  {"x", {"%"}},
-  {"z", {"2"}},
-};
+const std::vector<std::pair<std::string, std::vector<std::string>>>&
+L33T_TABLE() {
+  static base::NoDestructor<
+      std::vector<std::pair<std::string, std::vector<std::string>>>>
+      leet_table({
+          {"a", {"4", "@"}},
+          {"b", {"8"}},
+          {"c", {"(", "{", "[", "<"}},
+          {"e", {"3"}},
+          {"g", {"6", "9"}},
+          {"i", {"1", "!", "|"}},
+          {"l", {"1", "|", "7"}},
+          {"o", {"0"}},
+          {"s", {"$", "5"}},
+          {"t", {"+", "7"}},
+          {"x", {"%"}},
+          {"z", {"2"}},
+      });
+
+  return *leet_table;
+}
 
 // TODO: make this constexpr
-extern const std::vector<std::pair<RegexTag, std::regex>> REGEXEN = {
-  {RegexTag::RECENT_YEAR, std::regex(R"(19\d\d|200\d|201\d)")},
-};
+const std::vector<std::pair<RegexTag, std::regex>>& REGEXEN() {
+  static base::NoDestructor<std::vector<std::pair<RegexTag, std::regex>>>
+      regexen({
+          {RegexTag::RECENT_YEAR, std::regex(R"(19\d\d|200\d|201\d)")},
+      });
+  return *regexen;
+}
 
 const auto DATE_MAX_YEAR = 2050;
 const auto DATE_MIN_YEAR = 1000;
@@ -115,19 +128,18 @@ std::vector<Match> omnimatch(const std::string & password,
                                             std::cref(ranked_dict)));
 
   std::vector<Match> matches;
-  std::function<std::vector<Match>(const std::string &)> matchers[] = {
-    std::bind(dictionary_match, std::placeholders::_1,
-              std::cref(ranked_dictionaries)),
-    std::bind(reverse_dictionary_match, std::placeholders::_1,
-              std::cref(ranked_dictionaries)),
-    std::bind(l33t_match, std::placeholders::_1,
-              std::cref(ranked_dictionaries), std::cref(L33T_TABLE)),
-    std::bind(spatial_match, std::placeholders::_1,
-              std::cref(graphs())),
-    repeat_match,
-    sequence_match,
-    std::bind(regex_match, std::placeholders::_1, std::cref(REGEXEN)),
-    date_match,
+  std::function<std::vector<Match>(const std::string&)> matchers[] = {
+      std::bind(dictionary_match, std::placeholders::_1,
+                std::cref(ranked_dictionaries)),
+      std::bind(reverse_dictionary_match, std::placeholders::_1,
+                std::cref(ranked_dictionaries)),
+      std::bind(l33t_match, std::placeholders::_1,
+                std::cref(ranked_dictionaries), std::cref(L33T_TABLE())),
+      std::bind(spatial_match, std::placeholders::_1, std::cref(graphs())),
+      repeat_match,
+      sequence_match,
+      std::bind(regex_match, std::placeholders::_1, std::cref(REGEXEN())),
+      date_match,
   };
   for (const auto & matcher : matchers) {
     auto ret = matcher(password);
@@ -344,12 +356,13 @@ std::vector<Match> spatial_match(const std::string & password,
   return matches;
 }
 
-const auto SHIFTED_RX = std::regex("[~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?]");
-
 static
 std::vector<Match> spatial_match_helper(const std::string & password,
                                         const Graph & graph,
                                         GraphTag graph_tag) {
+  const auto SHIFTED_RX =
+      std::regex("[~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?]");
+
   std::vector<Match> matches;
   if (!password.length()) return matches;
   idx_t idx = 0;
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp
index 7ded5d89573f..ba73b909157c 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp
@@ -10,8 +10,8 @@
 
 namespace zxcvbn {
 
-extern const std::vector<std::pair<std::string, std::vector<std::string>>> L33T_TABLE;
-extern const std::vector<std::pair<RegexTag, std::regex>> REGEXEN;
+const std::vector<std::pair<std::string, std::vector<std::string>>>& L33T_TABLE();
+const std::vector<std::pair<RegexTag, std::regex>>& REGEXEN();
 
 std::vector<Match> dictionary_match(const std::string & password,
                                     const RankedDicts & ranked_dictionaries);
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp
index 1dfcb53bc42d..1664a27b277c 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/matching_js_bindings.cpp
@@ -66,7 +66,7 @@ emscripten::val _dictionary_match(const std::wstring & wpassword,
       std::vector<std::pair<std::string, std::vector<std::string>>> _store;
       auto & ret2 = [&] () -> const std::vector<std::pair<std::string, std::vector<std::string>>> & {
         if (l33t_table.isUndefined()) {
-          return zxcvbn::L33T_TABLE;
+          return zxcvbn::L33T_TABLE();
         }
         else {
           auto ret = val_converter<std::unordered_map<std::string, std::vector<std::string>>>::from(l33t_table);
@@ -198,7 +198,7 @@ emscripten::val repeat_match(const std::wstring & wpassword) {
 
 static
 emscripten::val regex_match(const std::wstring & wpassword) {
-  return to_val(zxcvbn::regex_match(to_utf8(wpassword), zxcvbn::REGEXEN));
+  return to_val(zxcvbn::regex_match(to_utf8(wpassword), zxcvbn::REGEXEN()));
 }
 
 static
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp
index 96c4c76d1e65..fe2a2ec8cb8b 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.cpp
@@ -9,6 +9,8 @@
 
 #include <cmath>
 
+#include "base/no_destructor.h"
+
 namespace std {
 
 template<class T, class U>
@@ -27,6 +29,26 @@ const auto MIN_GUESSES_BEFORE_GROWING_SEQUENCE = static_cast<guesses_t>(10000);
 const auto MIN_SUBMATCH_GUESSES_SINGLE_CHAR = static_cast<guesses_t>(10);
 const auto MIN_SUBMATCH_GUESSES_MULTI_CHAR = static_cast<guesses_t>(50);
 
+const std::regex& START_UPPER() {
+  static base::NoDestructor<std::regex> start_upper(R"(^[A-Z][^A-Z]+$)");
+  return *start_upper;
+}
+
+const std::regex& END_UPPER() {
+  static base::NoDestructor<std::regex> end_upper(R"(^[^A-Z]+[A-Z]$)");
+  return *end_upper;
+}
+
+const std::regex& ALL_UPPER() {
+  static base::NoDestructor<std::regex> all_upper(R"(^[^a-z]+$)");
+  return *all_upper;
+}
+
+const std::regex& ALL_LOWER() {
+  static base::NoDestructor<std::regex> all_lower(R"(^[^A-Z]+$)");
+  return *all_lower;
+}
+
 template<class Tret, class Tin>
 Tret factorial(Tin n) {
   // unoptimized, called only on small n
@@ -441,11 +463,12 @@ guesses_t dictionary_guesses(const Match & match) {
 
 guesses_t uppercase_variations(const Match & match) {
   auto & word = match.token;
-  if (std::regex_match(word, ALL_LOWER) || !word.size()) return 1;
+  if (std::regex_match(word, ALL_LOWER()) || !word.size())
+    return 1;
   // a capitalized word is the most common capitalization scheme,
   // so it only doubles the search space (uncapitalized + capitalized).
   // allcaps and end-capitalized are common enough too, underestimate as 2x factor to be safe.
-  for (const auto & regex : {START_UPPER, END_UPPER, ALL_UPPER}) {
+  for (const auto& regex : {START_UPPER(), END_UPPER(), ALL_UPPER()}) {
     if (std::regex_match(word, regex)) return 2;
   }
   // otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp
index ec9fd22d8e18..1038ee34587c 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp
@@ -11,10 +11,10 @@
 
 namespace zxcvbn {
 
-const auto START_UPPER = std::regex(R"(^[A-Z][^A-Z]+$)");
-const auto END_UPPER = std::regex(R"(^[^A-Z]+[A-Z]$)");
-const auto ALL_UPPER = std::regex(R"(^[^a-z]+$)");
-const auto ALL_LOWER = std::regex(R"(^[^A-Z]+$)");
+const std::regex& START_UPPER();
+const std::regex& END_UPPER();
+const std::regex& ALL_UPPER();
+const std::regex& ALL_LOWER();
 
 const guesses_t MIN_YEAR_SPACE = 20;
 const auto REFERENCE_YEAR = 2016;
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
index 084d3cc0cd7c..107bce0af064 100644
--- a/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
+++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
@@ -8,6 +8,8 @@
 
 #include <cassert>
 
+#include "base/no_destructor.h"
+
 namespace zxcvbn {
 
 namespace util {
@@ -32,7 +34,10 @@ std::string reverse_string(const std::string & in) {
   return conv.to_bytes(ret);
 }
 
-const std::codecvt_utf8<char32_t> char32_conv;
+const std::codecvt_utf8<char32_t>& char32_conv() {
+  static base::NoDestructor<std::codecvt_utf8<char32_t>> char32_conv;
+  return *char32_conv;
+}
 
 bool utf8_valid(std::string::const_iterator start,
                 std::string::const_iterator end) {
@@ -46,8 +51,8 @@ bool utf8_valid(std::string::const_iterator start,
     char32_t new_char;
     char32_t *to_next;
 
-    auto res = char32_conv.in(st, from, from_end, from_next,
-                              &new_char, &new_char + 1, to_next);
+    auto res = char32_conv().in(st, from, from_end, from_next, &new_char,
+                                &new_char + 1, to_next);
     if (!((res == std::codecvt_utf8<char32_t>::result::partial &&
            from_next != from_end) ||
           (res == std::codecvt_utf8<char32_t>::result::ok &&
@@ -67,7 +72,7 @@ template<class It>
 It _utf8_iter(It start, It end) {
   assert(start != end);
   std::mbstate_t st;
-  auto amt = char32_conv.length(st, &*start, &*end, 1);
+  auto amt = char32_conv().length(st, &*start, &*end, 1);
   return start + amt;
 }
 
@@ -110,8 +115,8 @@ std::pair<char32_t, It> _utf8_decode(It it, It end) {
   const char *from = &*it;
   const char *from_end = &*end;
   const char *from_next;
-  auto res = char32_conv.in(st, from, from_end, from_next,
-                            &new_char, &new_char + 1, to_next);
+  auto res = char32_conv().in(st, from, from_end, from_next, &new_char,
+                              &new_char + 1, to_next);
   assert((res == std::codecvt_utf8<char32_t>::result::partial &&
           from_next != from_end) ||
          (res == std::codecvt_utf8<char32_t>::result::ok &&
