From da73178171a85a38d9b739038d189a00fed99f3f Mon Sep 17 00:00:00 2001
From: RahulGautamSingh <rahultesnik@gmail.com>
Date: Wed, 20 Oct 2021 10:23:49 +0545
Subject: [PATCH] fix: refactor regex to use re2 (#12216)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
---
 lib/manager/ansible-galaxy/collections.ts     |  10 +-
 lib/manager/ansible-galaxy/extract.ts         |   9 +-
 lib/manager/ansible-galaxy/roles.ts           |   7 +-
 lib/manager/ansible-galaxy/util.ts            |  12 +-
 lib/manager/ansible/extract.ts                |   3 +-
 lib/manager/argocd/util.ts                    |   9 +-
 lib/manager/batect-wrapper/extract.ts         |   3 +-
 lib/manager/bazel/extract.ts                  |  36 +++---
 lib/manager/bazel/update.ts                   |  28 ++---
 lib/manager/buildkite/extract.ts              |  14 ++-
 lib/manager/bundler/artifacts.ts              |   7 +-
 lib/manager/bundler/extract.ts                |  29 ++---
 lib/manager/bundler/locked-version.ts         |   2 +-
 lib/manager/cake/index.ts                     |  11 +-
 lib/manager/cargo/artifacts.ts                |   3 +-
 lib/manager/cdnurl/extract.ts                 |   6 +-
 lib/manager/circleci/extract.ts               |   9 +-
 lib/manager/cocoapods/artifacts.ts            |   5 +-
 lib/manager/cocoapods/extract.ts              |  26 ++---
 lib/manager/composer/artifacts.ts             |   3 +-
 lib/manager/composer/extract.ts               |   7 +-
 lib/manager/deps-edn/extract.ts               |   5 +-
 lib/manager/docker-compose/extract.ts         |   3 +-
 lib/manager/dockerfile/extract.ts             |   7 +-
 lib/manager/droneci/extract.ts                |   3 +-
 lib/manager/git-submodules/extract.ts         |  11 +-
 lib/manager/github-actions/extract.ts         |  10 +-
 lib/manager/gitlabci-include/extract.ts       |   5 +-
 lib/manager/gitlabci/extract.ts               |  17 ++-
 lib/manager/gomod/artifacts.ts                |  13 ++-
 lib/manager/gomod/extract.ts                  |  14 ++-
 lib/manager/gomod/update.ts                   |  11 +-
 .../gradle/deep/gradle-updates-report.ts      |   6 +-
 lib/manager/gradle/shallow/tokenizer.ts       |  21 ++--
 lib/manager/gradle/shallow/utils.ts           |   2 +-
 lib/manager/helm-values/util.ts               |   3 +-
 lib/manager/helmfile/extract.ts               |   3 +-
 lib/manager/helmv3/update.ts                  |   2 +-
 lib/manager/homebrew/extract.ts               |   7 +-
 lib/manager/html/extract.ts                   |   7 +-
 lib/manager/jenkins/extract.ts                |   8 +-
 lib/manager/kubernetes/extract.ts             |   6 +-
 lib/manager/kustomize/extract.ts              |   6 +-
 lib/manager/leiningen/extract.ts              |  24 ++--
 lib/manager/maven/extract.ts                  |  30 ++---
 lib/manager/meteor/extract.ts                 |   7 +-
 lib/manager/mix/extract.ts                    |   8 +-
 lib/manager/npm/extract/index.ts              |  22 ++--
 lib/manager/npm/extract/pnpm.ts               |   2 +-
 lib/manager/npm/post-update/index.ts          |   7 +-
 lib/manager/npm/post-update/node-version.ts   |   3 +-
 lib/manager/npm/post-update/rules.ts          |   3 +-
 lib/manager/npm/post-update/yarn.ts           |   3 +-
 .../locked-dependency/dep-constraints.ts      |   3 +-
 .../npm/update/package-version/index.ts       |   2 +-
 lib/manager/nuget/artifacts.ts                |   3 +-
 lib/manager/nuget/extract.ts                  |   2 +-
 lib/manager/nuget/util.ts                     |   3 +-
 lib/manager/pip-compile/artifacts.ts          |   3 +-
 lib/manager/pip_requirements/artifacts.ts     |   3 +-
 lib/manager/pip_requirements/extract.ts       |  17 ++-
 lib/manager/pip_setup/extract.ts              |   5 +-
 lib/manager/pipenv/extract.ts                 |   7 +-
 lib/manager/pre-commit/extract.ts             |   4 +-
 lib/manager/sbt/extract.ts                    | 110 ++++++++++--------
 lib/manager/sbt/update.ts                     |   3 +-
 lib/manager/setup-cfg/extract.ts              |  11 +-
 lib/manager/swift/extract.ts                  |  35 +++---
 lib/manager/terraform/extract.ts              |   6 +-
 lib/manager/terraform/lockfile/hash.ts        |   2 +-
 lib/manager/terraform/lockfile/util.ts        |   8 +-
 lib/manager/terraform/modules.ts              |  15 ++-
 lib/manager/terraform/providers.ts            |  11 +-
 lib/manager/terraform/required-providers.ts   |   3 +-
 lib/manager/terraform/required-version.ts     |   4 +-
 lib/manager/terraform/util.ts                 |  13 ++-
 lib/manager/terragrunt/extract.ts             |   3 +-
 lib/manager/terragrunt/modules.ts             |  15 ++-
 lib/manager/terragrunt/providers.ts           |   6 +-
 lib/manager/terragrunt/util.ts                |   5 +-
 lib/platform/azure/index.ts                   |   3 +-
 lib/platform/bitbucket-server/index.ts        |  11 +-
 lib/platform/bitbucket/index.ts               |  13 ++-
 lib/platform/gitea/utils.ts                   |   4 +-
 lib/platform/github/index.ts                  |  16 ++-
 lib/platform/github/massage-markdown-links.ts |   5 +-
 lib/platform/gitlab/index.ts                  |  17 ++-
 lib/platform/utils/read-only-issue-body.ts    |   6 +-
 88 files changed, 519 insertions(+), 376 deletions(-)

diff --git a/lib/manager/ansible-galaxy/collections.ts b/lib/manager/ansible-galaxy/collections.ts
index 87072e3e34..a15ee60d9f 100644
--- a/lib/manager/ansible-galaxy/collections.ts
+++ b/lib/manager/ansible-galaxy/collections.ts
@@ -2,6 +2,7 @@ import { GalaxyCollectionDatasource } from '../../datasource/galaxy-collection';
 import * as datasourceGitTags from '../../datasource/git-tags';
 import * as datasourceGithubTags from '../../datasource/github-tags';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import {
   blockLineRegEx,
@@ -17,7 +18,7 @@ function interpretLine(
 ): void {
   const localDependency = dependency;
   const key = lineMatch[2];
-  const value = lineMatch[3].replace(/["']/g, '');
+  const value = lineMatch[3].replace(regEx(/["']/g), '');
   switch (key) {
     case 'name': {
       localDependency.managerData.name = value;
@@ -60,10 +61,13 @@ function handleGitDep(
     }
     // source definition without version appendix
     const source = nameMatch.groups.source;
-    const massagedDepName = nameMatch.groups.depName.replace(/.git$/, '');
+    const massagedDepName = nameMatch.groups.depName.replace(
+      regEx(/.git$/),
+      ''
+    );
     dep.depName = `${nameMatch.groups.hostname}/${massagedDepName}`;
     // remove leading `git+` from URLs like `git+https://...`
-    dep.lookupName = source.replace(/git\+/, '');
+    dep.lookupName = source.replace(regEx(/git\+/), '');
 
     // if version is declared using version appendix `<source url>,v1.2.0`, use it
     if (nameMatch.groups.version) {
diff --git a/lib/manager/ansible-galaxy/extract.ts b/lib/manager/ansible-galaxy/extract.ts
index fc270adddd..bd010432a5 100644
--- a/lib/manager/ansible-galaxy/extract.ts
+++ b/lib/manager/ansible-galaxy/extract.ts
@@ -1,4 +1,5 @@
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import { extractCollections } from './collections';
 import { extractCollectionsMetaDataFile } from './collections-metadata';
@@ -26,7 +27,7 @@ export default function extractPackageFile(
   fileName: string
 ): PackageFile | null {
   logger.trace('ansible-galaxy.extractPackageFile()');
-  const galaxyFileNameRegEx = /galaxy\.ya?ml$/;
+  const galaxyFileNameRegEx = regEx(/galaxy\.ya?ml$/);
   const deps: PackageDependency[] = [];
   const lines = content.split('\n');
 
@@ -44,10 +45,12 @@ export default function extractPackageFile(
       };
       // find role and collection block
       lines.forEach((line, index) => {
-        if (/^collections:/.exec(line)) {
+        if (regEx(/^collections:/).exec(line)) {
+          // TODO #12071
           positions.collections = index;
         }
-        if (/^roles:/.exec(line)) {
+        if (regEx(/^roles:/).exec(line)) {
+          // TODO #12071
           positions.roles = index;
         }
       });
diff --git a/lib/manager/ansible-galaxy/roles.ts b/lib/manager/ansible-galaxy/roles.ts
index a1e73e548d..21b3f9646e 100644
--- a/lib/manager/ansible-galaxy/roles.ts
+++ b/lib/manager/ansible-galaxy/roles.ts
@@ -1,6 +1,7 @@
 import { GalaxyDatasource } from '../../datasource/galaxy';
 import * as datasourceGitTags from '../../datasource/git-tags';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import {
   blockLineRegEx,
@@ -16,7 +17,7 @@ function interpretLine(
 ): PackageDependency {
   const localDependency: PackageDependency = dependency;
   const key = lineMatch[2];
-  const value = lineMatch[3].replace(/["']/g, '');
+  const value = lineMatch[3].replace(regEx(/["']/g), '');
   switch (key) {
     case 'name': {
       localDependency.managerData.name = value;
@@ -54,9 +55,9 @@ function finalize(dependency: PackageDependency): boolean {
   const sourceMatch = nameMatchRegex.exec(source);
   if (sourceMatch) {
     dep.datasource = datasourceGitTags.id;
-    dep.depName = sourceMatch.groups.depName.replace(/.git$/, '');
+    dep.depName = sourceMatch.groups.depName.replace(regEx(/.git$/), '');
     // remove leading `git+` from URLs like `git+https://...`
-    dep.lookupName = source.replace(/git\+/, '');
+    dep.lookupName = source.replace(regEx(/git\+/), '');
   } else if (galaxyDepRegex.exec(source)) {
     dep.datasource = GalaxyDatasource.id;
     dep.depName = dep.managerData.src;
diff --git a/lib/manager/ansible-galaxy/util.ts b/lib/manager/ansible-galaxy/util.ts
index b0b57d19d0..e88be41652 100644
--- a/lib/manager/ansible-galaxy/util.ts
+++ b/lib/manager/ansible-galaxy/util.ts
@@ -1,8 +1,12 @@
+import { regEx } from '../../util/regex';
+
 export const newBlockRegEx = /^\s*-\s*((\w+):\s*(.*))$/;
 export const blockLineRegEx = /^\s*((\w+):\s*(.*))$/;
 export const galaxyDepRegex = /[\w-]+\.[\w-]+/;
 export const dependencyRegex = /^dependencies:/;
-export const galaxyRegEx =
-  /^\s+(?<lookupName>[\w.]+):\s*["'](?<version>.+)["']\s*/;
-export const nameMatchRegex =
-  /(?<source>((git\+)?(?:(git|ssh|https?):\/\/)?(.*@)?(?<hostname>[\w.-]+)(?:(:\d+)?\/|:))(?<depName>[\w./-]+)(?:\.git)?)(,(?<version>[\w.]*))?/;
+export const galaxyRegEx = regEx(
+  /^\s+(?<lookupName>[\w.]+):\s*["'](?<version>.+)["']\s*/
+);
+export const nameMatchRegex = regEx(
+  /(?<source>((git\+)?(?:(git|ssh|https?):\/\/)?(.*@)?(?<hostname>[\w.-]+)(?:(:\d+)?\/|:))(?<depName>[\w./-]+)(?:\.git)?)(,(?<version>[\w.]*))?/
+);
diff --git a/lib/manager/ansible/extract.ts b/lib/manager/ansible/extract.ts
index b97d032fdf..4ee13ef36f 100644
--- a/lib/manager/ansible/extract.ts
+++ b/lib/manager/ansible/extract.ts
@@ -1,4 +1,5 @@
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import * as dockerVersioning from '../../versioning/docker';
 import { getDep } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
@@ -8,7 +9,7 @@ export default function extractPackageFile(
 ): PackageFile | null {
   logger.trace('ansible.extractPackageFile()');
   let deps: PackageDependency[] = [];
-  const re = /^\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/;
+  const re = regEx(/^\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/);
   for (const line of content.split('\n')) {
     const match = re.exec(line);
     if (match) {
diff --git a/lib/manager/argocd/util.ts b/lib/manager/argocd/util.ts
index 13c7146055..31939dc1c8 100644
--- a/lib/manager/argocd/util.ts
+++ b/lib/manager/argocd/util.ts
@@ -1,4 +1,7 @@
-export const keyValueExtractionRegex =
-  /^\s*(?<key>[^\s]+):\s+"?(?<value>[^"\s]+)"?\s*$/;
+import { regEx } from '../../util/regex';
+
+export const keyValueExtractionRegex = regEx(
+  /^\s*(?<key>[^\s]+):\s+"?(?<value>[^"\s]+)"?\s*$/
+);
 // looks for `apiVersion: argoproj.io/
-export const fileTestRegex = /\s*apiVersion:\s*argoproj.io\/\s*/;
+export const fileTestRegex = regEx(/\s*apiVersion:\s*argoproj.io\/\s*/);
diff --git a/lib/manager/batect-wrapper/extract.ts b/lib/manager/batect-wrapper/extract.ts
index a4366eac93..3738893207 100644
--- a/lib/manager/batect-wrapper/extract.ts
+++ b/lib/manager/batect-wrapper/extract.ts
@@ -1,9 +1,10 @@
 import { id as githubReleaseDatasource } from '../../datasource/github-releases';
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import { id as semverVersioning } from '../../versioning/semver';
 import type { PackageDependency, PackageFile } from '../types';
 
-const VERSION_REGEX = /^\s+VERSION="(.*)"$/m;
+const VERSION_REGEX = regEx(/^\s+VERSION="(.*)"$/m);
 
 export function extractPackageFile(fileContent: string): PackageFile | null {
   logger.trace('batect.extractPackageFile()');
diff --git a/lib/manager/bazel/extract.ts b/lib/manager/bazel/extract.ts
index 1b0782ef59..123f54d75f 100644
--- a/lib/manager/bazel/extract.ts
+++ b/lib/manager/bazel/extract.ts
@@ -8,6 +8,7 @@ import * as datasourceGithubTags from '../../datasource/github-tags';
 import * as datasourceGo from '../../datasource/go';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import * as dockerVersioning from '../../versioning/docker';
 import type { PackageDependency, PackageFile } from '../types';
 import type { UrlParsedResult } from './types';
@@ -50,7 +51,7 @@ function parseUrl(urlString: string): UrlParsedResult | null {
 
 const lexer = moo.states({
   main: {
-    lineComment: { match: /#.*?$/ },
+    lineComment: { match: /#.*?$/ }, // TODO #12070
     leftParen: { match: '(' },
     rightParen: { match: ')' },
     longDoubleQuoted: {
@@ -178,48 +179,48 @@ export function extractPackageFile(
     let digest: string;
     let repository: string;
     let registry: string;
-    let match = /name\s*=\s*"([^"]+)"/.exec(def);
+    let match = regEx(/name\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, depName] = match;
     }
-    match = /digest\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/digest\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, digest] = match;
     }
-    match = /registry\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/registry\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, registry] = match;
     }
-    match = /repository\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/repository\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, repository] = match;
     }
-    match = /remote\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/remote\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, remote] = match;
     }
-    match = /tag\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/tag\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, currentValue] = match;
     }
-    match = /url\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/url\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, url] = match;
     }
-    match = /urls\s*=\s*\[\s*"([^\]]+)",?\s*\]/.exec(def);
+    match = regEx(/urls\s*=\s*\[\s*"([^\]]+)",?\s*\]/).exec(def);
     if (match) {
-      const urls = match[1].replace(/\s/g, '').split('","');
+      const urls = match[1].replace(regEx(/\s/g), '').split('","');
       url = urls.find(parseUrl);
     }
-    match = /commit\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/commit\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, commit] = match;
     }
-    match = /sha256\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/sha256\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, sha256] = match;
     }
-    match = /importpath\s*=\s*"([^"]+)"/.exec(def);
+    match = regEx(/importpath\s*=\s*"([^"]+)"/).exec(def);
     if (match) {
       [, importpath] = match;
     }
@@ -256,10 +257,9 @@ export function extractPackageFile(
       dep.datasource = datasourceGo.id;
       dep.lookupName = importpath;
       if (remote) {
-        const remoteMatch =
-          /https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/.exec(
-            remote
-          );
+        const remoteMatch = regEx(
+          /https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/
+        ).exec(remote);
         if (remoteMatch && remoteMatch[0].length === remote.length) {
           dep.lookupName = remote.replace('https://', '');
         } else {
@@ -282,7 +282,7 @@ export function extractPackageFile(
       const parsedUrl = parseUrl(url);
       dep.depName = depName;
       dep.repo = parsedUrl.repo;
-      if (/^[a-f0-9]{40}$/i.test(parsedUrl.currentValue)) {
+      if (regEx(/^[a-f0-9]{40}$/i).test(parsedUrl.currentValue)) {
         dep.currentDigest = parsedUrl.currentValue;
       } else {
         dep.currentValue = parsedUrl.currentValue;
diff --git a/lib/manager/bazel/update.ts b/lib/manager/bazel/update.ts
index c08beb7df6..2e40e88468 100644
--- a/lib/manager/bazel/update.ts
+++ b/lib/manager/bazel/update.ts
@@ -12,8 +12,8 @@ function updateWithNewVersion(
   currentValue: string,
   newValue: string
 ): string {
-  const replaceFrom = currentValue.replace(/^v/, '');
-  const replaceTo = newValue.replace(/^v/, '');
+  const replaceFrom = currentValue.replace(regEx(/^v/), '');
+  const replaceTo = newValue.replace(regEx(/^v/), '');
   let newContent = content;
   do {
     newContent = newContent.replace(replaceFrom, replaceTo);
@@ -22,7 +22,7 @@ function updateWithNewVersion(
 }
 
 function extractUrl(flattened: string): string[] | null {
-  const urlMatch = /url="(.*?)"/.exec(flattened);
+  const urlMatch = regEx(/url="(.*?)"/).exec(flattened);
   if (!urlMatch) {
     logger.debug('Cannot locate urls in new definition');
     return null;
@@ -31,16 +31,16 @@ function extractUrl(flattened: string): string[] | null {
 }
 
 function extractUrls(content: string): string[] | null {
-  const flattened = content.replace(/\n/g, '').replace(/\s/g, '');
-  const urlsMatch = /urls?=\[.*?\]/.exec(flattened);
+  const flattened = content.replace(regEx(/\n/g), '').replace(regEx(/\s/g), '');
+  const urlsMatch = regEx(/urls?=\[.*?\]/).exec(flattened);
   if (!urlsMatch) {
     return extractUrl(flattened);
   }
   const urls = urlsMatch[0]
-    .replace(/urls?=\[/, '')
-    .replace(/,?\]$/, '')
+    .replace(regEx(/urls?=\[/), '')
+    .replace(regEx(/,?\]$/), '')
     .split(',')
-    .map((url) => url.replace(/"/g, ''));
+    .map((url) => url.replace(regEx(/"/g), ''));
   return urls;
 }
 
@@ -83,7 +83,7 @@ async function getHashFromUrls(urls: string[]): Promise<string | null> {
 }
 
 function setNewHash(content: string, hash: string): string {
-  return content.replace(/(sha256\s*=\s*)"[^"]+"/, `$1"${hash}"`);
+  return content.replace(regEx(/(sha256\s*=\s*)"[^"]+"/), `$1"${hash}"`);
 }
 
 export async function updateDependency({
@@ -97,19 +97,19 @@ export async function updateDependency({
     let newDef: string;
     if (upgrade.depType === 'container_pull') {
       newDef = upgrade.managerData.def
-        .replace(/(tag\s*=\s*)"[^"]+"/, `$1"${upgrade.newValue}"`)
-        .replace(/(digest\s*=\s*)"[^"]+"/, `$1"${upgrade.newDigest}"`);
+        .replace(regEx(/(tag\s*=\s*)"[^"]+"/), `$1"${upgrade.newValue}"`)
+        .replace(regEx(/(digest\s*=\s*)"[^"]+"/), `$1"${upgrade.newDigest}"`);
     }
     if (
       upgrade.depType === 'git_repository' ||
       upgrade.depType === 'go_repository'
     ) {
       newDef = upgrade.managerData.def
-        .replace(/(tag\s*=\s*)"[^"]+"/, `$1"${upgrade.newValue}"`)
-        .replace(/(commit\s*=\s*)"[^"]+"/, `$1"${upgrade.newDigest}"`);
+        .replace(regEx(/(tag\s*=\s*)"[^"]+"/), `$1"${upgrade.newValue}"`)
+        .replace(regEx(/(commit\s*=\s*)"[^"]+"/), `$1"${upgrade.newDigest}"`);
       if (upgrade.currentDigest && upgrade.updateType !== 'digest') {
         newDef = newDef.replace(
-          /(commit\s*=\s*)"[^"]+".*?\n/,
+          regEx(/(commit\s*=\s*)"[^"]+".*?\n/),
           `$1"${upgrade.newDigest}",  # ${upgrade.newValue}\n`
         );
       }
diff --git a/lib/manager/buildkite/extract.ts b/lib/manager/buildkite/extract.ts
index 0dc99d9391..2c4ae344b5 100644
--- a/lib/manager/buildkite/extract.ts
+++ b/lib/manager/buildkite/extract.ts
@@ -1,6 +1,7 @@
 import * as datasourceGithubTags from '../../datasource/github-tags';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import { isVersion } from '../../versioning/semver';
 import type { PackageDependency, PackageFile } from '../types';
 
@@ -13,16 +14,21 @@ export function extractPackageFile(content: string): PackageFile | null {
     for (let lineNumber = 1; lineNumber <= lines.length; lineNumber += 1) {
       const lineIdx = lineNumber - 1;
       const line = lines[lineIdx];
-      const pluginsSection = /^(?<pluginsIndent>\s*)(-?\s*)plugins:/.exec(line);
+      const pluginsSection = regEx(
+        /^(?<pluginsIndent>\s*)(-?\s*)plugins:/
+      ).exec(line); // TODO #12071
       if (pluginsSection) {
         logger.trace(`Matched plugins on line ${lineNumber}`);
         isPluginsSection = true;
         pluginsIndent = pluginsSection.groups.pluginsIndent;
       } else if (isPluginsSection) {
         logger.debug(`serviceImageLine: "${line}"`);
-        const { currentIndent } = /^(?<currentIndent>\s*)/.exec(line).groups;
-        const depLineMatch =
-          /^\s+(?:-\s+)?(?<depName>[^#]+)#(?<currentValue>[^:]+)/.exec(line);
+        const { currentIndent } = regEx(/^(?<currentIndent>\s*)/).exec(
+          line
+        ).groups; // TODO #12071
+        const depLineMatch = regEx(
+          /^\s+(?:-\s+)?(?<depName>[^#]+)#(?<currentValue>[^:]+)/
+        ).exec(line); // TODO #12071
         if (currentIndent.length <= pluginsIndent.length) {
           isPluginsSection = false;
           pluginsIndent = '';
diff --git a/lib/manager/bundler/artifacts.ts b/lib/manager/bundler/artifacts.ts
index e99063850f..f4d4860d0d 100644
--- a/lib/manager/bundler/artifacts.ts
+++ b/lib/manager/bundler/artifacts.ts
@@ -16,6 +16,7 @@ import {
   writeLocalFile,
 } from '../../util/fs';
 import { getRepoStatus } from '../../util/git';
+import { regEx } from '../../util/regex';
 import { add } from '../../util/sanitize';
 import { isValid } from '../../versioning/ruby';
 import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
@@ -46,8 +47,8 @@ async function getRubyConstraint(
     if (rubyVersionFileContent) {
       logger.debug('Using ruby version specified in .ruby-version');
       rubyConstraint = rubyVersionFileContent
-        .replace(/^ruby-/, '')
-        .replace(/\n/g, '')
+        .replace(regEx(/^ruby-/), '')
+        .replace(regEx(/\n/g), '')
         .trim();
     }
   }
@@ -234,7 +235,7 @@ export async function updateArtifacts(
       memCache.set('bundlerArtifactsError', BUNDLER_INVALID_CREDENTIALS);
       throw new Error(BUNDLER_INVALID_CREDENTIALS);
     }
-    const resolveMatchRe = new RegExp('\\s+(.*) was resolved to', 'g');
+    const resolveMatchRe = regEx('\\s+(.*) was resolved to', 'g');
     if (output.match(resolveMatchRe) && !config.isLockFileMaintenance) {
       logger.debug({ err }, 'Bundler has a resolve error');
       const resolveMatches = [];
diff --git a/lib/manager/bundler/extract.ts b/lib/manager/bundler/extract.ts
index a9cd7ca5fd..19b5fe5c5d 100644
--- a/lib/manager/bundler/extract.ts
+++ b/lib/manager/bundler/extract.ts
@@ -23,6 +23,7 @@ export async function extractPackageFile(
       sourceMatch =
         sourceMatch ||
         regEx(`^source ${delimiter}([^${delimiter}]+)${delimiter}\\s*$`).exec(
+          // TODO #12071
           line
         );
     }
@@ -33,13 +34,13 @@ export async function extractPackageFile(
     for (const delimiter of delimiters) {
       rubyMatch =
         rubyMatch ||
-        regEx(`^ruby ${delimiter}([^${delimiter}]+)${delimiter}`).exec(line);
+        regEx(`^ruby ${delimiter}([^${delimiter}]+)${delimiter}`).exec(line); // TODO #12071
     }
     if (rubyMatch) {
       res.constraints = { ruby: rubyMatch[1] };
     }
     const gemMatchRegex =
-      /^\s*gem\s+(['"])(?<depName>[^'"]+)\1(\s*,\s*(?<currentValue>(['"])[^'"]+\5(\s*,\s*\5[^'"]+\5)?))?/;
+      /^\s*gem\s+(['"])(?<depName>[^'"]+)\1(\s*,\s*(?<currentValue>(['"])[^'"]+\5(\s*,\s*\5[^'"]+\5)?))?/; // TODO #12070 #12071
     const gemMatch = gemMatchRegex.exec(line);
     if (gemMatch) {
       const dep: PackageDependency = {
@@ -48,7 +49,7 @@ export async function extractPackageFile(
       };
       if (gemMatch.groups.currentValue) {
         const currentValue = gemMatch.groups.currentValue;
-        dep.currentValue = /\s*,\s*/.test(currentValue)
+        dep.currentValue = regEx(/\s*,\s*/).test(currentValue) // TODO #12071
           ? currentValue
           : currentValue.slice(1, -1);
       } else {
@@ -59,12 +60,12 @@ export async function extractPackageFile(
       }
       res.deps.push(dep);
     }
-    const groupMatch = /^group\s+(.*?)\s+do/.exec(line);
+    const groupMatch = regEx(/^group\s+(.*?)\s+do/).exec(line); // TODO #12071
     if (groupMatch) {
       const depTypes = groupMatch[1]
         .split(',')
         .map((group) => group.trim())
-        .map((group) => group.replace(/^:/, ''));
+        .map((group) => group.replace(regEx(/^:/), '')); // TODO #12071
       const groupLineNumber = lineNumber;
       let groupContent = '';
       let groupLine = '';
@@ -72,7 +73,7 @@ export async function extractPackageFile(
         lineNumber += 1;
         groupLine = lines[lineNumber];
         if (groupLine !== 'end') {
-          groupContent += (groupLine || '').replace(/^ {2}/, '') + '\n';
+          groupContent += (groupLine || '').replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
         }
       }
       const groupRes = await extractPackageFile(groupContent);
@@ -91,7 +92,7 @@ export async function extractPackageFile(
     }
     for (const delimiter of delimiters) {
       const sourceBlockMatch = regEx(
-        `^source\\s+${delimiter}(.*?)${delimiter}\\s+do`
+        `^source\\s+${delimiter}(.*?)${delimiter}\\s+do` // TODO #12071
       ).exec(line);
       if (sourceBlockMatch) {
         const repositoryUrl = sourceBlockMatch[1];
@@ -107,7 +108,7 @@ export async function extractPackageFile(
             sourceLine = 'end';
           }
           if (sourceLine !== 'end') {
-            sourceContent += sourceLine.replace(/^ {2}/, '') + '\n';
+            sourceContent += sourceLine.replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
           }
         }
         const sourceRes = await extractPackageFile(sourceContent);
@@ -125,7 +126,7 @@ export async function extractPackageFile(
         }
       }
     }
-    const platformsMatch = /^platforms\s+(.*?)\s+do/.test(line);
+    const platformsMatch = regEx(/^platforms\s+(.*?)\s+do/).test(line); // TODO #12071
     if (platformsMatch) {
       const platformsLineNumber = lineNumber;
       let platformsContent = '';
@@ -134,7 +135,7 @@ export async function extractPackageFile(
         lineNumber += 1;
         platformsLine = lines[lineNumber];
         if (platformsLine !== 'end') {
-          platformsContent += platformsLine.replace(/^ {2}/, '') + '\n';
+          platformsContent += platformsLine.replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
         }
       }
       const platformsRes = await extractPackageFile(platformsContent);
@@ -151,7 +152,7 @@ export async function extractPackageFile(
         );
       }
     }
-    const ifMatch = /^if\s+(.*?)/.test(line);
+    const ifMatch = regEx(/^if\s+(.*?)/).test(line); // TODO #12071
     if (ifMatch) {
       const ifLineNumber = lineNumber;
       let ifContent = '';
@@ -160,7 +161,7 @@ export async function extractPackageFile(
         lineNumber += 1;
         ifLine = lines[lineNumber];
         if (ifLine !== 'end') {
-          ifContent += ifLine.replace(/^ {2}/, '') + '\n';
+          ifContent += ifLine.replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
         }
       }
       const ifRes = await extractPackageFile(ifContent);
@@ -194,7 +195,9 @@ export async function extractPackageFile(
           dep.lockedVersion = lockedDepValue;
         }
       }
-      const bundledWith = /\nBUNDLED WITH\n\s+(.*?)(\n|$)/.exec(lockContent);
+      const bundledWith = regEx(/\nBUNDLED WITH\n\s+(.*?)(\n|$)/).exec(
+        lockContent
+      );
       if (bundledWith) {
         res.constraints = res.constraints || {};
         res.constraints.bundler = bundledWith[1];
diff --git a/lib/manager/bundler/locked-version.ts b/lib/manager/bundler/locked-version.ts
index 49bec3d29f..ca9e477284 100644
--- a/lib/manager/bundler/locked-version.ts
+++ b/lib/manager/bundler/locked-version.ts
@@ -1,7 +1,7 @@
 import { logger } from '../../logger';
 import { isVersion } from '../../versioning/ruby';
 
-const DEP_REGEX = new RegExp('(?<=\\().*(?=\\))');
+const DEP_REGEX = new RegExp('(?<=\\().*(?=\\))'); // TODO #12070
 export function extractLockFileEntries(
   lockFileContent: string
 ): Map<string, string> {
diff --git a/lib/manager/cake/index.ts b/lib/manager/cake/index.ts
index 8f15b921ba..c469a3e29f 100644
--- a/lib/manager/cake/index.ts
+++ b/lib/manager/cake/index.ts
@@ -2,6 +2,7 @@ import moo from 'moo';
 import { ProgrammingLanguage } from '../../constants';
 import { id as datasource } from '../../datasource/nuget';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import { PackageDependency, PackageFile } from '../types';
 
 export const language = ProgrammingLanguage.NET;
@@ -12,13 +13,13 @@ export const defaultConfig = {
 
 const lexer = moo.states({
   main: {
-    lineComment: { match: /\/\/.*?$/ },
-    multiLineComment: { match: /\/\*[^]*?\*\//, lineBreaks: true },
+    lineComment: { match: /\/\/.*?$/ }, // TODO #12070
+    multiLineComment: { match: /\/\*[^]*?\*\//, lineBreaks: true }, // TODO #12070
     dependency: {
-      match: /^#(?:addin|tool|module|load|l)\s+(?:nuget|dotnet):.*$/,
+      match: /^#(?:addin|tool|module|load|l)\s+(?:nuget|dotnet):.*$/, // TODO #12070
     },
     dependencyQuoted: {
-      match: /^#(?:addin|tool|module|load|l)\s+"(?:nuget|dotnet):[^"]+"\s*$/,
+      match: /^#(?:addin|tool|module|load|l)\s+"(?:nuget|dotnet):[^"]+"\s*$/, // TODO #12070
       value: (s: string) => s.trim().slice(1, -1),
     },
     unknown: moo.fallback,
@@ -27,7 +28,7 @@ const lexer = moo.states({
 
 function parseDependencyLine(line: string): PackageDependency | null {
   try {
-    let url = line.replace(/^[^:]*:/, '');
+    let url = line.replace(regEx(/^[^:]*:/), '');
     const isEmptyHost = url.startsWith('?');
     url = isEmptyHost ? `http://localhost/${url}` : url;
 
diff --git a/lib/manager/cargo/artifacts.ts b/lib/manager/cargo/artifacts.ts
index 02a3562dc7..6898b9d4b9 100644
--- a/lib/manager/cargo/artifacts.ts
+++ b/lib/manager/cargo/artifacts.ts
@@ -7,6 +7,7 @@ import {
   readLocalFile,
   writeLocalFile,
 } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
 
 async function cargoUpdate(
@@ -39,7 +40,7 @@ async function cargoUpdate(
     // by the outer try { } catch {} and processed normally.
     const msgStart = 'error: There are multiple';
     if (err.code === 101 && err.stderr.startsWith(msgStart)) {
-      cmd = cmd.replace(/ --package.*/, '');
+      cmd = cmd.replace(regEx(/ --package.*/), '');
       await exec(cmd, execOptions);
     } else {
       throw err; // this is caught below
diff --git a/lib/manager/cdnurl/extract.ts b/lib/manager/cdnurl/extract.ts
index 650ea66067..16df9bf6c3 100644
--- a/lib/manager/cdnurl/extract.ts
+++ b/lib/manager/cdnurl/extract.ts
@@ -1,8 +1,10 @@
 import { CdnJsDatasource } from '../../datasource/cdnjs';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 
-export const cloudflareUrlRegex =
-  /\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/(?<depName>[^/]+?)\/(?<currentValue>[^/]+?)\/(?<asset>[-/_.a-zA-Z0-9]+)/;
+export const cloudflareUrlRegex = regEx(
+  /\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/(?<depName>[^/]+?)\/(?<currentValue>[^/]+?)\/(?<asset>[-/_.a-zA-Z0-9]+)/
+);
 
 export function extractPackageFile(content: string): PackageFile {
   const deps: PackageDependency[] = [];
diff --git a/lib/manager/circleci/extract.ts b/lib/manager/circleci/extract.ts
index 0ffe5ce1ea..5b76e9cd3e 100644
--- a/lib/manager/circleci/extract.ts
+++ b/lib/manager/circleci/extract.ts
@@ -1,5 +1,6 @@
 import { OrbDatasource } from '../../datasource/orb';
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import * as npmVersioning from '../../versioning/npm';
 import { getDep } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
@@ -10,7 +11,7 @@ export function extractPackageFile(content: string): PackageFile | null {
     const lines = content.split('\n');
     for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
       const line = lines[lineNumber];
-      const orbs = /^\s*orbs:\s*$/.exec(line);
+      const orbs = regEx(/^\s*orbs:\s*$/).exec(line); // TODO #12071
       if (orbs) {
         logger.trace(`Matched orbs on line ${lineNumber}`);
         let foundOrbOrNoop: boolean;
@@ -18,14 +19,14 @@ export function extractPackageFile(content: string): PackageFile | null {
           foundOrbOrNoop = false;
           const orbLine = lines[lineNumber + 1];
           logger.trace(`orbLine: "${orbLine}"`);
-          const yamlNoop = /^\s*(#|$)/.exec(orbLine);
+          const yamlNoop = regEx(/^\s*(#|$)/).exec(orbLine); // TODO #12071
           if (yamlNoop) {
             logger.debug('orbNoop');
             foundOrbOrNoop = true;
             lineNumber += 1;
             continue; // eslint-disable-line no-continue
           }
-          const orbMatch = /^\s+([^:]+):\s(.+)$/.exec(orbLine);
+          const orbMatch = regEx(/^\s+([^:]+):\s(.+)$/).exec(orbLine); // TODO #12071
           if (orbMatch) {
             logger.trace('orbMatch');
             foundOrbOrNoop = true;
@@ -46,7 +47,7 @@ export function extractPackageFile(content: string): PackageFile | null {
           }
         } while (foundOrbOrNoop);
       }
-      const match = /^\s*-? image:\s*'?"?([^\s'"]+)'?"?\s*$/.exec(line);
+      const match = regEx(/^\s*-? image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); // TODO #12071
       if (match) {
         const currentFrom = match[1];
         const dep = getDep(currentFrom);
diff --git a/lib/manager/cocoapods/artifacts.ts b/lib/manager/cocoapods/artifacts.ts
index 247eea7dda..3fc124fa06 100644
--- a/lib/manager/cocoapods/artifacts.ts
+++ b/lib/manager/cocoapods/artifacts.ts
@@ -10,9 +10,10 @@ import {
   writeLocalFile,
 } from '../../util/fs';
 import { getRepoStatus } from '../../util/git';
+import { regEx } from '../../util/regex';
 import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
 
-const pluginRegex = /^\s*plugin\s*(['"])(?<plugin>[^'"]+)\1/;
+const pluginRegex = /^\s*plugin\s*(['"])(?<plugin>[^'"]+)\1/; // TODO #12070
 
 function getPluginCommands(content: string): string[] {
   const result = new Set<string>();
@@ -62,7 +63,7 @@ export async function updateArtifacts({
     return null;
   }
 
-  const match = new RegExp(/^COCOAPODS: (?<cocoapodsVersion>.*)$/m).exec(
+  const match = regEx(/^COCOAPODS: (?<cocoapodsVersion>.*)$/m).exec(
     existingLockFileContent
   );
   const tagConstraint = match?.groups?.cocoapodsVersion ?? null;
diff --git a/lib/manager/cocoapods/extract.ts b/lib/manager/cocoapods/extract.ts
index 9535e783fc..b170cd24f1 100644
--- a/lib/manager/cocoapods/extract.ts
+++ b/lib/manager/cocoapods/extract.ts
@@ -5,16 +5,17 @@ import * as datasourcePod from '../../datasource/pod';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { getSiblingFileName, localPathExists } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import type { ParsedLine } from './types';
 
 const regexMappings = [
-  /^\s*pod\s+(['"])(?<spec>[^'"/]+)(\/(?<subspec>[^'"]+))?\1/,
-  /^\s*pod\s+(['"])[^'"]+\1\s*,\s*(['"])(?<currentValue>[^'"]+)\2\s*$/,
-  /,\s*:git\s*=>\s*(['"])(?<git>[^'"]+)\1/,
-  /,\s*:tag\s*=>\s*(['"])(?<tag>[^'"]+)\1/,
-  /,\s*:path\s*=>\s*(['"])(?<path>[^'"]+)\1/,
-  /^\s*source\s*(['"])(?<source>[^'"]+)\1/,
+  /^\s*pod\s+(['"])(?<spec>[^'"/]+)(\/(?<subspec>[^'"]+))?\1/, // TODO #12070
+  /^\s*pod\s+(['"])[^'"]+\1\s*,\s*(['"])(?<currentValue>[^'"]+)\2\s*$/, // TODO #12070
+  /,\s*:git\s*=>\s*(['"])(?<git>[^'"]+)\1/, // TODO #12070
+  /,\s*:tag\s*=>\s*(['"])(?<tag>[^'"]+)\1/, // TODO #12070
+  /,\s*:path\s*=>\s*(['"])(?<path>[^'"]+)\1/, // TODO #12070
+  /^\s*source\s*(['"])(?<source>[^'"]+)\1/, // TODO #12070
 ];
 
 export function parseLine(line: string): ParsedLine {
@@ -23,7 +24,7 @@ export function parseLine(line: string): ParsedLine {
     return result;
   }
   for (const regex of Object.values(regexMappings)) {
-    const match = regex.exec(line.replace(/#.*$/, ''));
+    const match = regex.exec(line.replace(regEx(/#.*$/), '')); // TODO #12071
     if (match?.groups) {
       result = { ...result, ...match.groups };
     }
@@ -50,10 +51,9 @@ export function parseLine(line: string): ParsedLine {
 export function gitDep(parsedLine: ParsedLine): PackageDependency | null {
   const { depName, git, tag } = parsedLine;
 
-  const platformMatch =
-    /[@/](?<platform>github|gitlab)\.com[:/](?<account>[^/]+)\/(?<repo>[^/]+)/.exec(
-      git
-    );
+  const platformMatch = regEx(
+    /[@/](?<platform>github|gitlab)\.com[:/](?<account>[^/]+)\/(?<repo>[^/]+)/
+  ).exec(git);
 
   if (platformMatch) {
     const { account, repo, platform } = platformMatch?.groups || {};
@@ -65,7 +65,7 @@ export function gitDep(parsedLine: ParsedLine): PackageDependency | null {
       return {
         datasource,
         depName,
-        lookupName: `${account}/${repo.replace(/\.git$/, '')}`,
+        lookupName: `${account}/${repo.replace(regEx(/\.git$/), '')}`,
         currentValue: tag,
       };
     }
@@ -103,7 +103,7 @@ export async function extractPackageFile(
     }: ParsedLine = parsedLine;
 
     if (source) {
-      registryUrls.push(source.replace(/\/*$/, ''));
+      registryUrls.push(source.replace(regEx(/\/*$/), '')); // TODO #12071
     }
 
     if (depName) {
diff --git a/lib/manager/composer/artifacts.ts b/lib/manager/composer/artifacts.ts
index 0506e26c0e..f4493ab28f 100644
--- a/lib/manager/composer/artifacts.ts
+++ b/lib/manager/composer/artifacts.ts
@@ -19,6 +19,7 @@ import {
 } from '../../util/fs';
 import { getRepoStatus } from '../../util/git';
 import * as hostRules from '../../util/host-rules';
+import { regEx } from '../../util/regex';
 import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
 import type { AuthJson } from './types';
 import {
@@ -80,7 +81,7 @@ export async function updateArtifacts({
 }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
   logger.debug(`composer.updateArtifacts(${packageFileName})`);
 
-  const lockFileName = packageFileName.replace(/\.json$/, '.lock');
+  const lockFileName = packageFileName.replace(regEx(/\.json$/), '.lock');
   const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');
   if (!existingLockFileContent) {
     logger.debug('No composer.lock found');
diff --git a/lib/manager/composer/extract.ts b/lib/manager/composer/extract.ts
index e651bd9d81..f12b8b4ff6 100644
--- a/lib/manager/composer/extract.ts
+++ b/lib/manager/composer/extract.ts
@@ -4,6 +4,7 @@ import * as datasourcePackagist from '../../datasource/packagist';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { readLocalFile } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import { api as semverComposer } from '../../versioning/composer';
 import type { PackageDependency, PackageFile } from '../types';
 import type {
@@ -21,7 +22,7 @@ import type {
  * See https://github.com/composer/composer/blob/750a92b4b7aecda0e5b2f9b963f1cb1421900675/src/Composer/Repository/ComposerRepository.php#L815
  */
 function transformRegUrl(url: string): string {
-  return url.replace(/(\/packages\.json)$/, '');
+  return url.replace(regEx(/(\/packages\.json)$/), ''); // TODO #12071
 }
 
 /**
@@ -94,7 +95,7 @@ export async function extractPackageFile(
   const res: PackageFile = { deps: [] };
 
   // handle lockfile
-  const lockfilePath = fileName.replace(/\.json$/, '.lock');
+  const lockfilePath = fileName.replace(regEx(/\.json$/), '.lock');
   const lockContents = await readLocalFile(lockfilePath, 'utf8');
   let lockParsed: ComposerLock;
   if (lockContents) {
@@ -163,7 +164,7 @@ export async function extractPackageFile(
               (item) => item.name === dep.depName
             );
             if (lockedDep && semverComposer.isVersion(lockedDep.version)) {
-              dep.lockedVersion = lockedDep.version.replace(/^v/i, '');
+              dep.lockedVersion = lockedDep.version.replace(regEx(/^v/i), ''); // TODO #12071
             }
           }
           deps.push(dep);
diff --git a/lib/manager/deps-edn/extract.ts b/lib/manager/deps-edn/extract.ts
index 76aaadfacc..af43268cdd 100644
--- a/lib/manager/deps-edn/extract.ts
+++ b/lib/manager/deps-edn/extract.ts
@@ -1,11 +1,14 @@
 import { ClojureDatasource } from '../../datasource/clojure';
+import { regEx } from '../../util/regex';
 import { expandDepName } from '../leiningen/extract';
 import type { PackageDependency, PackageFile } from '../types';
 
 export function extractPackageFile(content: string): PackageFile {
   const deps: PackageDependency[] = [];
 
-  const regex = /([^{\s,]*)[\s,]*{[\s,]*:mvn\/version[\s,]+"([^"]+)"[\s,]*}/;
+  const regex = regEx(
+    /([^{\s,]*)[\s,]*{[\s,]*:mvn\/version[\s,]+"([^"]+)"[\s,]*}/
+  );
   let rest = content;
   let match = regex.exec(rest);
   let offset = 0;
diff --git a/lib/manager/docker-compose/extract.ts b/lib/manager/docker-compose/extract.ts
index 5e17f93000..ce5e937300 100644
--- a/lib/manager/docker-compose/extract.ts
+++ b/lib/manager/docker-compose/extract.ts
@@ -1,6 +1,7 @@
 import is from '@sindresorhus/is';
 import { load } from 'js-yaml';
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import { getDep } from '../dockerfile/extract';
 import type { PackageFile } from '../types';
 import type { DockerComposeConfig } from './types';
@@ -56,7 +57,7 @@ export function extractPackageFile(
     return null;
   }
   try {
-    const lineMapper = new LineMapper(content, /^\s*image:/);
+    const lineMapper = new LineMapper(content, regEx(/^\s*image:/));
 
     // docker-compose v1 places the services at the top level,
     // docker-compose v2+ places the services within a 'services' key
diff --git a/lib/manager/dockerfile/extract.ts b/lib/manager/dockerfile/extract.ts
index 4a0b6f11ec..b792195379 100644
--- a/lib/manager/dockerfile/extract.ts
+++ b/lib/manager/dockerfile/extract.ts
@@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
 import * as datasourceDocker from '../../datasource/docker';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import * as ubuntuVersioning from '../../versioning/ubuntu';
 import type { PackageDependency, PackageFile } from '../types';
 
@@ -32,7 +33,7 @@ export function splitImageParts(currentFrom: string): PackageDependency {
   return dep;
 }
 
-const quayRegex = /^quay\.io(?::[1-9][0-9]{0,4})?/i;
+const quayRegex = regEx(/^quay\.io(?::[1-9][0-9]{0,4})?/i);
 
 export function getDep(
   currentFrom: string,
@@ -89,7 +90,7 @@ export function extractPackageFile(content: string): PackageFile | null {
   const stageNames: string[] = [];
 
   const fromMatches = content.matchAll(
-    /^[ \t]*FROM(?:\\\r?\n| |\t|#.*?\r?\n|[ \t]--[a-z]+=\w+?)*[ \t](?<image>\S+)(?:(?:\\\r?\n| |\t|#.*\r?\n)+as[ \t]+(?<name>\S+))?/gim
+    /^[ \t]*FROM(?:\\\r?\n| |\t|#.*?\r?\n|[ \t]--[a-z]+=\w+?)*[ \t](?<image>\S+)(?:(?:\\\r?\n| |\t|#.*\r?\n)+as[ \t]+(?<name>\S+))?/gim // TODO #12070
   );
 
   for (const fromMatch of fromMatches) {
@@ -116,7 +117,7 @@ export function extractPackageFile(content: string): PackageFile | null {
   }
 
   const copyFromMatches = content.matchAll(
-    /^[ \t]*COPY(?:\\\r?\n| |\t|#.*\r?\n|[ \t]--[a-z]+=\w+?)*[ \t]--from=(?<image>\S+)/gim
+    /^[ \t]*COPY(?:\\\r?\n| |\t|#.*\r?\n|[ \t]--[a-z]+=\w+?)*[ \t]--from=(?<image>\S+)/gim // TODO #12070
   );
 
   for (const copyFromMatch of copyFromMatches) {
diff --git a/lib/manager/droneci/extract.ts b/lib/manager/droneci/extract.ts
index 7a8a9ecbcb..b02dffd55c 100644
--- a/lib/manager/droneci/extract.ts
+++ b/lib/manager/droneci/extract.ts
@@ -1,4 +1,5 @@
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import { getDep } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
 
@@ -8,7 +9,7 @@ export function extractPackageFile(content: string): PackageFile | null {
     const lines = content.split('\n');
     for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
       const line = lines[lineNumber];
-      const match = /^\s* image:\s*'?"?([^\s'"]+)'?"?\s*$/.exec(line);
+      const match = regEx(/^\s* image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); // TODO #12071
       if (match) {
         const currentFrom = match[1];
         const dep = getDep(currentFrom);
diff --git a/lib/manager/git-submodules/extract.ts b/lib/manager/git-submodules/extract.ts
index b5083af836..ae09c10ecf 100644
--- a/lib/manager/git-submodules/extract.ts
+++ b/lib/manager/git-submodules/extract.ts
@@ -6,6 +6,7 @@ import * as datasourceGitRefs from '../../datasource/git-refs';
 import { logger } from '../../logger';
 import { simpleGitConfig } from '../../util/git/config';
 import { getHttpUrl, getRemoteUrlWithToken } from '../../util/git/url';
+import { regEx } from '../../util/regex';
 import type { ExtractConfig, PackageFile } from '../types';
 import { GitModule } from './types';
 
@@ -32,7 +33,7 @@ async function getUrl(
   return URL.resolve(`${remoteUrl}/`, path);
 }
 
-const headRefRe = /ref: refs\/heads\/(?<branch>\w+)\s/;
+const headRefRe = regEx(/ref: refs\/heads\/(?<branch>\w+)\s/);
 
 async function getDefaultBranch(subModuleUrl: string): Promise<string> {
   const val = await Git().listRemote(['--symref', subModuleUrl, 'HEAD']);
@@ -71,11 +72,11 @@ async function getModules(
       ])) ?? /* istanbul ignore next: should never happen */ ''
     )
       .trim()
-      .split(/\n/)
+      .split(regEx(/\n/))
       .filter((s) => !!s);
 
     for (const line of modules) {
-      const [, name, path] = line.split(/submodule\.(.+?)\.path\s(.+)/);
+      const [, name, path] = line.split(regEx(/submodule\.(.+?)\.path\s(.+)/)); // TODO #12071
       res.push({ name, path });
     }
   } catch (err) /* istanbul ignore next */ {
@@ -104,8 +105,8 @@ export default async function extractPackageFile(
     try {
       const [currentDigest] = (await git.subModule(['status', path]))
         .trim()
-        .replace(/^[-+]/, '')
-        .split(/\s/);
+        .replace(regEx(/^[-+]/), '') // TODO #12071
+        .split(regEx(/\s/)); // TODO #12071
       const subModuleUrl = await getUrl(git, gitModulesPath, name);
       // hostRules only understands HTTP URLs
       // Find HTTP URL, then apply token
diff --git a/lib/manager/github-actions/extract.ts b/lib/manager/github-actions/extract.ts
index cea79172fb..d5a7bbd234 100644
--- a/lib/manager/github-actions/extract.ts
+++ b/lib/manager/github-actions/extract.ts
@@ -1,16 +1,18 @@
 import * as githubTagsDatasource from '../../datasource/github-tags';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import * as dockerVersioning from '../../versioning/docker';
 import { getDep } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
 
-const dockerRe = /^\s+uses: docker:\/\/([^"]+)\s*$/;
-const actionRe =
-  /^\s+-?\s+?uses: (?<replaceString>(?<depName>[\w-]+\/[\w-]+)(?<path>\/.*)?@(?<currentValue>.+?)(?: # renovate: tag=(?<tag>.+?))?)\s*?$/;
+const dockerRe = regEx(/^\s+uses: docker:\/\/([^"]+)\s*$/);
+const actionRe = regEx(
+  /^\s+-?\s+?uses: (?<replaceString>(?<depName>[\w-]+\/[\w-]+)(?<path>\/.*)?@(?<currentValue>.+?)(?: # renovate: tag=(?<tag>.+?))?)\s*?$/
+);
 
 // SHA1 or SHA256, see https://github.blog/2020-10-19-git-2-29-released/
-const shaRe = /^[a-z0-9]{40}|[a-z0-9]{64}$/;
+const shaRe = regEx(/^[a-z0-9]{40}|[a-z0-9]{64}$/);
 
 export function extractPackageFile(content: string): PackageFile | null {
   logger.trace('github-actions.extractPackageFile()');
diff --git a/lib/manager/gitlabci-include/extract.ts b/lib/manager/gitlabci-include/extract.ts
index 63e8921b5b..cd5c5a7392 100644
--- a/lib/manager/gitlabci-include/extract.ts
+++ b/lib/manager/gitlabci-include/extract.ts
@@ -3,6 +3,7 @@ import { load } from 'js-yaml';
 import * as datasourceGitlabTags from '../../datasource/gitlab-tags';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import { replaceReferenceTags } from '../gitlabci/utils';
 import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 
@@ -45,7 +46,9 @@ export function extractPackageFile(
       if (includeObj?.file && includeObj.project) {
         const dep = extractDepFromIncludeFile(includeObj);
         if (config.endpoint) {
-          dep.registryUrls = [config.endpoint.replace(/\/api\/v4\/?/, '')];
+          dep.registryUrls = [
+            config.endpoint.replace(regEx(/\/api\/v4\/?/), ''),
+          ]; // TODO #12071
         }
         deps.push(dep);
       }
diff --git a/lib/manager/gitlabci/extract.ts b/lib/manager/gitlabci/extract.ts
index 3ec54aff72..2d0fee6ce6 100644
--- a/lib/manager/gitlabci/extract.ts
+++ b/lib/manager/gitlabci/extract.ts
@@ -7,13 +7,12 @@ import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 import type { GitlabPipeline } from './types';
 import { replaceReferenceTags } from './utils';
 
-const commentsRe = /^\s*#/;
-const whitespaceRe = /^(?<whitespace>\s*)/;
+const commentsRe = /^\s*#/; // TODO #12070
+const whitespaceRe = /^(?<whitespace>\s*)/; // TODO #12070
 const imageRe =
-  /^(?<whitespace>\s*)image:(?:\s+['"]?(?<image>[^\s'"]+)['"]?)?\s*$/;
-const nameRe = /^\s*name:\s+['"]?(?<depName>[^\s'"]+)['"]?\s*$/;
-const serviceRe = /^\s*-\s*(?:name:\s+)?['"]?(?<depName>[^\s'"]+)['"]?\s*$/;
-
+  /^(?<whitespace>\s*)image:(?:\s+['"]?(?<image>[^\s'"]+)['"]?)?\s*$/; // TODO #12070
+const nameRe = /^\s*name:\s+['"]?(?<depName>[^\s'"]+)['"]?\s*$/; // TODO #12070
+const serviceRe = /^\s*-\s*(?:name:\s+)?['"]?(?<depName>[^\s'"]+)['"]?\s*$/; // TODO #12070
 function skipCommentLines(
   lines: string[],
   lineNumber: number
@@ -62,7 +61,7 @@ export function extractPackageFile(content: string): PackageFile | null {
           }
         }
       }
-      const services = /^\s*services:\s*$/.test(line);
+      const services = /^\s*services:\s*$/.test(line); // TODO #12071  #12070
       if (services) {
         logger.trace(`Matched services on line ${lineNumber}`);
         let foundImage: boolean;
@@ -121,7 +120,7 @@ export async function extractAllPackageFiles(
     if (is.array(doc?.include)) {
       for (const includeObj of doc.include) {
         if (is.string(includeObj.local)) {
-          const fileObj = includeObj.local.replace(/^\//, '');
+          const fileObj = includeObj.local.replace(/^\//, ''); // TODO #12071 #12070
           if (!seen.has(fileObj)) {
             seen.add(fileObj);
             filesToExamine.push(fileObj);
@@ -129,7 +128,7 @@ export async function extractAllPackageFiles(
         }
       }
     } else if (is.string(doc?.include)) {
-      const fileObj = doc.include.replace(/^\//, '');
+      const fileObj = doc.include.replace(/^\//, ''); // TODO #12071  #12070
       if (!seen.has(fileObj)) {
         seen.add(fileObj);
         filesToExamine.push(fileObj);
diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts
index a4dc7a33b8..9b6f08de39 100644
--- a/lib/manager/gomod/artifacts.ts
+++ b/lib/manager/gomod/artifacts.ts
@@ -9,6 +9,7 @@ import { ExecOptions, exec } from '../../util/exec';
 import { ensureCacheDir, readLocalFile, writeLocalFile } from '../../util/fs';
 import { getRepoStatus } from '../../util/git';
 import { find } from '../../util/host-rules';
+import { regEx } from '../../util/regex';
 import { isValid } from '../../versioning/semver';
 import type {
   PackageDependency,
@@ -48,10 +49,10 @@ function getUpdateImportPathCmds(
     if (gomodModCompatibility) {
       if (
         gomodModCompatibility.startsWith('v') &&
-        isValid(gomodModCompatibility.replace(/^v/, ''))
+        isValid(gomodModCompatibility.replace(regEx(/^v/), ''))
       ) {
         installMarwanModArgs = installMarwanModArgs.replace(
-          /@latest$/,
+          regEx(/@latest$/),
           `@${gomodModCompatibility}`
         );
       } else {
@@ -76,7 +77,7 @@ function useModcacherw(goVersion: string): boolean {
     return true;
   }
 
-  const [, majorPart, minorPart] = /(\d+)\.(\d+)/.exec(goVersion) ?? [];
+  const [, majorPart, minorPart] = regEx(/(\d+)\.(\d+)/).exec(goVersion) ?? [];
   const [major, minor] = [majorPart, minorPart].map((x) => parseInt(x, 10));
 
   return (
@@ -94,7 +95,7 @@ export async function updateArtifacts({
 }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
   logger.debug(`gomod.updateArtifacts(${goModFileName})`);
 
-  const sumFileName = goModFileName.replace(/\.mod$/, '.sum');
+  const sumFileName = goModFileName.replace(regEx(/\.mod$/), '.sum');
   const existingGoSumContent = await readLocalFile(sumFileName);
   if (!existingGoSumContent) {
     logger.debug('No go.sum found');
@@ -107,7 +108,7 @@ export async function updateArtifacts({
 
   try {
     const massagedGoMod = newGoModContent.replace(
-      /\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g,
+      regEx(/\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g),
       '\n// renovate-replace $1'
     );
     if (massagedGoMod !== newGoModContent) {
@@ -237,7 +238,7 @@ export async function updateArtifacts({
 
     const finalGoModContent = (
       await readLocalFile(goModFileName, 'utf8')
-    ).replace(/\/\/ renovate-replace /g, '');
+    ).replace(regEx(/\/\/ renovate-replace /g), '');
     if (finalGoModContent !== newGoModContent) {
       logger.debug('Found updated go.mod after go.sum update');
       res.push({
diff --git a/lib/manager/gomod/extract.ts b/lib/manager/gomod/extract.ts
index 74e3482ac2..beaeed66d1 100644
--- a/lib/manager/gomod/extract.ts
+++ b/lib/manager/gomod/extract.ts
@@ -2,6 +2,7 @@ import { validRange } from 'semver';
 import * as datasourceGo from '../../datasource/go';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import { isVersion } from '../../versioning/semver';
 import type { PackageDependency, PackageFile } from '../types';
 
@@ -12,7 +13,7 @@ function getDep(
 ): PackageDependency {
   const [, , currentValue] = match;
   let [, depName] = match;
-  depName = depName.replace(/"/g, '');
+  depName = depName.replace(regEx(/"/g), '');
   const dep: PackageDependency = {
     managerData: {
       lineNumber,
@@ -26,7 +27,7 @@ function getDep(
   } else {
     dep.skipReason = SkipReason.UnsupportedVersion;
   }
-  const digestMatch = /v0\.0.0-\d{14}-([a-f0-9]{12})/.exec(currentValue);
+  const digestMatch = regEx(/v0\.0.0-\d{14}-([a-f0-9]{12})/).exec(currentValue);
   if (digestMatch) {
     [, dep.currentDigest] = digestMatch;
     dep.digestOneAndOnly = true;
@@ -45,13 +46,14 @@ export function extractPackageFile(content: string): PackageFile | null {
       if (line.startsWith('go ') && validRange(line.replace('go ', ''))) {
         constraints.go = line.replace('go ', '^');
       }
-      const replaceMatch =
-        /^replace\s+[^\s]+[\s]+[=][>]\s+([^\s]+)\s+([^\s]+)/.exec(line);
+      const replaceMatch = regEx(
+        /^replace\s+[^\s]+[\s]+[=][>]\s+([^\s]+)\s+([^\s]+)/
+      ).exec(line); // TODO #12071
       if (replaceMatch) {
         const dep = getDep(lineNumber, replaceMatch, 'replace');
         deps.push(dep);
       }
-      const requireMatch = /^require\s+([^\s]+)\s+([^\s]+)/.exec(line);
+      const requireMatch = regEx(/^require\s+([^\s]+)\s+([^\s]+)/).exec(line); // TODO #12071
       if (requireMatch && !line.endsWith('// indirect')) {
         logger.trace({ lineNumber }, `require line: "${line}"`);
         const dep = getDep(lineNumber, requireMatch, 'require');
@@ -62,7 +64,7 @@ export function extractPackageFile(content: string): PackageFile | null {
         do {
           lineNumber += 1;
           line = lines[lineNumber];
-          const multiMatch = /^\s+([^\s]+)\s+([^\s]+)/.exec(line);
+          const multiMatch = regEx(/^\s+([^\s]+)\s+([^\s]+)/).exec(line); // TODO #12071
           logger.trace(`reqLine: "${line}"`);
           if (multiMatch && !line.endsWith('// indirect')) {
             logger.trace({ lineNumber }, `require line: "${line}"`);
diff --git a/lib/manager/gomod/update.ts b/lib/manager/gomod/update.ts
index eef2923c62..49aa13d185 100644
--- a/lib/manager/gomod/update.ts
+++ b/lib/manager/gomod/update.ts
@@ -1,10 +1,11 @@
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import type { UpdateDependencyConfig } from '../types';
 
 function getDepNameWithNoVersion(depName: string): string {
   let depNameNoVersion = depName.split('/').slice(0, 3).join('/');
   if (depNameNoVersion.startsWith('gopkg.in')) {
-    depNameNoVersion = depNameNoVersion.replace(/\.v\d+$/, '');
+    depNameNoVersion = depNameNoVersion.replace(regEx(/\.v\d+$/), '');
   }
   return depNameNoVersion;
 }
@@ -31,14 +32,14 @@ export function updateDependency({
     }
     let updateLineExp: RegExp;
     if (depType === 'replace') {
-      updateLineExp = new RegExp(
+      updateLineExp = regEx(
         /^(replace\s+[^\s]+[\s]+[=][>]+\s+)([^\s]+\s+)([^\s]+)/
       );
     } else if (depType === 'require') {
       if (upgrade.managerData.multiLine) {
-        updateLineExp = new RegExp(/^(\s+[^\s]+)(\s+)([^\s]+)/);
+        updateLineExp = regEx(/^(\s+[^\s]+)(\s+)([^\s]+)/);
       } else {
-        updateLineExp = new RegExp(/^(require\s+[^\s]+)(\s+)([^\s]+)/);
+        updateLineExp = regEx(/^(require\s+[^\s]+)(\s+)([^\s]+)/);
       }
     }
     if (updateLineExp && !updateLineExp.test(lineToChange)) {
@@ -86,7 +87,7 @@ export function updateDependency({
           // Replace version
           const [oldV] = upgrade.currentValue.split('.');
           newLine = newLine.replace(
-            new RegExp(`/${oldV}(\\s+)`),
+            regEx(`/${oldV}(\\s+)`),
             `/v${upgrade.newMajor}$1`
           );
         }
diff --git a/lib/manager/gradle/deep/gradle-updates-report.ts b/lib/manager/gradle/deep/gradle-updates-report.ts
index 917caf1e67..59ec47b264 100644
--- a/lib/manager/gradle/deep/gradle-updates-report.ts
+++ b/lib/manager/gradle/deep/gradle-updates-report.ts
@@ -6,6 +6,7 @@ import {
   readLocalFile,
   writeLocalFile,
 } from '../../../util/fs';
+import { regEx } from '../../../util/regex';
 import type {
   BuildDependency,
   GradleDependencyWithRepos,
@@ -144,11 +145,12 @@ export async function extractDependenciesFromUpdatesReport(
       if (depName.endsWith('_%%')) {
         return {
           ...dep,
-          depName: depName.replace(/_%%/, ''),
+          depName: depName.replace(regEx(/_%%/), ''), // TODO #12071
           datasource: datasourceSbtPackage.id,
         };
       }
-      if (/^%.*%$/.test(currentValue)) {
+      if (regEx(/^%.*%$/).test(currentValue)) {
+        // TODO #12071
         return { ...dep, skipReason: 'version-placeholder' };
       }
       return dep;
diff --git a/lib/manager/gradle/shallow/tokenizer.ts b/lib/manager/gradle/shallow/tokenizer.ts
index 73a698bcd2..728fcbe2a8 100644
--- a/lib/manager/gradle/shallow/tokenizer.ts
+++ b/lib/manager/gradle/shallow/tokenizer.ts
@@ -1,8 +1,9 @@
 import moo from 'moo';
+import { regEx } from '../../../util/regex';
 import { TokenType } from './common';
 import type { StringInterpolation, Token } from './types';
 
-const escapedCharRegex = /\\['"bfnrt\\]/;
+const escapedCharRegex = /\\['"bfnrt\\]/; // TODO #12070
 const escapedChars = {
   [TokenType.EscapedChar]: {
     match: escapedCharRegex,
@@ -23,17 +24,17 @@ const escapedChars = {
 const lexer = moo.states({
   // Top-level Groovy lexemes
   main: {
-    [TokenType.LineComment]: { match: /\/\/.*?$/ },
-    [TokenType.MultiComment]: { match: /\/\*[^]*?\*\//, lineBreaks: true },
-    [TokenType.Newline]: { match: /\r?\n/, lineBreaks: true },
-    [TokenType.Space]: { match: /[ \t\r]+/ },
+    [TokenType.LineComment]: { match: /\/\/.*?$/ }, // TODO #12070
+    [TokenType.MultiComment]: { match: /\/\*[^]*?\*\//, lineBreaks: true }, // TODO #12070
+    [TokenType.Newline]: { match: /\r?\n/, lineBreaks: true }, // TODO #12070
+    [TokenType.Space]: { match: /[ \t\r]+/ }, // TODO #12070
     [TokenType.Semicolon]: ';',
     [TokenType.Colon]: ':',
     [TokenType.Dot]: '.',
     [TokenType.Comma]: ',',
-    [TokenType.Operator]: /(?:==|\+=?|-=?|\/=?|\*\*?|\.+|:)/,
+    [TokenType.Operator]: /(?:==|\+=?|-=?|\/=?|\*\*?|\.+|:)/, // TODO #12070
     [TokenType.Assignment]: '=',
-    [TokenType.Word]: { match: /[a-zA-Z$_][a-zA-Z0-9$_]+/ },
+    [TokenType.Word]: { match: /[a-zA-Z$_][a-zA-Z0-9$_]+/ }, // TODO #12070
     [TokenType.LeftParen]: { match: '(' },
     [TokenType.RightParen]: { match: ')' },
     [TokenType.LeftBracket]: { match: '[' },
@@ -85,12 +86,12 @@ const lexer = moo.states({
     variable: {
       // Supported: ${foo}, $foo, ${ foo.bar.baz }, $foo.bar.baz
       match:
-        /\${\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\s*\.\s*[a-zA-Z_][a-zA-Z0-9_]*)*\s*}|\$[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*/,
+        /\${\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\s*\.\s*[a-zA-Z_][a-zA-Z0-9_]*)*\s*}|\$[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*/, // TODO #12070
       value: (x: string): string =>
-        x.replace(/^\${?\s*/, '').replace(/\s*}$/, ''),
+        x.replace(regEx(/^\${?\s*/), '').replace(regEx(/\s*}$/), ''),
     },
     [TokenType.IgnoredInterpolationStart]: {
-      match: /\${/,
+      match: /\${/, // TODO #12070
       push: TokenType.IgnoredInterpolationStart,
     },
     [TokenType.Chars]: moo.fallback,
diff --git a/lib/manager/gradle/shallow/utils.ts b/lib/manager/gradle/shallow/utils.ts
index e1da8b2a79..c9c2a36a79 100644
--- a/lib/manager/gradle/shallow/utils.ts
+++ b/lib/manager/gradle/shallow/utils.ts
@@ -111,7 +111,7 @@ export function isTOMLFile(path: string): boolean {
 }
 
 export function toAbsolutePath(packageFile: string): string {
-  return upath.join(packageFile.replace(/^[/\\]*/, '/'));
+  return upath.join(packageFile.replace(regEx(/^[/\\]*/), '/'));
 }
 
 export function reorderFiles(packageFiles: string[]): string[] {
diff --git a/lib/manager/helm-values/util.ts b/lib/manager/helm-values/util.ts
index f1707aef7b..d435b451c3 100644
--- a/lib/manager/helm-values/util.ts
+++ b/lib/manager/helm-values/util.ts
@@ -1,7 +1,8 @@
 import { hasKey } from '../../util/object';
+import { regEx } from '../../util/regex';
 import { HelmDockerImageDependency } from './types';
 
-const parentKeyRe = /image$/i;
+const parentKeyRe = regEx(/image$/i);
 
 /**
  * Type guard to determine whether a given partial Helm values.yaml object potentially
diff --git a/lib/manager/helmfile/extract.ts b/lib/manager/helmfile/extract.ts
index c2cc664568..39544b7456 100644
--- a/lib/manager/helmfile/extract.ts
+++ b/lib/manager/helmfile/extract.ts
@@ -3,11 +3,12 @@ import { loadAll } from 'js-yaml';
 import { HelmDatasource } from '../../datasource/helm';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 import type { Doc } from './types';
 
 const isValidChartName = (name: string): boolean =>
-  !/[!@#$%^&*(),.?":{}/|<>A-Z]/.test(name);
+  !regEx(/[!@#$%^&*(),.?":{}/|<>A-Z]/).test(name);
 
 export function extractPackageFile(
   content: string,
diff --git a/lib/manager/helmv3/update.ts b/lib/manager/helmv3/update.ts
index f43af27cb7..2ffd5c9e3e 100644
--- a/lib/manager/helmv3/update.ts
+++ b/lib/manager/helmv3/update.ts
@@ -20,7 +20,7 @@ export function bumpPackageVersion(
     }
     logger.debug({ newChartVersion });
     bumpedContent = content.replace(
-      /^(version:\s*).*$/m,
+      /^(version:\s*).*$/m, // TODO #12070
       `$1${newChartVersion}`
     );
     if (bumpedContent === content) {
diff --git a/lib/manager/homebrew/extract.ts b/lib/manager/homebrew/extract.ts
index 04803fc6c5..fbe78c91bd 100644
--- a/lib/manager/homebrew/extract.ts
+++ b/lib/manager/homebrew/extract.ts
@@ -1,6 +1,7 @@
 import * as datasourceGithubTags from '../../datasource/github-tags';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import type { UrlPathParsedResult } from './types';
 import { isSpace, removeComments, skip } from './util';
@@ -19,7 +20,7 @@ function parseSha256(idx: number, content: string): string | null {
 }
 
 function extractSha256(content: string): string | null {
-  const sha256RegExp = /(^|\s)sha256(\s)/;
+  const sha256RegExp = regEx(/(^|\s)sha256(\s)/);
   let i = content.search(sha256RegExp);
   if (isSpace(content[i])) {
     i += 1;
@@ -42,7 +43,7 @@ function parseUrl(idx: number, content: string): string | null {
 }
 
 function extractUrl(content: string): string | null {
-  const urlRegExp = /(^|\s)url(\s)/;
+  const urlRegExp = regEx(/(^|\s)url(\s)/);
   let i = content.search(urlRegExp);
   // content.search() returns -1 if not found
   if (i === -1) {
@@ -117,7 +118,7 @@ function parseClassHeader(idx: number, content: string): string | null {
 }
 
 function extractClassName(content: string): string | null {
-  const classRegExp = /(^|\s)class\s/;
+  const classRegExp = regEx(/(^|\s)class\s/);
   let i = content.search(classRegExp);
   if (isSpace(content[i])) {
     i += 1;
diff --git a/lib/manager/html/extract.ts b/lib/manager/html/extract.ts
index b027836e78..6bb3383e06 100644
--- a/lib/manager/html/extract.ts
+++ b/lib/manager/html/extract.ts
@@ -1,10 +1,13 @@
 import { CdnJsDatasource } from '../../datasource/cdnjs';
+import { regEx } from '../../util/regex';
 import { cloudflareUrlRegex } from '../cdnurl/extract';
 import type { PackageDependency, PackageFile } from '../types';
 
-const regex = /<\s*(script|link)\s+[^>]*?\/?>/i;
+const regex = regEx(/<\s*(script|link)\s+[^>]*?\/?>/i);
 
-const integrityRegex = /\s+integrity\s*=\s*("|')(?<currentDigest>[^"']+)/;
+const integrityRegex = regEx(
+  /\s+integrity\s*=\s*("|')(?<currentDigest>[^"']+)/
+);
 
 export function extractDep(tag: string): PackageDependency | null {
   const match = cloudflareUrlRegex.exec(tag);
diff --git a/lib/manager/jenkins/extract.ts b/lib/manager/jenkins/extract.ts
index 1ea64b039d..c5e9d013eb 100644
--- a/lib/manager/jenkins/extract.ts
+++ b/lib/manager/jenkins/extract.ts
@@ -3,11 +3,12 @@ import * as datasourceJenkins from '../../datasource/jenkins-plugins';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { isSkipComment } from '../../util/ignore';
+import { regEx } from '../../util/regex';
 import * as dockerVersioning from '../../versioning/docker';
 import type { PackageDependency, PackageFile } from '../types';
 import type { JenkinsPlugin, JenkinsPlugins } from './types';
 
-const YamlExtension = /\.ya?ml$/;
+const YamlExtension = regEx(/\.ya?ml$/);
 
 function getDependency(plugin: JenkinsPlugin): PackageDependency {
   const dep: PackageDependency = {
@@ -70,8 +71,9 @@ function extractYaml(content: string): PackageDependency[] {
 
 function extractText(content: string): PackageDependency[] {
   const deps: PackageDependency[] = [];
-  const regex =
-    /^\s*(?<depName>[\d\w-]+):(?<currentValue>[^#\s]+)[#\s]*(?<comment>.*)$/;
+  const regex = regEx(
+    /^\s*(?<depName>[\d\w-]+):(?<currentValue>[^#\s]+)[#\s]*(?<comment>.*)$/
+  );
 
   for (const line of content.split('\n')) {
     const match = regex.exec(line);
diff --git a/lib/manager/kubernetes/extract.ts b/lib/manager/kubernetes/extract.ts
index cdd2827ca6..1eb9b20c27 100644
--- a/lib/manager/kubernetes/extract.ts
+++ b/lib/manager/kubernetes/extract.ts
@@ -1,4 +1,5 @@
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import { getDep } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
 
@@ -7,13 +8,14 @@ export function extractPackageFile(content: string): PackageFile | null {
   let deps: PackageDependency[] = [];
 
   const isKubernetesManifest =
-    /\s*apiVersion\s*:/.test(content) && /\s*kind\s*:/.test(content);
+    regEx(/\s*apiVersion\s*:/).test(content) &&
+    regEx(/\s*kind\s*:/).test(content);
   if (!isKubernetesManifest) {
     return null;
   }
 
   for (const line of content.split('\n')) {
-    const match = /^\s*-?\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/.exec(line);
+    const match = regEx(/^\s*-?\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); // TODO #12071
     if (match) {
       const currentFrom = match[1];
       const dep = getDep(currentFrom);
diff --git a/lib/manager/kustomize/extract.ts b/lib/manager/kustomize/extract.ts
index f4cd424f8b..8c3f3ade85 100644
--- a/lib/manager/kustomize/extract.ts
+++ b/lib/manager/kustomize/extract.ts
@@ -5,14 +5,16 @@ import * as datasourceGitTags from '../../datasource/git-tags';
 import * as datasourceGitHubTags from '../../datasource/github-tags';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import { splitImageParts } from '../dockerfile/extract';
 import type { PackageDependency, PackageFile } from '../types';
 import type { Image, Kustomize } from './types';
 
 // URL specifications should follow the hashicorp URL format
 // https://github.com/hashicorp/go-getter#url-format
-const gitUrl =
-  /^(?:git::)?(?<url>(?:(?:(?:http|https|ssh):\/\/)?(?:.*@)?)?(?<path>(?:[^:/\s]+(?::[0-9]+)?[:/])?(?<project>[^/\s]+\/[^/\s]+)))(?<subdir>[^?\s]*)\?ref=(?<currentValue>.+)$/;
+const gitUrl = regEx(
+  /^(?:git::)?(?<url>(?:(?:(?:http|https|ssh):\/\/)?(?:.*@)?)?(?<path>(?:[^:/\s]+(?::[0-9]+)?[:/])?(?<project>[^/\s]+\/[^/\s]+)))(?<subdir>[^?\s]*)\?ref=(?<currentValue>.+)$/
+);
 
 export function extractBase(base: string): PackageDependency | null {
   const match = gitUrl.exec(base);
diff --git a/lib/manager/leiningen/extract.ts b/lib/manager/leiningen/extract.ts
index e219db21b2..90e51d0278 100644
--- a/lib/manager/leiningen/extract.ts
+++ b/lib/manager/leiningen/extract.ts
@@ -1,15 +1,16 @@
 import { ClojureDatasource } from '../../datasource/clojure';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import type { ExtractContext, ExtractedVariables } from './types';
 
 export function trimAtKey(str: string, kwName: string): string | null {
-  const regex = new RegExp(`:${kwName}(?=\\s)`);
+  const regex = new RegExp(`:${kwName}(?=\\s)`); // TODO #12070
   const keyOffset = str.search(regex);
   if (keyOffset < 0) {
     return null;
   }
   const withSpaces = str.slice(keyOffset + kwName.length + 1);
-  const valueOffset = withSpaces.search(/[^\s]/);
+  const valueOffset = withSpaces.search(regEx(/[^\s]/));
   if (valueOffset < 0) {
     return null;
   }
@@ -35,16 +36,16 @@ export function extractFromVectors(
   let artifactId = '';
   let version = '';
 
-  const isSpace = (ch: string): boolean => ch && /[\s,]/.test(ch);
+  const isSpace = (ch: string): boolean => ch && regEx(/[\s,]/).test(ch);
 
   const cleanStrLiteral = (s: string): string =>
-    s.replace(/^"/, '').replace(/"$/, '');
+    s.replace(regEx(/^"/), '').replace(regEx(/"$/), '');
 
   const yieldDep = (): void => {
     if (artifactId && version) {
       const depName = expandDepName(cleanStrLiteral(artifactId));
       if (version.startsWith('~')) {
-        const currentValue = vars[version.replace(/^~\s*/, '')];
+        const currentValue = vars[version.replace(regEx(/^~\s*/), '')];
         if (currentValue) {
           result.push({
             ...ctx,
@@ -102,7 +103,7 @@ function extractLeinRepos(content: string): string[] {
   const result = [];
 
   const repoContent = trimAtKey(
-    content.replace(/;;.*(?=[\r\n])/g, ''), // get rid of comments
+    content.replace(/;;.*(?=[\r\n])/g, ''), // get rid of comments // TODO #12070
     'repositories'
   );
 
@@ -122,16 +123,19 @@ function extractLeinRepos(content: string): string[] {
       }
     }
     const repoSectionContent = repoContent.slice(0, endIdx);
-    const matches = repoSectionContent.match(/"https?:\/\/[^"]*"/g) || [];
-    const urls = matches.map((x) => x.replace(/^"/, '').replace(/"$/, ''));
+    const matches = repoSectionContent.match(/"https?:\/\/[^"]*"/g) || []; // TODO #12070
+    const urls = matches.map((x) =>
+      x.replace(regEx(/^"/), '').replace(regEx(/"$/), '')
+    ); // TODO #12071
     urls.forEach((url) => result.push(url));
   }
 
   return result;
 }
 
-const defRegex =
-  /^[\s,]*\([\s,]*def[\s,]+(?<varName>[-+*=<>.!?#$%&_|a-zA-Z][-+*=<>.!?#$%&_|a-zA-Z0-9']+)[\s,]*"(?<stringValue>[^"]*)"[\s,]*\)[\s,]*$/;
+const defRegex = regEx(
+  /^[\s,]*\([\s,]*def[\s,]+(?<varName>[-+*=<>.!?#$%&_|a-zA-Z][-+*=<>.!?#$%&_|a-zA-Z0-9']+)[\s,]*"(?<stringValue>[^"]*)"[\s,]*\)[\s,]*$/
+);
 
 export function extractVariables(content: string): ExtractedVariables {
   const result: ExtractedVariables = {};
diff --git a/lib/manager/maven/extract.ts b/lib/manager/maven/extract.ts
index a8721584c6..28e72a8054 100644
--- a/lib/manager/maven/extract.ts
+++ b/lib/manager/maven/extract.ts
@@ -6,6 +6,7 @@ import { MAVEN_REPO } from '../../datasource/maven/common';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { readLocalFile } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 import type { MavenProp } from './types';
 
@@ -33,7 +34,7 @@ export function parsePom(raw: string): XmlDocument | null {
 }
 
 function containsPlaceholder(str: string): boolean {
-  return /\${.*?}/g.test(str);
+  return regEx(/\${.*?}/g).test(str);
 }
 
 function depFromNode(node: XmlElement): PackageDependency | null {
@@ -95,7 +96,7 @@ function applyProps(
   props: MavenProp
 ): PackageDependency<Record<string, any>> {
   const replaceAll = (str: string): string =>
-    str.replace(/\${.*?}/g, (substr) => {
+    str.replace(regEx(/\${.*?}/g), (substr) => {
       const propKey = substr.slice(2, -1).trim();
       const propValue = props[propKey];
       return propValue ? propValue.val : substr;
@@ -107,19 +108,22 @@ function applyProps(
   let fileReplacePosition = dep.fileReplacePosition;
   let propSource = null;
   let groupName = null;
-  const currentValue = dep.currentValue.replace(/^\${.*?}$/, (substr) => {
-    const propKey = substr.slice(2, -1).trim();
-    const propValue = props[propKey];
-    if (propValue) {
-      if (!groupName) {
-        groupName = propKey;
+  const currentValue = dep.currentValue.replace(
+    regEx(/^\${.*?}$/),
+    (substr) => {
+      const propKey = substr.slice(2, -1).trim();
+      const propValue = props[propKey];
+      if (propValue) {
+        if (!groupName) {
+          groupName = propKey;
+        }
+        fileReplacePosition = propValue.fileReplacePosition;
+        propSource = propValue.packageFile;
+        return propValue.val;
       }
-      fileReplacePosition = propValue.fileReplacePosition;
-      propSource = propValue.packageFile;
-      return propValue.val;
+      return substr;
     }
-    return substr;
-  });
+  );
 
   const result: PackageDependency = {
     ...dep,
diff --git a/lib/manager/meteor/extract.ts b/lib/manager/meteor/extract.ts
index 651827aa92..943842d904 100644
--- a/lib/manager/meteor/extract.ts
+++ b/lib/manager/meteor/extract.ts
@@ -1,20 +1,21 @@
 import { id as npmId } from '../../datasource/npm';
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 
 export function extractPackageFile(content: string): PackageFile | null {
   let deps: PackageDependency[] = [];
-  const npmDepends = /\nNpm\.depends\({([\s\S]*?)}\);/.exec(content);
+  const npmDepends = regEx(/\nNpm\.depends\({([\s\S]*?)}\);/).exec(content);
   if (!npmDepends) {
     return null;
   }
   try {
     deps = npmDepends[1]
-      .replace(/(\s|\\n|\\t|'|")/g, '')
+      .replace(regEx(/(\s|\\n|\\t|'|")/g), '')
       .split(',')
       .map((dep) => dep.trim())
       .filter((dep) => dep.length)
-      .map((dep) => dep.split(/:(.*)/))
+      .map((dep) => dep.split(regEx(/:(.*)/))) // TODO #12071
       .map((arr) => {
         const [depName, currentValue] = arr;
         // istanbul ignore if
diff --git a/lib/manager/mix/extract.ts b/lib/manager/mix/extract.ts
index 0f13f92387..c55a334eea 100644
--- a/lib/manager/mix/extract.ts
+++ b/lib/manager/mix/extract.ts
@@ -2,11 +2,13 @@ import { HexDatasource } from '../../datasource/hex';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { findLocalSiblingOrParent, localPathExists } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 
-const depSectionRegExp = /defp\s+deps.*do/g;
-const depMatchRegExp =
-  /{:(\w+),\s*([^:"]+)?:?\s*"([^"]+)",?\s*(organization: "(.*)")?.*}/gm;
+const depSectionRegExp = regEx(/defp\s+deps.*do/g);
+const depMatchRegExp = regEx(
+  /{:(\w+),\s*([^:"]+)?:?\s*"([^"]+)",?\s*(organization: "(.*)")?.*}/gm
+);
 
 export async function extractPackageFile(
   content: string,
diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts
index 174d1a0543..2ce178ba19 100644
--- a/lib/manager/npm/extract/index.ts
+++ b/lib/manager/npm/extract/index.ts
@@ -26,12 +26,12 @@ function parseDepName(depType: string, key: string): string {
     return key;
   }
 
-  const [, depName] = /((?:@[^/]+\/)?[^/@]+)$/.exec(key) ?? [];
+  const [, depName] = /((?:@[^/]+\/)?[^/@]+)$/.exec(key) ?? []; // TODO #12070
   return depName;
 }
 
 const RE_REPOSITORY_GITHUB_SSH_FORMAT =
-  /(?:git@)github.com:([^/]+)\/([^/.]+)(?:\.git)?/;
+  /(?:git@)github.com:([^/]+)\/([^/.]+)(?:\.git)?/; // TODO #12070
 
 export async function extractPackageFile(
   content: string,
@@ -106,11 +106,11 @@ export async function extractPackageFile(
     } else {
       npmrc = config.npmrc || '';
       if (npmrc.length) {
-        npmrc = npmrc.replace(/\n?$/, '\n');
+        npmrc = npmrc.replace(/\n?$/, '\n'); // TODO #12070
       }
       if (repoNpmrc?.includes('package-lock')) {
         logger.debug('Stripping package-lock setting from .npmrc');
-        repoNpmrc = repoNpmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n');
+        repoNpmrc = repoNpmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); // TODO #12070
       }
       if (repoNpmrc.includes('=${') && !getGlobalConfig().exposeAllEnv) {
         logger.debug(
@@ -272,10 +272,10 @@ export async function extractPackageFile(
     const matchUrlSshFormat = RE_REPOSITORY_GITHUB_SSH_FORMAT.exec(depNamePart);
     if (matchUrlSshFormat === null) {
       githubOwnerRepo = depNamePart
-        .replace(/^github:/, '')
-        .replace(/^git\+/, '')
-        .replace(/^https:\/\/github\.com\//, '')
-        .replace(/\.git$/, '');
+        .replace(/^github:/, '') // TODO #12070
+        .replace(/^git\+/, '') // TODO #12070
+        .replace(/^https:\/\/github\.com\//, '') // TODO #12070
+        .replace(/\.git$/, ''); // TODO #12070
       const githubRepoSplit = githubOwnerRepo.split('/');
       if (githubRepoSplit.length !== 2) {
         dep.skipReason = SkipReason.UnknownVersion;
@@ -287,7 +287,7 @@ export async function extractPackageFile(
       githubRepo = matchUrlSshFormat[2];
       githubOwnerRepo = `${githubOwner}/${githubRepo}`;
     }
-    const githubValidRegex = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/;
+    const githubValidRegex = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/; // TODO #12070
     if (
       !githubValidRegex.test(githubOwner) ||
       !githubValidRegex.test(githubRepo)
@@ -302,8 +302,8 @@ export async function extractPackageFile(
       dep.lookupName = githubOwnerRepo;
       dep.pinDigests = false;
     } else if (
-      /^[0-9a-f]{7}$/.test(depRefPart) ||
-      /^[0-9a-f]{40}$/.test(depRefPart)
+      /^[0-9a-f]{7}$/.test(depRefPart) || // TODO #12070
+      /^[0-9a-f]{40}$/.test(depRefPart) // TODO #12070
     ) {
       dep.currentRawValue = dep.currentValue;
       dep.currentValue = null;
diff --git a/lib/manager/npm/extract/pnpm.ts b/lib/manager/npm/extract/pnpm.ts
index 022ef6c8f4..a394c6aafe 100644
--- a/lib/manager/npm/extract/pnpm.ts
+++ b/lib/manager/npm/extract/pnpm.ts
@@ -105,7 +105,7 @@ export async function detectPnpmWorkspaces(
       packageFilters !== null &&
       matchesAnyPattern(
         packageFile,
-        packageFilters.map((filter) => filter.replace(/\/?$/, '/package.json'))
+        packageFilters.map((filter) => filter.replace(/\/?$/, '/package.json')) // TODO #12070 #12071
       );
     if (isPackageInWorkspace) {
       p.pnpmShrinkwrap = lockFilePath;
diff --git a/lib/manager/npm/post-update/index.ts b/lib/manager/npm/post-update/index.ts
index 0742fbafbc..fa6830da0b 100644
--- a/lib/manager/npm/post-update/index.ts
+++ b/lib/manager/npm/post-update/index.ts
@@ -23,6 +23,7 @@ import {
 } from '../../../util/fs';
 import { branchExists, getFile, getRepoStatus } from '../../../util/git';
 import * as hostRules from '../../../util/host-rules';
+import { regEx } from '../../../util/regex';
 import type { PackageFile, PostUpdateConfig, Upgrade } from '../../types';
 import { getZeroInstallPaths } from '../extract/yarn';
 import * as lerna from './lerna';
@@ -340,8 +341,8 @@ async function updateYarnOffline(
       if (mirrorLine) {
         const mirrorPath = mirrorLine
           .split(' ')[1]
-          .replace(/"/g, '')
-          .replace(/\/?$/, '/');
+          .replace(regEx(/"/g), '')
+          .replace(regEx(/\/?$/), '/');
         resolvedPaths.push(upath.join(lockFileDir, mirrorPath));
       }
     }
@@ -489,7 +490,7 @@ export async function getAdditionalFiles(
         logger.debug(`${npmLock} needs updating`);
         updatedArtifacts.push({
           name: npmLock,
-          contents: res.lockFile.replace(new RegExp(`${token}`, 'g'), ''),
+          contents: res.lockFile.replace(regEx(`${token}`, 'g'), ''),
         });
       }
     }
diff --git a/lib/manager/npm/post-update/node-version.ts b/lib/manager/npm/post-update/node-version.ts
index 7c4daa8baf..8c44d201ea 100644
--- a/lib/manager/npm/post-update/node-version.ts
+++ b/lib/manager/npm/post-update/node-version.ts
@@ -1,6 +1,7 @@
 import { satisfies, validRange } from 'semver';
 import { logger } from '../../../logger';
 import { getSiblingFileName, readLocalFile } from '../../../util/fs';
+import { regEx } from '../../../util/regex';
 import { isStable } from '../../../versioning/node';
 import type { PostUpdateConfig } from '../../types';
 
@@ -8,7 +9,7 @@ async function getNodeFile(filename: string): Promise<string> | null {
   try {
     const constraint = (await readLocalFile(filename, 'utf8'))
       .split('\n')[0]
-      .replace(/^v/, '');
+      .replace(regEx(/^v/), '');
     if (validRange(constraint)) {
       logger.debug(`Using node constraint "${constraint}" from ${filename}`);
       return constraint;
diff --git a/lib/manager/npm/post-update/rules.ts b/lib/manager/npm/post-update/rules.ts
index a228783513..0b7cc70bd1 100644
--- a/lib/manager/npm/post-update/rules.ts
+++ b/lib/manager/npm/post-update/rules.ts
@@ -1,5 +1,6 @@
 import is from '@sindresorhus/is';
 import * as hostRules from '../../../util/host-rules';
+import { regEx } from '../../../util/regex';
 import { validateUrl } from '../../../util/url';
 
 export interface HostRulesResult {
@@ -18,7 +19,7 @@ export function processHostRules(): HostRulesResult {
   for (const hostRule of npmHostRules) {
     if (hostRule.resolvedHost) {
       let uri = hostRule.matchHost;
-      uri = validateUrl(uri) ? uri.replace(/^https?:/, '') : `//${uri}/`;
+      uri = validateUrl(uri) ? uri.replace(regEx(/^https?:/), '') : `//${uri}/`; // TODO #12071
       if (hostRule.token) {
         const key = hostRule.authType === 'Basic' ? '_auth' : '_authToken';
         additionalNpmrcContent.push(`${uri}:${key}=${hostRule.token}`);
diff --git a/lib/manager/npm/post-update/yarn.ts b/lib/manager/npm/post-update/yarn.ts
index 24e15f9ef6..1ca1c95233 100644
--- a/lib/manager/npm/post-update/yarn.ts
+++ b/lib/manager/npm/post-update/yarn.ts
@@ -12,6 +12,7 @@ import { logger } from '../../../logger';
 import { ExternalHostError } from '../../../types/errors/external-host-error';
 import { ExecOptions, exec } from '../../../util/exec';
 import { readFile, remove } from '../../../util/fs';
+import { regEx } from '../../../util/regex';
 import type { PostUpdateConfig, Upgrade } from '../../types';
 import { getNodeConstraint } from './node-version';
 import { GenerateLockFileResult } from './types';
@@ -32,7 +33,7 @@ export async function checkYarnrc(
         .split('\n')
         .find((line) => line.startsWith('yarn-path '));
       if (pathLine) {
-        yarnPath = pathLine.replace(/^yarn-path\s+"?(.+?)"?$/, '$1');
+        yarnPath = pathLine.replace(regEx(/^yarn-path\s+"?(.+?)"?$/), '$1');
       }
     }
   } catch (err) /* istanbul ignore next */ {
diff --git a/lib/manager/npm/update/locked-dependency/dep-constraints.ts b/lib/manager/npm/update/locked-dependency/dep-constraints.ts
index 3bdb1c8404..88e4eb4853 100644
--- a/lib/manager/npm/update/locked-dependency/dep-constraints.ts
+++ b/lib/manager/npm/update/locked-dependency/dep-constraints.ts
@@ -1,5 +1,6 @@
 import type { PackageJson } from 'type-fest';
 import { logger } from '../../../../logger';
+import { regEx } from '../../../../util/regex';
 import { api as semver } from '../../../../versioning/npm';
 import type { PackageLockOrEntry, ParentDependency } from './types';
 
@@ -31,7 +32,7 @@ export function findDepConstraints(
   if (parentDepName && requires) {
     let constraint = requires[depName];
     if (constraint) {
-      constraint = constraint.replace(/(\d)rc$/, '$1-rc');
+      constraint = constraint.replace(regEx(/(\d)rc$/), '$1-rc');
       // istanbul ignore else
       if (semver.isValid(constraint)) {
         if (semver.matches(currentVersion, constraint)) {
diff --git a/lib/manager/npm/update/package-version/index.ts b/lib/manager/npm/update/package-version/index.ts
index f45f1e1dfe..9644b59b47 100644
--- a/lib/manager/npm/update/package-version/index.ts
+++ b/lib/manager/npm/update/package-version/index.ts
@@ -31,7 +31,7 @@ export function bumpPackageVersion(
     }
     logger.debug({ newPjVersion });
     bumpedContent = content.replace(
-      /("version":\s*")[^"]*/,
+      /("version":\s*")[^"]*/, // TODO #12070
       `$1${newPjVersion}`
     );
     if (bumpedContent === content) {
diff --git a/lib/manager/nuget/artifacts.ts b/lib/manager/nuget/artifacts.ts
index 45175f3c15..34a910aad3 100644
--- a/lib/manager/nuget/artifacts.ts
+++ b/lib/manager/nuget/artifacts.ts
@@ -13,6 +13,7 @@ import {
   writeLocalFile,
 } from '../../util/fs';
 import * as hostRules from '../../util/host-rules';
+import { regEx } from '../../util/regex';
 import type {
   UpdateArtifact,
   UpdateArtifactsConfig,
@@ -88,7 +89,7 @@ export async function updateArtifacts({
 }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
   logger.debug(`nuget.updateArtifacts(${packageFileName})`);
 
-  if (!/(?:cs|vb|fs)proj$/i.test(packageFileName)) {
+  if (!regEx(/(?:cs|vb|fs)proj$/i).test(packageFileName)) {
     // This could be implemented in the future if necessary.
     // It's not that easy though because the questions which
     // project file to restore how to determine which lock files
diff --git a/lib/manager/nuget/extract.ts b/lib/manager/nuget/extract.ts
index f4d3af4cb2..a5e6ab86a7 100644
--- a/lib/manager/nuget/extract.ts
+++ b/lib/manager/nuget/extract.ts
@@ -21,7 +21,7 @@ import { getConfiguredRegistries } from './util';
  * so we don't include it in the extracting regexp
  */
 const checkVersion =
-  /^\s*(?:[[])?(?:(?<currentValue>[^"(,[\]]+)\s*(?:,\s*[)\]]|])?)\s*$/;
+  /^\s*(?:[[])?(?:(?<currentValue>[^"(,[\]]+)\s*(?:,\s*[)\]]|])?)\s*$/; // TODO #12070
 const elemNames = new Set([
   'PackageReference',
   'PackageVersion',
diff --git a/lib/manager/nuget/util.ts b/lib/manager/nuget/util.ts
index d7fcd54f03..526474edbc 100644
--- a/lib/manager/nuget/util.ts
+++ b/lib/manager/nuget/util.ts
@@ -5,6 +5,7 @@ import { XmlDocument } from 'xmldoc';
 import * as datasourceNuget from '../../datasource/nuget';
 import { logger } from '../../logger';
 import { readFile } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { Registry } from './types';
 
 async function readFileAsXmlDocument(file: string): Promise<XmlDocument> {
@@ -68,7 +69,7 @@ export async function getConfiguredRegistries(
         logger.debug(`clearing registry URLs`);
         registries.length = 0;
       } else if (child.name === 'add') {
-        const isHttpUrl = /^https?:\/\//i.test(child.attr.value);
+        const isHttpUrl = regEx(/^https?:\/\//i).test(child.attr.value); // TODO #12071
         if (isHttpUrl) {
           let registryUrl = child.attr.value;
           if (child.attr.protocolVersion) {
diff --git a/lib/manager/pip-compile/artifacts.ts b/lib/manager/pip-compile/artifacts.ts
index 58056c07d9..ecd23f1c79 100644
--- a/lib/manager/pip-compile/artifacts.ts
+++ b/lib/manager/pip-compile/artifacts.ts
@@ -5,6 +5,7 @@ import { logger } from '../../logger';
 import { ExecOptions, exec } from '../../util/exec';
 import { deleteLocalFile, readLocalFile, writeLocalFile } from '../../util/fs';
 import { getRepoStatus } from '../../util/git';
+import { regEx } from '../../util/regex';
 import type {
   UpdateArtifact,
   UpdateArtifactsConfig,
@@ -42,7 +43,7 @@ export async function updateArtifacts({
   newPackageFileContent: newInputContent,
   config,
 }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
-  const outputFileName = inputFileName.replace(/(\.in)?$/, '.txt');
+  const outputFileName = inputFileName.replace(regEx(/(\.in)?$/), '.txt');
   logger.debug(
     `pipCompile.updateArtifacts(${inputFileName}->${outputFileName})`
   );
diff --git a/lib/manager/pip_requirements/artifacts.ts b/lib/manager/pip_requirements/artifacts.ts
index ade3806b51..4725a5a938 100644
--- a/lib/manager/pip_requirements/artifacts.ts
+++ b/lib/manager/pip_requirements/artifacts.ts
@@ -3,6 +3,7 @@ import { TEMPORARY_ERROR } from '../../constants/error-messages';
 import { logger } from '../../logger';
 import { ExecOptions, exec } from '../../util/exec';
 import { readLocalFile } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
 
 export async function updateArtifacts({
@@ -18,7 +19,7 @@ export async function updateArtifacts({
   }
   try {
     const cmd: string[] = [];
-    const rewrittenContent = newPackageFileContent.replace(/\\\n/g, '');
+    const rewrittenContent = newPackageFileContent.replace(regEx(/\\\n/g), '');
     const lines = rewrittenContent.split('\n').map((line) => line.trim());
     for (const dep of updatedDeps) {
       const hashLine = lines.find(
diff --git a/lib/manager/pip_requirements/extract.ts b/lib/manager/pip_requirements/extract.ts
index 183abeb53c..01cff069da 100644
--- a/lib/manager/pip_requirements/extract.ts
+++ b/lib/manager/pip_requirements/extract.ts
@@ -5,6 +5,7 @@ import { PypiDatasource } from '../../datasource/pypi';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { isSkipComment } from '../../util/ignore';
+import { regEx } from '../../util/regex';
 import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 
 export const packagePattern =
@@ -12,7 +13,10 @@ export const packagePattern =
 const extrasPattern = '(?:\\s*\\[[^\\]]+\\])?';
 
 const rangePattern: string = RANGE_PATTERN;
-const specifierPartPattern = `\\s*${rangePattern.replace(/\?<\w+>/g, '?:')}`;
+const specifierPartPattern = `\\s*${rangePattern.replace(
+  regEx(/\?<\w+>/g),
+  '?:'
+)}`;
 const specifierPattern = `${specifierPartPattern}(?:\\s*,${specifierPartPattern})*`;
 export const dependencyPattern = `(${packagePattern})(${extrasPattern})(${specifierPattern})`;
 
@@ -49,7 +53,7 @@ export function extractPackageFile(
   }
   registryUrls = registryUrls.concat(extraUrls);
 
-  const regex = new RegExp(`^${dependencyPattern}$`, 'g');
+  const regex = regEx(`^${dependencyPattern}$`, 'g');
   const deps = content
     .split('\n')
     .map((rawline) => {
@@ -84,15 +88,18 @@ export function extractPackageFile(
   if (registryUrls.length > 0) {
     res.registryUrls = registryUrls.map((url) => {
       // handle the optional quotes in eg. `--extra-index-url "https://foo.bar"`
-      const cleaned = url.replace(/^"/, '').replace(/"$/, '');
+      const cleaned = url.replace(regEx(/^"/), '').replace(regEx(/"$/), ''); // TODO #12071
       if (!getGlobalConfig().exposeAllEnv) {
         return cleaned;
       }
       // interpolate any environment variables
       return cleaned.replace(
-        /(\$[A-Za-z\d_]+)|(\${[A-Za-z\d_]+})/g,
+        regEx(/(\$[A-Za-z\d_]+)|(\${[A-Za-z\d_]+})/g), // TODO #12071
         (match) => {
-          const envvar = match.substring(1).replace(/^{/, '').replace(/}$/, '');
+          const envvar = match
+            .substring(1)
+            .replace(regEx(/^{/), '')
+            .replace(regEx(/}$/), ''); // TODO #12071
           const sub = process.env[envvar];
           return sub || match;
         }
diff --git a/lib/manager/pip_setup/extract.ts b/lib/manager/pip_setup/extract.ts
index 1745e85ea6..97cb24ce76 100644
--- a/lib/manager/pip_setup/extract.ts
+++ b/lib/manager/pip_setup/extract.ts
@@ -4,6 +4,7 @@ import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { exec } from '../../util/exec';
 import { isSkipComment } from '../../util/ignore';
+import { regEx } from '../../util/regex';
 import { dependencyPattern } from '../pip_requirements/extract';
 import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 import type { PythonSetup } from './types';
@@ -63,7 +64,7 @@ export async function extractSetupFile(
   });
   if (res.stderr) {
     const stderr = res.stderr
-      .replace(/.*\n\s*import imp/, '')
+      .replace(regEx(/.*\n\s*import imp/), '')
       .trim()
       .replace('fatal: No names found, cannot describe anything.', '');
     if (stderr.length) {
@@ -97,7 +98,7 @@ export async function extractPackageFile(
       requires.push(...req);
     }
   }
-  const regex = new RegExp(`^${dependencyPattern}`);
+  const regex = regEx(`^${dependencyPattern}`);
   const lines = content.split('\n');
   const deps = requires
     .map((req) => {
diff --git a/lib/manager/pipenv/extract.ts b/lib/manager/pipenv/extract.ts
index 9c6cbe5361..1bad1beb61 100644
--- a/lib/manager/pipenv/extract.ts
+++ b/lib/manager/pipenv/extract.ts
@@ -5,15 +5,16 @@ import { PypiDatasource } from '../../datasource/pypi';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
 import { localPathExists } from '../../util/fs';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import type { PipFile } from './types';
 
 // based on https://www.python.org/dev/peps/pep-0508/#names
-const packageRegex = /^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$/i;
+const packageRegex = regEx(/^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$/i);
 const rangePattern: string = RANGE_PATTERN;
 
 const specifierPartPattern = `\\s*${rangePattern.replace(
-  /\?<\w+>/g,
+  regEx(/\?<\w+>/g),
   '?:'
 )}\\s*`;
 const specifierPattern = `${specifierPartPattern}(?:,${specifierPartPattern})*`;
@@ -24,7 +25,7 @@ function extractFromSection(
   if (!(section in pipfile)) {
     return [];
   }
-  const specifierRegex = new RegExp(`^${specifierPattern}$`);
+  const specifierRegex = regEx(`^${specifierPattern}$`);
   const pipfileSection = pipfile[section];
 
   const deps = Object.entries(pipfileSection)
diff --git a/lib/manager/pre-commit/extract.ts b/lib/manager/pre-commit/extract.ts
index aef244b22b..9e0dec1d7b 100644
--- a/lib/manager/pre-commit/extract.ts
+++ b/lib/manager/pre-commit/extract.ts
@@ -89,13 +89,13 @@ function extractDependency(
     // This splits "git@private.registry.com:user/repo" -> "private.registry.com" "user/repo
     regEx('^git@(?<hostname>[^:]+):(?<depName>\\S*)'),
     // This split "git://github.com/pre-commit/pre-commit-hooks" -> "github.com" "pre-commit/pre-commit-hooks"
-    /^git:\/\/(?<hostname>[^/]+)\/(?<depName>\S*)/,
+    regEx(/^git:\/\/(?<hostname>[^/]+)\/(?<depName>\S*)/),
   ];
   for (const urlMatcher of urlMatchers) {
     const match = urlMatcher.exec(repository);
     if (match) {
       const hostname = match.groups.hostname;
-      const depName = match.groups.depName.replace(/\.git$/i, '');
+      const depName = match.groups.depName.replace(regEx(/\.git$/i), ''); // TODO 12071
       const sourceDef = determineDatasource(repository, hostname);
       return {
         ...sourceDef,
diff --git a/lib/manager/sbt/extract.ts b/lib/manager/sbt/extract.ts
index f83f81648c..25d11b30cd 100644
--- a/lib/manager/sbt/extract.ts
+++ b/lib/manager/sbt/extract.ts
@@ -2,38 +2,42 @@ import * as datasourceMaven from '../../datasource/maven';
 import { MAVEN_REPO } from '../../datasource/maven/common';
 import * as datasourceSbtPackage from '../../datasource/sbt-package';
 import * as datasourceSbtPlugin from '../../datasource/sbt-plugin';
+import { regEx } from '../../util/regex';
 import { get } from '../../versioning';
 import * as mavenVersioning from '../../versioning/maven';
 import type { PackageDependency, PackageFile } from '../types';
 import type { ParseContext, ParseOptions } from './types';
 
-const stripComment = (str: string): string => str.replace(/(^|\s+)\/\/.*$/, '');
+const stripComment = (str: string): string =>
+  str.replace(regEx(/(^|\s+)\/\/.*$/), '');
 
 const isSingleLineDep = (str: string): boolean =>
-  /^\s*(libraryDependencies|dependencyOverrides)\s*\+=\s*/.test(str);
+  regEx(/^\s*(libraryDependencies|dependencyOverrides)\s*\+=\s*/).test(str);
 
 const isDepsBegin = (str: string): boolean =>
-  /^\s*(libraryDependencies|dependencyOverrides)\s*\+\+=\s*/.test(str);
+  regEx(/^\s*(libraryDependencies|dependencyOverrides)\s*\+\+=\s*/).test(str);
 
 const isPluginDep = (str: string): boolean =>
-  /^\s*addSbtPlugin\s*\(.*\)\s*$/.test(str);
+  regEx(/^\s*addSbtPlugin\s*\(.*\)\s*$/).test(str);
 
-const isStringLiteral = (str: string): boolean => /^"[^"]*"$/.test(str);
+const isStringLiteral = (str: string): boolean => regEx(/^"[^"]*"$/).test(str);
 
 const isScalaVersion = (str: string): boolean =>
-  /^\s*scalaVersion\s*:=\s*"[^"]*"[\s,]*$/.test(str);
+  regEx(/^\s*scalaVersion\s*:=\s*"[^"]*"[\s,]*$/).test(str);
 
 const getScalaVersion = (str: string): string =>
-  str.replace(/^\s*scalaVersion\s*:=\s*"/, '').replace(/"[\s,]*$/, '');
+  str
+    .replace(regEx(/^\s*scalaVersion\s*:=\s*"/), '')
+    .replace(regEx(/"[\s,]*$/), '');
 
 const isPackageFileVersion = (str: string): boolean =>
-  /^(version\s*:=\s*).*$/.test(str);
+  regEx(/^(version\s*:=\s*).*$/).test(str);
 
 const getPackageFileVersion = (str: string): string =>
   str
-    .replace(/^\s*version\s*:=\s*/, '')
-    .replace(/[\s,]*$/, '')
-    .replace(/"/g, '');
+    .replace(regEx(/^\s*version\s*:=\s*/), '')
+    .replace(regEx(/[\s,]*$/), '')
+    .replace(regEx(/"/g), '');
 
 /*
   https://www.scala-sbt.org/release/docs/Cross-Build.html#Publishing+conventions
@@ -54,62 +58,64 @@ const normalizeScalaVersion = (str: string): string => {
       return str;
     }
   }
-  if (/^\d+\.\d+\.\d+$/.test(str)) {
-    return str.replace(/^(\d+)\.(\d+)\.\d+$/, '$1.$2');
+  if (regEx(/^\d+\.\d+\.\d+$/).test(str)) {
+    return str.replace(regEx(/^(\d+)\.(\d+)\.\d+$/), '$1.$2');
   }
   // istanbul ignore next
   return str;
 };
 
 const isScalaVersionVariable = (str: string): boolean =>
-  /^\s*scalaVersion\s*:=\s*[_a-zA-Z][_a-zA-Z0-9]*[\s,]*$/.test(str);
+  regEx(/^\s*scalaVersion\s*:=\s*[_a-zA-Z][_a-zA-Z0-9]*[\s,]*$/).test(str);
 
 const getScalaVersionVariable = (str: string): string =>
-  str.replace(/^\s*scalaVersion\s*:=\s*/, '').replace(/[\s,]*$/, '');
+  str
+    .replace(regEx(/^\s*scalaVersion\s*:=\s*/), '')
+    .replace(regEx(/[\s,]*$/), '');
 
 const isResolver = (str: string): boolean =>
-  /^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"[^"]*"[\s,)]*$/.test(
-    str
-  );
+  regEx(
+    /^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"[^"]*"[\s,)]*$/
+  ).test(str);
 const getResolverUrl = (str: string): string =>
   str
-    .replace(/^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"/, '')
-    .replace(/"[\s,)]*$/, '');
+    .replace(regEx(/^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"/), '')
+    .replace(regEx(/"[\s,)]*$/), '');
 
 const isVarDependency = (str: string): boolean =>
-  /^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=.*(%%?).*%.*/.test(
-    str
-  );
+  regEx(
+    /^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=.*(%%?).*%.*/
+  ).test(str);
 
 const isVarDef = (str: string): boolean =>
-  /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"[^"]*"\s*$/.test(
-    str
-  );
+  regEx(
+    /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"[^"]*"\s*$/
+  ).test(str);
 
 const isVarSeqSingleLine = (str: string): boolean =>
-  /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*\).*\s*$/.test(
-    str
-  );
+  regEx(
+    /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*\).*\s*$/
+  ).test(str);
 
 const isVarSeqMultipleLine = (str: string): boolean =>
-  /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*[^)]*.*$/.test(
-    str
-  );
+  regEx(
+    /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*[^)]*.*$/
+  ).test(str);
 
 const getVarName = (str: string): string =>
   str
-    .replace(/^\s*(private\s*)?(lazy\s*)?val\s+/, '')
-    .replace(/\s*=\s*"[^"]*"\s*$/, '');
+    .replace(regEx(/^\s*(private\s*)?(lazy\s*)?val\s+/), '')
+    .replace(regEx(/\s*=\s*"[^"]*"\s*$/), '');
 
 const isVarName = (str: string): boolean =>
-  /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(str);
+  regEx(/^[_a-zA-Z][_a-zA-Z0-9]*$/).test(str);
 
 const getVarInfo = (str: string, ctx: ParseContext): { val: string } => {
   const rightPart = str.replace(
-    /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"/,
+    regEx(/^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"/),
     ''
   );
-  const val = rightPart.replace(/"\s*$/, '');
+  const val = rightPart.replace(regEx(/"\s*$/), '');
   return { val };
 };
 
@@ -125,15 +131,15 @@ function parseDepExpr(
 
   const resolveToken = (str: string): string =>
     isStringLiteral(str)
-      ? str.replace(/^"/, '').replace(/"$/, '')
+      ? str.replace(regEx(/^"/), '').replace(regEx(/"$/), '')
       : variables[str].val;
 
   const tokens = expr
     .trim()
-    .split(/("[^"]*")/g)
-    .map((x) => (/"[^"]*"/.test(x) ? x : x.replace(/[()]+/g, '')))
+    .split(regEx(/("[^"]*")/g))
+    .map((x) => (regEx(/"[^"]*"/).test(x) ? x : x.replace(regEx(/[()]+/g), ''))) // TODO #12071
     .join('')
-    .split(/\s*(%%?)\s*|\s*classifier\s*/);
+    .split(regEx(/\s*(%%?)\s*|\s*classifier\s*/));
 
   const [
     rawGroupId,
@@ -183,7 +189,7 @@ function parseDepExpr(
   const currentValue = resolveToken(rawVersion);
 
   if (!depType && rawScope) {
-    depType = rawScope.replace(/^"/, '').replace(/"$/, '');
+    depType = rawScope.replace(regEx(/^"/), '').replace(regEx(/"$/), '');
   }
 
   const result: PackageDependency = {
@@ -243,13 +249,15 @@ function parseSbtLine(
       registryUrls.push(url);
     } else if (isVarSeqSingleLine(line)) {
       isMultiDeps = false;
-      const depExpr = line.replace(/^.*Seq\(\s*/, '').replace(/\).*$/, '');
+      const depExpr = line
+        .replace(regEx(/^.*Seq\(\s*/), '')
+        .replace(regEx(/\).*$/), '');
       dep = parseDepExpr(depExpr, {
         ...ctx,
       });
     } else if (isVarSeqMultipleLine(line)) {
       isMultiDeps = true;
-      const depExpr = line.replace(/^.*Seq\(\s*/, '');
+      const depExpr = line.replace(regEx(/^.*Seq\(\s*/), '');
       dep = parseDepExpr(depExpr, {
         ...ctx,
       });
@@ -258,7 +266,7 @@ function parseSbtLine(
     } else if (isVarDependency(line)) {
       isMultiDeps = false;
       const depExpr = line.replace(
-        /^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*/,
+        regEx(/^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*/),
         ''
       );
       dep = parseDepExpr(depExpr, {
@@ -266,14 +274,14 @@ function parseSbtLine(
       });
     } else if (isSingleLineDep(line)) {
       isMultiDeps = false;
-      const depExpr = line.replace(/^.*\+=\s*/, '');
+      const depExpr = line.replace(regEx(/^.*\+=\s*/), '');
       dep = parseDepExpr(depExpr, {
         ...ctx,
       });
     } else if (isPluginDep(line)) {
       isMultiDeps = false;
-      const rightPart = line.replace(/^\s*addSbtPlugin\s*\(/, '');
-      const depExpr = rightPart.replace(/\)\s*$/, '');
+      const rightPart = line.replace(regEx(/^\s*addSbtPlugin\s*\(/), '');
+      const depExpr = rightPart.replace(regEx(/\)\s*$/), '');
       dep = parseDepExpr(depExpr, {
         ...ctx,
         depType: 'plugin',
@@ -281,8 +289,8 @@ function parseSbtLine(
     } else if (isDepsBegin(line)) {
       isMultiDeps = true;
     } else if (isMultiDeps) {
-      const rightPart = line.replace(/^[\s,]*/, '');
-      const depExpr = rightPart.replace(/[\s,]*$/, '');
+      const rightPart = line.replace(regEx(/^[\s,]*/), '');
+      const depExpr = rightPart.replace(regEx(/[\s,]*$/), '');
       dep = parseDepExpr(depExpr, {
         ...ctx,
       });
@@ -332,7 +340,7 @@ export function extractPackageFile(content: string): PackageFile {
   if (!content) {
     return null;
   }
-  const lines = content.split(/\n/).map(stripComment);
+  const lines = content.split(regEx(/\n/)).map(stripComment);
   return lines.reduce(parseSbtLine, {
     registryUrls: [MAVEN_REPO],
     deps: [],
diff --git a/lib/manager/sbt/update.ts b/lib/manager/sbt/update.ts
index afab698d95..f15ef8882f 100644
--- a/lib/manager/sbt/update.ts
+++ b/lib/manager/sbt/update.ts
@@ -1,5 +1,6 @@
 import { ReleaseType, inc } from 'semver';
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import type { BumpPackageVersionResult } from '../types';
 
 export function bumpPackageVersion(
@@ -18,7 +19,7 @@ export function bumpPackageVersion(
     return { bumpedContent };
   }
   bumpedContent = content.replace(
-    /^(version\s*:=\s*).*$/m,
+    regEx(/^(version\s*:=\s*).*$/m),
     `$1"${bumpedVersion}"`
   );
 
diff --git a/lib/manager/setup-cfg/extract.ts b/lib/manager/setup-cfg/extract.ts
index 6fdb150fa6..7ab666964a 100644
--- a/lib/manager/setup-cfg/extract.ts
+++ b/lib/manager/setup-cfg/extract.ts
@@ -1,14 +1,15 @@
 import { PypiDatasource } from '../../datasource/pypi';
+import { regEx } from '../../util/regex';
 import pep440 from '../../versioning/pep440';
 import type { PackageDependency, PackageFile, Result } from '../types';
 
 function getSectionName(str: string): string {
-  const [, sectionName] = /^\[\s*([^\s]+)\s*]\s*$/.exec(str) || [];
+  const [, sectionName] = regEx(/^\[\s*([^\s]+)\s*]\s*$/).exec(str) || []; // TODO #12071
   return sectionName;
 }
 
 function getSectionRecord(str: string): string {
-  const [, sectionRecord] = /^([^\s]+)\s+=/.exec(str) || [];
+  const [, sectionRecord] = regEx(/^([^\s]+)\s+=/).exec(str) || []; // TODO #12071
   return sectionRecord;
 }
 
@@ -33,7 +34,7 @@ function parseDep(
   record: string
 ): PackageDependency | null {
   const [, depName, , currentValue] =
-    /\s+([-_a-zA-Z0-9]*)(\[.*\])?\s*(.*)/.exec(line) || [];
+    regEx(/\s+([-_a-zA-Z0-9]*)(\[.*\])?\s*(.*)/).exec(line) || [];
   if (
     section &&
     record &&
@@ -64,7 +65,7 @@ export function extractPackageFile(
   const deps: PackageDependency[] = [];
   content
     .split('\n')
-    .map((line) => line.replace(/[;#].*$/, '').trimRight())
+    .map((line) => line.replace(regEx(/[;#].*$/), '').trimRight()) // TODO #12071
     .forEach((rawLine) => {
       let line = rawLine;
       const newSectionName = getSectionName(line);
@@ -74,7 +75,7 @@ export function extractPackageFile(
       } else {
         if (newSectionRecord) {
           sectionRecord = newSectionRecord;
-          line = rawLine.replace(/^[^=]*=\s*/, '\t');
+          line = rawLine.replace(regEx(/^[^=]*=\s*/), '\t'); // TODO #12071
         }
         const dep = parseDep(line, sectionName, sectionRecord);
         if (dep) {
diff --git a/lib/manager/swift/extract.ts b/lib/manager/swift/extract.ts
index f7feb08408..2000dd184c 100644
--- a/lib/manager/swift/extract.ts
+++ b/lib/manager/swift/extract.ts
@@ -1,21 +1,22 @@
 import * as datasourceGitTags from '../../datasource/git-tags';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import type { MatchResult } from './types';
 
 const regExps = {
-  wildcard: /^.*?/,
-  space: /(\s+|\/\/[^\n]*|\/\*.*\*\/)+/s,
-  depsKeyword: /dependencies/,
-  colon: /:/,
-  beginSection: /\[/,
-  endSection: /],?/,
-  package: /\s*.\s*package\s*\(\s*/,
-  urlKey: /url/,
-  stringLiteral: /"[^"]+"/,
-  comma: /,/,
-  from: /from/,
-  rangeOp: /\.\.[.<]/,
-  exactVersion: /\.\s*exact\s*\(\s*/,
+  wildcard: regEx(/^.*?/),
+  space: regEx(/(\s+|\/\/[^\n]*|\/\*.*\*\/)+/, 's'),
+  depsKeyword: regEx(/dependencies/),
+  colon: regEx(/:/),
+  beginSection: regEx(/\[/),
+  endSection: regEx(/],?/),
+  package: regEx(/\s*.\s*package\s*\(\s*/),
+  urlKey: regEx(/url/),
+  stringLiteral: regEx(/"[^"]+"/),
+  comma: regEx(/,/),
+  from: regEx(/from/),
+  rangeOp: regEx(/\.\.[.<]/),
+  exactVersion: regEx(/\.\s*exact\s*\(\s*/),
 };
 
 const WILDCARD = 'wildcard';
@@ -116,9 +117,9 @@ function getDepName(url: string): string | null {
     const { host, pathname } = new URL(url);
     if (host === 'github.com' || host === 'gitlab.com') {
       return pathname
-        .replace(/^\//, '')
-        .replace(/\.git$/, '')
-        .replace(/\/$/, '');
+        .replace(regEx(/^\//), '')
+        .replace(regEx(/\.git$/), '')
+        .replace(regEx(/\/$/), '');
     }
     return url;
   } catch (e) {
@@ -224,7 +225,7 @@ export function extractPackageFile(
           yieldDep();
           state = null;
         } else if (label === STRING_LITERAL) {
-          lookupName = substr.replace(/^"/, '').replace(/"$/, '');
+          lookupName = substr.replace(regEx(/^"/), '').replace(regEx(/"$/), '');
           state = '.package(url: [depName]';
         } else if (label === PACKAGE) {
           yieldDep();
diff --git a/lib/manager/terraform/extract.ts b/lib/manager/terraform/extract.ts
index e9912586b0..ad18986475 100644
--- a/lib/manager/terraform/extract.ts
+++ b/lib/manager/terraform/extract.ts
@@ -1,5 +1,6 @@
 import is from '@sindresorhus/is';
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
 import { TerraformDependencyTypes } from './common';
 import { extractLocks, findLockFile, readLockFile } from './lockfile/util';
@@ -26,8 +27,9 @@ import {
   getTerraformDependencyType,
 } from './util';
 
-const dependencyBlockExtractionRegex =
-  /^\s*(?<type>[a-z_]+)\s+("(?<lookupName>[^"]+)"\s+)?("(?<terraformName>[^"]+)"\s+)?{\s*$/;
+const dependencyBlockExtractionRegex = regEx(
+  /^\s*(?<type>[a-z_]+)\s+("(?<lookupName>[^"]+)"\s+)?("(?<terraformName>[^"]+)"\s+)?{\s*$/
+);
 const contentCheckList = [
   'module "',
   'provider "',
diff --git a/lib/manager/terraform/lockfile/hash.ts b/lib/manager/terraform/lockfile/hash.ts
index 4862d444da..94799f362c 100644
--- a/lib/manager/terraform/lockfile/hash.ts
+++ b/lib/manager/terraform/lockfile/hash.ts
@@ -31,7 +31,7 @@ export class TerraformProviderHash {
 
       // add double space, the filename and a new line char
       rootHash.update('  ');
-      const fileName = file.replace(/^.*[\\/]/, '');
+      const fileName = file.replace(/^.*[\\/]/, ''); // TODO #12070
       rootHash.update(fileName);
       rootHash.update('\n');
     }
diff --git a/lib/manager/terraform/lockfile/util.ts b/lib/manager/terraform/lockfile/util.ts
index d8282800fa..b439866582 100644
--- a/lib/manager/terraform/lockfile/util.ts
+++ b/lib/manager/terraform/lockfile/util.ts
@@ -9,12 +9,12 @@ import type {
 } from './types';
 
 const providerStartLineRegex =
-  /^provider "(?<registryUrl>[^/]*)\/(?<namespace>[^/]*)\/(?<depName>[^/]*)"/;
+  /^provider "(?<registryUrl>[^/]*)\/(?<namespace>[^/]*)\/(?<depName>[^/]*)"/; // TODO #12070
 const versionLineRegex =
-  /^(?<prefix>[\s]*version[\s]*=[\s]*")(?<version>[^"']+)(?<suffix>".*)$/;
+  /^(?<prefix>[\s]*version[\s]*=[\s]*")(?<version>[^"']+)(?<suffix>".*)$/; // TODO #12070
 const constraintLineRegex =
-  /^(?<prefix>[\s]*constraints[\s]*=[\s]*")(?<constraint>[^"']+)(?<suffix>".*)$/;
-const hashLineRegex = /^(?<prefix>\s*")(?<hash>[^"]+)(?<suffix>",.*)$/;
+  /^(?<prefix>[\s]*constraints[\s]*=[\s]*")(?<constraint>[^"']+)(?<suffix>".*)$/; // TODO #12070
+const hashLineRegex = /^(?<prefix>\s*")(?<hash>[^"]+)(?<suffix>",.*)$/; // TODO #12070
 
 const lockFile = '.terraform.lock.hcl';
 
diff --git a/lib/manager/terraform/modules.ts b/lib/manager/terraform/modules.ts
index a7903a0233..34f0d6c8f4 100644
--- a/lib/manager/terraform/modules.ts
+++ b/lib/manager/terraform/modules.ts
@@ -3,16 +3,19 @@ import * as datasourceGithubTags from '../../datasource/github-tags';
 import { TerraformModuleDatasource } from '../../datasource/terraform-module';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import { TerraformDependencyTypes } from './common';
 import { extractTerraformProvider } from './providers';
 import type { ExtractionResult } from './types';
 
-export const githubRefMatchRegex =
-  /github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i;
-export const gitTagsRefMatchRegex =
-  /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/;
-const hostnameMatchRegex = /^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/;
+export const githubRefMatchRegex = regEx(
+  /github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i
+);
+export const gitTagsRefMatchRegex = regEx(
+  /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/
+);
+const hostnameMatchRegex = regEx(/^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/);
 
 export function extractTerraformModule(
   startingLine: number,
@@ -32,7 +35,7 @@ export function analyseTerraformModule(dep: PackageDependency): void {
   const gitTagsRefMatch = gitTagsRefMatchRegex.exec(dep.managerData.source);
   /* eslint-disable no-param-reassign */
   if (githubRefMatch) {
-    dep.lookupName = githubRefMatch.groups.project.replace(/\.git$/, '');
+    dep.lookupName = githubRefMatch.groups.project.replace(regEx(/\.git$/), '');
     dep.depType = 'module';
     dep.depName = 'github.com/' + dep.lookupName;
     dep.currentValue = githubRefMatch.groups.tag;
diff --git a/lib/manager/terraform/providers.ts b/lib/manager/terraform/providers.ts
index 09e925df26..0b07a7251b 100644
--- a/lib/manager/terraform/providers.ts
+++ b/lib/manager/terraform/providers.ts
@@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
 import { TerraformProviderDatasource } from '../../datasource/terraform-provider';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import { TerraformDependencyTypes } from './common';
 import type { ProviderLock } from './lockfile/types';
@@ -12,8 +13,9 @@ import {
   massageProviderLookupName,
 } from './util';
 
-export const sourceExtractionRegex =
-  /^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/;
+export const sourceExtractionRegex = regEx(
+  /^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/
+);
 
 export function extractTerraformProvider(
   startingLine: number,
@@ -36,11 +38,12 @@ export function extractTerraformProvider(
     }
 
     const line = lines[lineNumber];
+
     // istanbul ignore next
     if (is.string(line)) {
       // `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block
-      const openBrackets = (line.match(/\{/g) || []).length;
-      const closedBrackets = (line.match(/\}/g) || []).length;
+      const openBrackets = (line.match(/\{/g) || []).length; // TODO #12071 #12070
+      const closedBrackets = (line.match(/\}/g) || []).length; // TODO #12071 #12070
       braceCounter = braceCounter + openBrackets - closedBrackets;
 
       // only update fields inside the root block
diff --git a/lib/manager/terraform/required-providers.ts b/lib/manager/terraform/required-providers.ts
index 95c7f0d25f..6ac73de512 100644
--- a/lib/manager/terraform/required-providers.ts
+++ b/lib/manager/terraform/required-providers.ts
@@ -1,3 +1,4 @@
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import { TerraformDependencyTypes } from './common';
 import type { ProviderLock } from './lockfile/types';
@@ -5,7 +6,7 @@ import { analyzeTerraformProvider } from './providers';
 import type { ExtractionResult } from './types';
 import { keyValueExtractionRegex } from './util';
 
-export const providerBlockExtractionRegex = /^\s*(?<key>[^\s]+)\s+=\s+{/;
+export const providerBlockExtractionRegex = regEx(/^\s*(?<key>[^\s]+)\s+=\s+{/);
 
 function extractBlock(
   lineNum: number,
diff --git a/lib/manager/terraform/required-version.ts b/lib/manager/terraform/required-version.ts
index d5f6020389..dc16f52211 100644
--- a/lib/manager/terraform/required-version.ts
+++ b/lib/manager/terraform/required-version.ts
@@ -20,8 +20,8 @@ export function extractTerraformRequiredVersion(
 
     const line = lines[lineNumber];
     // `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block
-    const openBrackets = (line.match(/\{/g) || []).length;
-    const closedBrackets = (line.match(/\}/g) || []).length;
+    const openBrackets = (line.match(/\{/g) || []).length; // TODO #12070
+    const closedBrackets = (line.match(/\}/g) || []).length; // TODO #12070
     braceCounter = braceCounter + openBrackets - closedBrackets;
 
     const kvMatch = keyValueExtractionRegex.exec(line);
diff --git a/lib/manager/terraform/util.ts b/lib/manager/terraform/util.ts
index 10082d7d55..9793c547c1 100644
--- a/lib/manager/terraform/util.ts
+++ b/lib/manager/terraform/util.ts
@@ -1,12 +1,15 @@
 import { TerraformProviderDatasource } from '../../datasource/terraform-provider';
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import { TerraformDependencyTypes } from './common';
 import type { ProviderLock } from './lockfile/types';
 
-export const keyValueExtractionRegex =
-  /^\s*(?<key>[^\s]+)\s+=\s+"(?<value>[^"]+)"\s*$/;
-export const resourceTypeExtractionRegex =
-  /^\s*resource\s+"(?<type>[^\s]+)"\s+"(?<name>[^"]+)"\s*{/;
+export const keyValueExtractionRegex = regEx(
+  /^\s*(?<key>[^\s]+)\s+=\s+"(?<value>[^"]+)"\s*$/
+);
+export const resourceTypeExtractionRegex = regEx(
+  /^\s*resource\s+"(?<type>[^\s]+)"\s+"(?<name>[^"]+)"\s*{/
+);
 
 export function getTerraformDependencyType(
   value: string
@@ -40,7 +43,7 @@ export function checkFileContainsDependency(
   return checkList.some((check) => content.includes(check));
 }
 
-const pathStringRegex = /(.|..)?(\/[^/])+/;
+const pathStringRegex = regEx(/(.|..)?(\/[^/])+/);
 export function checkIfStringIsPath(path: string): boolean {
   const match = pathStringRegex.exec(path);
   return !!match;
diff --git a/lib/manager/terragrunt/extract.ts b/lib/manager/terragrunt/extract.ts
index 6f114a45f1..978359b6a8 100644
--- a/lib/manager/terragrunt/extract.ts
+++ b/lib/manager/terragrunt/extract.ts
@@ -1,4 +1,5 @@
 import { logger } from '../../logger';
+import { regEx } from '../../util/regex';
 import type { PackageDependency, PackageFile } from '../types';
 import { TerragruntDependencyTypes } from './common';
 import { analyseTerragruntModule, extractTerragruntModule } from './modules';
@@ -8,7 +9,7 @@ import {
   getTerragruntDependencyType,
 } from './util';
 
-const dependencyBlockExtractionRegex = /^\s*(?<type>[a-z_]+)\s+{\s*$/;
+const dependencyBlockExtractionRegex = regEx(/^\s*(?<type>[a-z_]+)\s+{\s*$/);
 const contentCheckList = ['terraform {'];
 
 export function extractPackageFile(content: string): PackageFile | null {
diff --git a/lib/manager/terragrunt/modules.ts b/lib/manager/terragrunt/modules.ts
index 3b3f0e4ba5..be070cbd40 100644
--- a/lib/manager/terragrunt/modules.ts
+++ b/lib/manager/terragrunt/modules.ts
@@ -3,16 +3,19 @@ import * as datasourceGithubTags from '../../datasource/github-tags';
 import { TerraformModuleDatasource } from '../../datasource/terraform-module';
 import { logger } from '../../logger';
 import { SkipReason } from '../../types';
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import { TerragruntDependencyTypes } from './common';
 import { extractTerragruntProvider } from './providers';
 import type { ExtractionResult } from './types';
 
-export const githubRefMatchRegex =
-  /github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i;
-export const gitTagsRefMatchRegex =
-  /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/;
-const hostnameMatchRegex = /^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/;
+export const githubRefMatchRegex = regEx(
+  /github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i
+);
+export const gitTagsRefMatchRegex = regEx(
+  /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/
+);
+const hostnameMatchRegex = regEx(/^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/);
 
 export function extractTerragruntModule(
   startingLine: number,
@@ -34,7 +37,7 @@ export function analyseTerragruntModule(dep: PackageDependency): void {
   /* eslint-disable no-param-reassign */
   if (githubRefMatch) {
     dep.depType = 'github';
-    dep.lookupName = githubRefMatch.groups.project.replace(/\.git$/, '');
+    dep.lookupName = githubRefMatch.groups.project.replace(regEx(/\.git$/), '');
     dep.depName = 'github.com/' + dep.lookupName;
     dep.currentValue = githubRefMatch.groups.tag;
     dep.datasource = datasourceGithubTags.id;
diff --git a/lib/manager/terragrunt/providers.ts b/lib/manager/terragrunt/providers.ts
index 284a6053a3..f44650ecee 100644
--- a/lib/manager/terragrunt/providers.ts
+++ b/lib/manager/terragrunt/providers.ts
@@ -1,10 +1,12 @@
+import { regEx } from '../../util/regex';
 import type { PackageDependency } from '../types';
 import { TerragruntDependencyTypes } from './common';
 import type { ExtractionResult } from './types';
 import { keyValueExtractionRegex } from './util';
 
-export const sourceExtractionRegex =
-  /^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/;
+export const sourceExtractionRegex = regEx(
+  /^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/
+);
 
 function extractBracesContent(content): number {
   const stack = [];
diff --git a/lib/manager/terragrunt/util.ts b/lib/manager/terragrunt/util.ts
index 63ebc18956..b920ebb934 100644
--- a/lib/manager/terragrunt/util.ts
+++ b/lib/manager/terragrunt/util.ts
@@ -1,6 +1,9 @@
+import { regEx } from '../../util/regex';
 import { TerragruntDependencyTypes } from './common';
 
-export const keyValueExtractionRegex = /^\s*source\s+=\s+"(?<value>[^"]+)"\s*$/;
+export const keyValueExtractionRegex = regEx(
+  /^\s*source\s+=\s+"(?<value>[^"]+)"\s*$/
+);
 
 export function getTerragruntDependencyType(
   value: string
diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts
index 60185e64fb..f0bfd15f20 100644
--- a/lib/platform/azure/index.ts
+++ b/lib/platform/azure/index.ts
@@ -14,6 +14,7 @@ import { logger } from '../../logger';
 import { BranchStatus, PrState, VulnerabilityAlert } from '../../types';
 import * as git from '../../util/git';
 import * as hostRules from '../../util/host-rules';
+import { regEx } from '../../util/regex';
 import { sanitize } from '../../util/sanitize';
 import { ensureTrailingSlash } from '../../util/url';
 import type {
@@ -678,7 +679,7 @@ export function massageMarkdown(input: string): string {
       'you tick the rebase/retry checkbox',
       'rename PR to start with "rebase!"'
     )
-    .replace(new RegExp(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '');
+    .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '');
 }
 
 /* istanbul ignore next */
diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts
index d88faecdf3..9612e13570 100644
--- a/lib/platform/bitbucket-server/index.ts
+++ b/lib/platform/bitbucket-server/index.ts
@@ -20,6 +20,7 @@ import {
   BitbucketServerHttp,
   setBaseUrl,
 } from '../../util/http/bitbucket-server';
+import { regEx } from '../../util/regex';
 import { sanitize } from '../../util/sanitize';
 import { ensureTrailingSlash, getQueryString } from '../../util/url';
 import type {
@@ -784,7 +785,7 @@ export async function ensureCommentRemoval({
 // Pull Request
 
 const escapeHash = (input: string): string =>
-  input ? input.replace(/#/g, '%23') : input;
+  input ? input.replace(regEx(/#/g), '%23') : input;
 
 export async function createPr({
   sourceBranch,
@@ -991,10 +992,10 @@ export function massageMarkdown(input: string): string {
       'you tick the rebase/retry checkbox',
       'rename PR to start with "rebase!"'
     )
-    .replace(/<\/?summary>/g, '**')
-    .replace(/<\/?details>/g, '')
-    .replace(new RegExp(`\n---\n\n.*?<!-- rebase-check -->.*?(\n|$)`), '')
-    .replace(new RegExp('<!--.*?-->', 'g'), '');
+    .replace(regEx(/<\/?summary>/g), '**')
+    .replace(regEx(/<\/?details>/g), '')
+    .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?(\n|$)`), '')
+    .replace(regEx('<!--.*?-->', 'g'), '');
 }
 
 export function getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]> {
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index aca5adc95b..c2e4db583b 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -8,6 +8,7 @@ import { BranchStatus, PrState, VulnerabilityAlert } from '../../types';
 import * as git from '../../util/git';
 import * as hostRules from '../../util/host-rules';
 import { BitbucketHttp, setBaseUrl } from '../../util/http/bitbucket';
+import { regEx } from '../../util/regex';
 import { sanitize } from '../../util/sanitize';
 import type {
   BranchStatusConfig,
@@ -173,7 +174,7 @@ export async function initRepo({
   // Converts API hostnames to their respective HTTP git hosts:
   // `api.bitbucket.org`  to `bitbucket.org`
   // `api-staging.<host>` to `staging.<host>`
-  const hostnameWithoutApiPrefix = /api[.|-](.+)/.exec(hostname)[1];
+  const hostnameWithoutApiPrefix = regEx(/api[.|-](.+)/).exec(hostname)[1];
 
   const url = git.getUrl({
     protocol: 'https',
@@ -286,7 +287,7 @@ export async function getPr(prNo: number): Promise<Pr | null> {
 }
 
 const escapeHash = (input: string): string =>
-  input ? input.replace(/#/g, '%23') : input;
+  input ? input.replace(regEx(/#/g), '%23') : input;
 
 interface BranchResponse {
   target: {
@@ -462,10 +463,10 @@ export function massageMarkdown(input: string): string {
       'you tick the rebase/retry checkbox',
       'rename PR to start with "rebase!"'
     )
-    .replace(/<\/?summary>/g, '**')
-    .replace(/<\/?details>/g, '')
-    .replace(new RegExp(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '')
-    .replace(/\]\(\.\.\/pull\//g, '](../../pull-requests/');
+    .replace(regEx(/<\/?summary>/g), '**')
+    .replace(regEx(/<\/?details>/g), '')
+    .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '')
+    .replace(regEx(/\]\(\.\.\/pull\//g), '](../../pull-requests/');
 }
 
 export async function ensureIssue({
diff --git a/lib/platform/gitea/utils.ts b/lib/platform/gitea/utils.ts
index d9cfe3495f..492644bf7d 100644
--- a/lib/platform/gitea/utils.ts
+++ b/lib/platform/gitea/utils.ts
@@ -1,3 +1,5 @@
+import { regEx } from '../../util/regex';
+
 export function smartLinks(body: string): string {
-  return body?.replace(/\]\(\.\.\/pull\//g, '](pulls/');
+  return body?.replace(regEx(/\]\(\.\.\/pull\//g), '](pulls/');
 }
diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts
index aa7debfa87..457cd5bb67 100644
--- a/lib/platform/github/index.ts
+++ b/lib/platform/github/index.ts
@@ -23,6 +23,7 @@ import { getCache } from '../../util/cache/repository';
 import * as git from '../../util/git';
 import * as hostRules from '../../util/host-rules';
 import * as githubHttp from '../../util/http/github';
+import { regEx } from '../../util/regex';
 import { sanitize } from '../../util/sanitize';
 import { ensureTrailingSlash } from '../../util/url';
 import type {
@@ -78,7 +79,7 @@ const defaults = {
 };
 
 const escapeHash = (input: string): string =>
-  input ? input.replace(/#/g, '%23') : input;
+  input ? input.replace(regEx(/#/g), '%23') : input;
 
 export async function initPlatform({
   endpoint,
@@ -768,7 +769,7 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> {
       return null;
     }
     try {
-      const title = autoclosedPr.title.replace(/ - autoclosed$/, '');
+      const title = autoclosedPr.title.replace(regEx(/ - autoclosed$/), '');
       await githubApi.patchJson(`repos/${config.repository}/pulls/${number}`, {
         body: {
           state: 'open',
@@ -1181,7 +1182,7 @@ export async function addReviewers(
   const userReviewers = reviewers.filter((e) => !e.startsWith('team:'));
   const teamReviewers = reviewers
     .filter((e) => e.startsWith('team:'))
-    .map((e) => e.replace(/^team:/, ''));
+    .map((e) => e.replace(regEx(/^team:/), '')); // TODO #12071
   try {
     await githubApi.postJson(
       `repos/${
@@ -1623,9 +1624,12 @@ export function massageMarkdown(input: string): string {
   }
   const massagedInput = massageMarkdownLinks(input)
     // to be safe, replace all github.com links with renovatebot redirector
-    .replace(/href="https?:\/\/github.com\//g, 'href="https://togithub.com/')
-    .replace(/]\(https:\/\/github\.com\//g, '](https://togithub.com/')
-    .replace(/]: https:\/\/github\.com\//g, ']: https://togithub.com/');
+    .replace(
+      regEx(/href="https?:\/\/github.com\//g),
+      'href="https://togithub.com/'
+    )
+    .replace(regEx(/]\(https:\/\/github\.com\//g), '](https://togithub.com/')
+    .replace(regEx(/]: https:\/\/github\.com\//g), ']: https://togithub.com/');
   return smartTruncate(massagedInput, 60000);
 }
 
diff --git a/lib/platform/github/massage-markdown-links.ts b/lib/platform/github/massage-markdown-links.ts
index 7c788b3f67..cbff68d00f 100644
--- a/lib/platform/github/massage-markdown-links.ts
+++ b/lib/platform/github/massage-markdown-links.ts
@@ -3,6 +3,7 @@ import remark from 'remark';
 import type { Plugin, Transformer } from 'unified';
 import { logger } from '../../logger';
 import { hasKey } from '../../util/object';
+import { regEx } from '../../util/regex';
 
 interface UrlMatch {
   start: number;
@@ -11,10 +12,10 @@ interface UrlMatch {
 }
 
 const urlRegex =
-  /(?:https?:)?(?:\/\/)?(?:www\.)?(?<!api\.)(?:to)?github\.com\/[-_a-z0-9]+\/[-_a-z0-9]+\/(?:discussions|issues|pull)\/[0-9]+(?:#[-_a-z0-9]+)?/i;
+  /(?:https?:)?(?:\/\/)?(?:www\.)?(?<!api\.)(?:to)?github\.com\/[-_a-z0-9]+\/[-_a-z0-9]+\/(?:discussions|issues|pull)\/[0-9]+(?:#[-_a-z0-9]+)?/i; // TODO #12070
 
 function massageLink(input: string): string {
-  return input.replace(/(?:to)?github\.com/i, 'togithub.com');
+  return input.replace(regEx(/(?:to)?github\.com/i), 'togithub.com'); // TODO #12071
 }
 
 function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin {
diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts
index 6d6f784419..348372468e 100644
--- a/lib/platform/gitlab/index.ts
+++ b/lib/platform/gitlab/index.ts
@@ -22,6 +22,7 @@ import * as git from '../../util/git';
 import * as hostRules from '../../util/host-rules';
 import { HttpResponse } from '../../util/http';
 import { setBaseUrl } from '../../util/http/gitlab';
+import { regEx } from '../../util/regex';
 import { sanitize } from '../../util/sanitize';
 import { ensureTrailingSlash, getQueryString, parseUrl } from '../../util/url';
 import type {
@@ -150,7 +151,7 @@ export async function getRepos(): Promise<string[]> {
 }
 
 function urlEscape(str: string): string {
-  return str ? str.replace(/\//g, '%2F') : str;
+  return str ? str.replace(regEx(/\//g), '%2F') : str;
 }
 
 export async function getRawFile(
@@ -669,9 +670,9 @@ export async function mergePr({ id }: MergePRConfig): Promise<boolean> {
 
 export function massageMarkdown(input: string): string {
   let desc = input
-    .replace(/Pull Request/g, 'Merge Request')
-    .replace(/PR/g, 'MR')
-    .replace(/\]\(\.\.\/pull\//g, '](!');
+    .replace(regEx(/Pull Request/g), 'Merge Request')
+    .replace(regEx(/PR/g), 'MR')
+    .replace(regEx(/\]\(\.\.\/pull\//g), '](!');
 
   if (lt(defaults.version, '13.4.0')) {
     logger.debug(
@@ -1073,7 +1074,9 @@ export async function ensureComment({
 }: EnsureCommentConfig): Promise<boolean> {
   const sanitizedContent = sanitize(content);
   const massagedTopic = topic
-    ? topic.replace(/Pull Request/g, 'Merge Request').replace(/PR/g, 'MR')
+    ? topic
+        .replace(regEx(/Pull Request/g), 'Merge Request')
+        .replace(regEx(/PR/g), 'MR')
     : topic;
   const comments = await getComments(number);
   let body: string;
@@ -1082,7 +1085,9 @@ export async function ensureComment({
   if (topic) {
     logger.debug(`Ensuring comment "${massagedTopic}" in #${number}`);
     body = `### ${topic}\n\n${sanitizedContent}`;
-    body = body.replace(/Pull Request/g, 'Merge Request').replace(/PR/g, 'MR');
+    body = body
+      .replace(regEx(/Pull Request/g), 'Merge Request')
+      .replace(regEx(/PR/g), 'MR');
     comments.forEach((comment: { body: string; id: number }) => {
       if (comment.body.startsWith(`### ${massagedTopic}\n\n`)) {
         commentId = comment.id;
diff --git a/lib/platform/utils/read-only-issue-body.ts b/lib/platform/utils/read-only-issue-body.ts
index d2ffa1d4de..43bca3bcfd 100644
--- a/lib/platform/utils/read-only-issue-body.ts
+++ b/lib/platform/utils/read-only-issue-body.ts
@@ -1,10 +1,12 @@
+import { regEx } from '../../util/regex';
+
 export function readOnlyIssueBody(body: string): string {
   return body
     .replace(' only once you click their checkbox below', '')
     .replace(' unless you click a checkbox below', '')
     .replace(' To discard all commits and start over, click on a checkbox.', '')
-    .replace(/ Click (?:on |)a checkbox.*\./g, '')
-    .replace(/\[ ] <!-- \w*-branch.*-->/g, '');
+    .replace(regEx(/ Click (?:on |)a checkbox.*\./g), '')
+    .replace(regEx(/\[ ] <!-- \w*-branch.*-->/g), '');
 }
 
 export default readOnlyIssueBody;
-- 
GitLab