diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts
index 94a7bc142ca291232c29d289a9e451b955c901ce..0d7485f93ecd32681650eb24c9b40aed0a108185 100644
--- a/lib/platform/azure/index.ts
+++ b/lib/platform/azure/index.ts
@@ -5,6 +5,7 @@ import { appSlug } from '../../config/app-strings';
 import GitStorage from '../git/storage';
 import { logger } from '../../logger';
 import { PlatformConfig, RepoParams, RepoConfig } from '../common';
+import { sanitize } from '../../util/sanitize';
 
 interface Config {
   storage: GitStorage;
@@ -353,7 +354,7 @@ export async function createPr(
   const targetRefName = azureHelper.getNewBranchName(
     useDefaultBranch ? config.defaultBranch : config.baseBranch
   );
-  const description = azureHelper.max4000Chars(hostRules.sanitize(body));
+  const description = azureHelper.max4000Chars(sanitize(body));
   const azureApiGit = await azureApi.gitApi();
   const workItemRefs = [
     {
@@ -405,9 +406,7 @@ export async function updatePr(prNo: number, title: string, body?: string) {
     title,
   };
   if (body) {
-    objToUpdate.description = azureHelper.max4000Chars(
-      hostRules.sanitize(body)
-    );
+    objToUpdate.description = azureHelper.max4000Chars(sanitize(body));
   }
   await azureApiGit.updatePullRequest(objToUpdate, config.repoId, prNo);
 }
@@ -418,7 +417,7 @@ export async function ensureComment(
   content: string
 ) {
   logger.debug(`ensureComment(${issueNo}, ${topic}, content)`);
-  const body = `### ${topic}\n\n${hostRules.sanitize(content)}`;
+  const body = `### ${topic}\n\n${sanitize(content)}`;
   const azureApiGit = await azureApi.gitApi();
   await azureApiGit.createThread(
     {
diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts
index b0b5aa73cc3e9c6015e4af18f24bcc91511e3bbc..02db3b56f71c699099d23122ff068b77f8189753 100644
--- a/lib/platform/bitbucket-server/index.ts
+++ b/lib/platform/bitbucket-server/index.ts
@@ -7,6 +7,7 @@ import * as hostRules from '../../util/host-rules';
 import GitStorage from '../git/storage';
 import { logger } from '../../logger';
 import { PlatformConfig, RepoParams, RepoConfig } from '../common';
+import { sanitize } from '../../util/sanitize';
 
 /*
  * Version: 5.3 (EOL Date: 15 Aug 2019)
@@ -592,7 +593,7 @@ export async function ensureComment(
   topic: string | null,
   rawContent: string
 ) {
-  const content = hostRules.sanitize(rawContent);
+  const content = sanitize(rawContent);
   try {
     const comments = await getComments(prNo);
     let body: string;
@@ -728,7 +729,7 @@ export async function createPr(
   _labels?: string[] | null,
   useDefaultBranch?: boolean
 ) {
-  const description = hostRules.sanitize(rawDescription);
+  const description = sanitize(rawDescription);
   logger.debug(`createPr(${branchName}, title=${title})`);
   const base = useDefaultBranch ? config.defaultBranch : config.baseBranch;
   let reviewers = [];
@@ -883,7 +884,7 @@ export async function updatePr(
   title: string,
   rawDescription: string
 ) {
-  const description = hostRules.sanitize(rawDescription);
+  const description = sanitize(rawDescription);
   logger.debug(`updatePr(${prNo}, title=${title})`);
 
   try {
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index 7835ad4ed374d6c0016d3f5d2bfa3952073c511e..063d80bc70ac6ab73531e6f03fdcd7441e3b0c91 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -9,6 +9,7 @@ import { readOnlyIssueBody } from '../utils/read-only-issue-body';
 import { appSlug } from '../../config/app-strings';
 import * as comments from './comments';
 import { PlatformConfig, RepoParams, RepoConfig } from '../common';
+import { sanitize } from '../../util/sanitize';
 
 let config: utils.Config = {} as any;
 
@@ -353,7 +354,7 @@ async function closeIssue(issueNumber: number) {
 
 export async function ensureIssue(title: string, body: string) {
   logger.debug(`ensureIssue()`);
-  const description = getPrBody(hostRules.sanitize(body));
+  const description = getPrBody(sanitize(body));
 
   /* istanbul ignore if */
   if (!config.has_issues) {
@@ -476,12 +477,7 @@ export function ensureComment(
   content: string
 ) {
   // https://developer.atlassian.com/bitbucket/api/2/reference/search?q=pullrequest+comment
-  return comments.ensureComment(
-    config,
-    prNo,
-    topic,
-    hostRules.sanitize(content)
-  );
+  return comments.ensureComment(config, prNo, topic, sanitize(content));
 }
 
 export function ensureCommentRemoval(prNo: number, topic: string) {
@@ -536,7 +532,7 @@ export async function createPr(
 
   const body = {
     title,
-    description: hostRules.sanitize(description),
+    description: sanitize(description),
     source: {
       branch: {
         name: branchName,
@@ -652,7 +648,7 @@ export async function updatePr(
 ) {
   logger.debug(`updatePr(${prNo}, ${title}, body)`);
   await api.put(`/2.0/repositories/${config.repository}/pullrequests/${prNo}`, {
-    body: { title, description: hostRules.sanitize(description) },
+    body: { title, description: sanitize(description) },
   });
 }
 
diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts
index db2df6a0cf9ebd529b5d9dd86255b7b2c062bacc..3b9a7580f3d5b89694a1914a83bc612d0c25c45e 100644
--- a/lib/platform/github/index.ts
+++ b/lib/platform/github/index.ts
@@ -15,6 +15,7 @@ import {
   configFileNames,
   urls,
 } from '../../config/app-strings';
+import { sanitize } from '../../util/sanitize';
 
 const defaultConfigFile = configFileNames[0];
 
@@ -835,7 +836,7 @@ export async function ensureIssue(
   reopen = true
 ) {
   logger.debug(`ensureIssue(${title})`);
-  const body = hostRules.sanitize(rawbody);
+  const body = sanitize(rawbody);
   try {
     const issueList = await getIssueList();
     const issues = issueList.filter(i => i.title === title);
@@ -1035,7 +1036,7 @@ export async function ensureComment(
   topic: string | null,
   rawContent: string
 ) {
-  const content = hostRules.sanitize(rawContent);
+  const content = sanitize(rawContent);
   try {
     const comments = await getComments(issueNo);
     let body: string;
@@ -1187,7 +1188,7 @@ export async function createPr(
   useDefaultBranch: boolean,
   platformOptions: { statusCheckVerify?: boolean } = {}
 ) {
-  const body = hostRules.sanitize(rawBody);
+  const body = sanitize(rawBody);
   const base = useDefaultBranch ? config.defaultBranch : config.baseBranch;
   // Include the repository owner to handle forkMode and regular mode
   const head = `${config.repository!.split('/')[0]}:${branchName}`;
@@ -1588,7 +1589,7 @@ export async function getPrFiles(prNo: number) {
 
 export async function updatePr(prNo: number, title: string, rawBody?: string) {
   logger.debug(`updatePr(${prNo}, ${title}, body)`);
-  const body = hostRules.sanitize(rawBody);
+  const body = sanitize(rawBody);
   const patchBody: any = { title };
   if (body) {
     patchBody.body = body;
diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts
index e34ea3b7c02d14a23dfba382a13a9cd7e9460818..3e47de1557934467b94efc357e60bd4f047d3b91 100644
--- a/lib/platform/gitlab/index.ts
+++ b/lib/platform/gitlab/index.ts
@@ -7,6 +7,7 @@ import GitStorage from '../git/storage';
 import { PlatformConfig, RepoParams, RepoConfig } from '../common';
 import { configFileNames } from '../../config/app-strings';
 import { logger } from '../../logger';
+import { sanitize } from '../../util/sanitize';
 
 const defaultConfigFile = configFileNames[0];
 let config: {
@@ -453,7 +454,7 @@ export async function findIssue(title: string) {
 
 export async function ensureIssue(title: string, body: string) {
   logger.debug(`ensureIssue()`);
-  const description = getPrBody(hostRules.sanitize(body));
+  const description = getPrBody(sanitize(body));
   try {
     const issueList = await getIssueList();
     const issue = issueList.find((i: { title: string }) => i.title === title);
@@ -574,7 +575,7 @@ export async function ensureComment(
   topic: string | null | undefined,
   rawContent: string
 ) {
-  const content = hostRules.sanitize(rawContent);
+  const content = sanitize(rawContent);
   const massagedTopic = topic
     ? topic.replace(/Pull Request/g, 'Merge Request').replace(/PR/g, 'MR')
     : topic;
@@ -692,7 +693,7 @@ export async function createPr(
   labels?: string[] | null,
   useDefaultBranch?: boolean
 ) {
-  const description = hostRules.sanitize(rawDescription);
+  const description = sanitize(rawDescription);
   const targetBranch = useDefaultBranch
     ? config.defaultBranch
     : config.baseBranch;
@@ -800,7 +801,7 @@ export async function updatePr(
   await api.put(`projects/${config.repository}/merge_requests/${iid}`, {
     body: {
       title,
-      description: hostRules.sanitize(description),
+      description: sanitize(description),
     },
   });
 }
diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts
index 1f045a24e1efacf5a438b4f99db6023c8572cf6e..0e4704a448ae369f5e47a595d14454b2ec679df9 100644
--- a/lib/util/host-rules.ts
+++ b/lib/util/host-rules.ts
@@ -1,6 +1,7 @@
 import URL from 'url';
 import merge from 'deepmerge';
 import { logger } from '../logger';
+import * as sanitize from './sanitize';
 
 export interface HostRule {
   hostType?: string;
@@ -15,8 +16,6 @@ export interface HostRule {
   timeout?: number;
 }
 
-let secrets: string[] = [];
-
 let hostRules: HostRule[] = [];
 
 export function add(params: HostRule) {
@@ -33,14 +32,13 @@ export function add(params: HostRule) {
   const confidentialFields = ['password', 'token'];
   confidentialFields.forEach(field => {
     const secret = params[field];
-    if (secret && secret.length > 3 && !secrets.includes(secret))
-      secrets.push(secret);
+    if (secret && secret.length > 3) sanitize.add(secret);
   });
   if (params.username && params.password) {
     const secret = Buffer.from(
       `${params.username}:${params.password}`
     ).toString('base64');
-    if (!secrets.includes(secret)) secrets.push(secret);
+    sanitize.add(secret);
   }
 }
 
@@ -166,18 +164,7 @@ export function hosts({ hostType }: { hostType: string }) {
     .filter(Boolean);
 }
 
-export function sanitize(input: string) {
-  if (!input) return input;
-  let output: string = input;
-  secrets.forEach(secret => {
-    while (output.includes(secret)) {
-      output = output.replace(secret, '**redacted**');
-    }
-  });
-  return output;
-}
-
 export function clear() {
   hostRules = [];
-  secrets = [];
+  sanitize.clear();
 }
diff --git a/lib/util/sanitize.ts b/lib/util/sanitize.ts
new file mode 100644
index 0000000000000000000000000000000000000000..98d6b737c1ea9185e1e986414d055f4a36c0aec9
--- /dev/null
+++ b/lib/util/sanitize.ts
@@ -0,0 +1,20 @@
+const secrets = new Set<string>();
+
+export function sanitize(input: string) {
+  if (!input) return input;
+  let output: string = input;
+  secrets.forEach(secret => {
+    while (output.includes(secret)) {
+      output = output.replace(secret, '**redacted**');
+    }
+  });
+  return output;
+}
+
+export function add(secret: string) {
+  secrets.add(secret);
+}
+
+export function clear() {
+  secrets.clear();
+}
diff --git a/test/platform/azure/index.spec.ts b/test/platform/azure/index.spec.ts
index ce772c70ac66307237fede17d08f4ee7992ce75f..e93d28124d0a7fcfd519355a186925459d47a51f 100644
--- a/test/platform/azure/index.spec.ts
+++ b/test/platform/azure/index.spec.ts
@@ -20,7 +20,7 @@ describe('platform/azure', () => {
     jest.mock('../../../lib/platform/git/storage');
     jest.mock('../../../lib/util/host-rules');
     hostRules = require('../../../lib/util/host-rules');
-    hostRules.sanitize = jest.fn(input => input);
+    require('../../../lib/util/sanitize').sanitize = jest.fn(input => input);
     azure = require('../../../lib/platform/azure');
     azureApi = require('../../../lib/platform/azure/azure-got-wrapper');
     azureHelper = require('../../../lib/platform/azure/azure-helper');
diff --git a/test/platform/bitbucket-server/index.spec.ts b/test/platform/bitbucket-server/index.spec.ts
index abdeb193421d3cfe5b8f027347fc1dc455f9ce41..063944356a0707eab4516514cdc1e1a144fe955a 100644
--- a/test/platform/bitbucket-server/index.spec.ts
+++ b/test/platform/bitbucket-server/index.spec.ts
@@ -34,7 +34,6 @@ describe('platform/bitbucket-server', () => {
         jest.mock('../../../lib/platform/git/storage');
         jest.mock('../../../lib/util/host-rules');
         hostRules = require('../../../lib/util/host-rules');
-        hostRules.sanitize = jest.fn(input => input);
         api = require('../../../lib/platform/bitbucket-server/bb-got-wrapper')
           .api;
         jest.spyOn(api, 'get');
diff --git a/test/platform/bitbucket/index.spec.ts b/test/platform/bitbucket/index.spec.ts
index ce2bfbe8cb392f415508776db3b67c5ee96dbd48..a097eeaf568174c02be7563e9ecc61894d481282 100644
--- a/test/platform/bitbucket/index.spec.ts
+++ b/test/platform/bitbucket/index.spec.ts
@@ -17,7 +17,6 @@ describe('platform/bitbucket', () => {
     jest.mock('../../../lib/platform/git/storage');
     jest.mock('../../../lib/util/host-rules');
     hostRules = require('../../../lib/util/host-rules');
-    hostRules.sanitize = jest.fn(input => input);
     api = require('../../../lib/platform/bitbucket/bb-got-wrapper').api;
     bitbucket = require('../../../lib/platform/bitbucket');
     GitStorage = require('../../../lib/platform/git/storage').Storage;
diff --git a/test/platform/github/index.spec.ts b/test/platform/github/index.spec.ts
index e19d8149427cbef7f35581f13e4a37483a56b5a2..60bab0e5fbfc64394475a9787c897a4414707aef 100644
--- a/test/platform/github/index.spec.ts
+++ b/test/platform/github/index.spec.ts
@@ -18,7 +18,6 @@ describe('platform/github', () => {
       .api as any;
     github = await import('../../../lib/platform/github');
     hostRules = (await import('../../../lib/util/host-rules')) as any;
-    hostRules.sanitize = jest.fn(input => input);
     jest.mock('../../../lib/platform/git/storage');
     GitStorage = (await import('../../../lib/platform/git/storage'))
       .Storage as any;
diff --git a/test/platform/gitlab/index.spec.ts b/test/platform/gitlab/index.spec.ts
index 252daf41b2b7c7332ee3d90343684b249484b310..106d2f0bb4d39afc8acd2accc2128fc65cf84283 100644
--- a/test/platform/gitlab/index.spec.ts
+++ b/test/platform/gitlab/index.spec.ts
@@ -19,7 +19,6 @@ describe('platform/gitlab', () => {
     api = require('../../../lib/platform/gitlab/gl-got-wrapper').api;
     jest.mock('../../../lib/util/host-rules');
     hostRules = require('../../../lib/util/host-rules');
-    hostRules.sanitize = jest.fn(input => input);
     jest.mock('../../../lib/platform/git/storage');
     GitStorage = require('../../../lib/platform/git/storage').Storage;
     GitStorage.mockImplementation(() => ({
diff --git a/test/util/__snapshots__/host-rules.spec.ts.snap b/test/util/__snapshots__/host-rules.spec.ts.snap
index 4ed77aa00ea991f3e78c07c7c388e69ca0a51c80..2eb17cea817e76bdc7dd6a2dfc8f2aa12c9726ff 100644
--- a/test/util/__snapshots__/host-rules.spec.ts.snap
+++ b/test/util/__snapshots__/host-rules.spec.ts.snap
@@ -33,5 +33,3 @@ Array [
   "my.local.registry",
 ]
 `;
-
-exports[`util/host-rules find() sanitizes secrets from strings 1`] = `"My token is **redacted**, username is \\"userabc\\" and password is \\"**redacted**\\" (hashed: **redacted**)"`;
diff --git a/test/util/__snapshots__/sanitize.spec.ts.snap b/test/util/__snapshots__/sanitize.spec.ts.snap
new file mode 100644
index 0000000000000000000000000000000000000000..a2b1fff385f13cbf21e99bc945295a4d95359470
--- /dev/null
+++ b/test/util/__snapshots__/sanitize.spec.ts.snap
@@ -0,0 +1,3 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`util/sanitize sanitizes secrets from strings 1`] = `"My token is **redacted**, username is \\"userabc\\" and password is \\"**redacted**\\" (hashed: **redacted**)"`;
diff --git a/test/util/host-rules.spec.ts b/test/util/host-rules.spec.ts
index 3304b600263004f8bbbebde4bbbbb3f673d06f38..c3c47ffbe1bec54f3768439b76aeaad3259fd91b 100644
--- a/test/util/host-rules.spec.ts
+++ b/test/util/host-rules.spec.ts
@@ -1,4 +1,4 @@
-import { add, find, clear, hosts, sanitize } from '../../lib/util/host-rules';
+import { add, find, clear, hosts } from '../../lib/util/host-rules';
 
 describe('util/host-rules', () => {
   beforeEach(() => {
@@ -143,26 +143,5 @@ describe('util/host-rules', () => {
       expect(res).toMatchSnapshot();
       expect(res).toHaveLength(2);
     });
-    it('sanitizes empty string', () => {
-      expect(sanitize(null)).toEqual(null);
-    });
-    it('sanitizes secrets from strings', () => {
-      const token = 'abc123token';
-      const username = 'userabc';
-      const password = 'password123';
-      add({
-        token,
-      });
-      add({
-        username,
-        password,
-      });
-      const hashed = Buffer.from(`${username}:${password}`).toString('base64');
-      expect(
-        sanitize(
-          `My token is ${token}, username is "${username}" and password is "${password}" (hashed: ${hashed})`
-        )
-      ).toMatchSnapshot();
-    });
   });
 });
diff --git a/test/util/sanitize.spec.ts b/test/util/sanitize.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6cd222c2c611cde83a306d46ade5efe9ce9ba58
--- /dev/null
+++ b/test/util/sanitize.spec.ts
@@ -0,0 +1,25 @@
+import { add, clear, sanitize } from '../../lib/util/sanitize';
+
+describe('util/sanitize', () => {
+  beforeEach(() => {
+    clear();
+  });
+
+  it('sanitizes empty string', () => {
+    expect(sanitize(null)).toEqual(null);
+  });
+  it('sanitizes secrets from strings', () => {
+    const token = 'abc123token';
+    const username = 'userabc';
+    const password = 'password123';
+    add(token);
+    const hashed = Buffer.from(`${username}:${password}`).toString('base64');
+    add(hashed);
+    add(password);
+    expect(
+      sanitize(
+        `My token is ${token}, username is "${username}" and password is "${password}" (hashed: ${hashed})`
+      )
+    ).toMatchSnapshot();
+  });
+});