diff --git a/lib/config/cli.js b/lib/config/cli.js
index 086d63fa6a2ed11454daa6a68f7cae1016e7d3b9..454c407f869243bcb6aa4ae49ce31faefe99362d 100644
--- a/lib/config/cli.js
+++ b/lib/config/cli.js
@@ -17,7 +17,12 @@ function getCliName(option) {
 
 function getConfig(input) {
   // massage migrated configuration keys
-  const argv = input.map(a => a.replace('--endpoints=', '--host-rules='));
+  const argv = input.map(a =>
+    a
+      .replace('--endpoints=', '--host-rules=')
+      .replace('--expose-env=true', '--trust-level=high')
+      .replace('--expose-env', '--trust-level=high')
+  );
   const options = configDefinitions.getOptions();
 
   const config = {};
diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index 94eeeeb5676cb514dd85b2157860bc570ea5553c..75c6926a3b99b890fc16052185124f81419704b6 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -188,12 +188,12 @@ const options = [
     default: null,
   },
   {
-    name: 'exposeEnv',
+    name: 'trustLevel',
     description:
-      'Enable this to expose bot process.env to repositories for npmrc substitution and package installation',
+      'Set this to "high" if the bot should trust the repository owners/contents',
     stage: 'global',
-    type: 'boolean',
-    default: false,
+    type: 'string',
+    default: 'low',
   },
   {
     name: 'platform',
diff --git a/lib/config/migration.js b/lib/config/migration.js
index e58dcefa1966fb81de3148f87ed139189075497b..b7592e27c9f2c44eda1b562b7bc665b1f50c332f 100644
--- a/lib/config/migration.js
+++ b/lib/config/migration.js
@@ -109,6 +109,14 @@ function migrateConfig(config) {
         } else if (val === false) {
           migratedConfig.rangeStrategy = 'replace';
         }
+      } else if (key === 'exposeEnv') {
+        isMigrated = true;
+        delete migratedConfig.exposeEnv;
+        if (val === true) {
+          migratedConfig.trustLevel = 'high';
+        } else if (val === false) {
+          migratedConfig.trustLevel = 'low';
+        }
       } else if (key === 'upgradeInRange') {
         isMigrated = true;
         delete migratedConfig.upgradeInRange;
diff --git a/lib/datasource/npm.js b/lib/datasource/npm.js
index 4979f7940bd89c7e6dc54b2bfa6898920f22e5aa..0673fcecc046a224381f737f455e6fb7f977bfc2 100644
--- a/lib/datasource/npm.js
+++ b/lib/datasource/npm.js
@@ -56,7 +56,7 @@ function maskToken(token) {
   )}${token.slice(-2)}`;
 }
 
-function setNpmrc(input, exposeEnv = false) {
+function setNpmrc(input, trustLevel = 'low') {
   if (input) {
     if (input === npmrcRaw) {
       return;
@@ -73,7 +73,7 @@ function setNpmrc(input, exposeEnv = false) {
         delete npmrc[key];
       }
     }
-    if (!exposeEnv) {
+    if (trustLevel !== 'high') {
       return;
     }
     for (const key in npmrc) {
@@ -112,8 +112,8 @@ async function getPkgReleases(input, config) {
     return getDependency(depName, retries);
   }
   if (config) {
-    const exposeEnv = config.global ? config.global.exposeEnv : false;
-    setNpmrc(config.npmrc, exposeEnv);
+    const trustLevel = config.global ? config.global.trustLevel : 'low';
+    setNpmrc(config.npmrc, trustLevel);
   }
   const purl = input;
   const res = await getDependency(purl.fullname, retries);
diff --git a/lib/manager/composer/artifacts.js b/lib/manager/composer/artifacts.js
index 2936a58006c82bfbbdf450258d83980e5d68bac4..9426f015d798f8898bdd24b84efe443f7c1e6ef0 100644
--- a/lib/manager/composer/artifacts.js
+++ b/lib/manager/composer/artifacts.js
@@ -99,7 +99,7 @@ async function getArtifacts(
       await fs.outputFile(localAuthFileName, JSON.stringify(authJson));
     }
     const env =
-      config.global && config.global.exposeEnv
+      config.global && config.global.trustLevel === 'high'
         ? process.env
         : {
             HOME: process.env.HOME,
diff --git a/lib/manager/gomod/artifacts.js b/lib/manager/gomod/artifacts.js
index 74c6948e63c7bb0049f32407f86632d6e69356e0..879d5e5de25e2e326fd98f349f58d3f599cea5b1 100644
--- a/lib/manager/gomod/artifacts.js
+++ b/lib/manager/gomod/artifacts.js
@@ -42,7 +42,7 @@ async function getArtifacts(
       await fs.outputFile(localGoSumFileName, existingGoSumContent);
     }
     const env =
-      config.global && config.global.exposeEnv
+      config.global && config.global.trustLevel === 'high'
         ? process.env
         : {
             HOME: process.env.HOME,
diff --git a/lib/manager/npm/extract/index.js b/lib/manager/npm/extract/index.js
index 847d921b492835a45fcc73fe45795963b0410d12..6ce36861f82f4872ffe10ba1ca30f387db0d8dd5 100644
--- a/lib/manager/npm/extract/index.js
+++ b/lib/manager/npm/extract/index.js
@@ -100,7 +100,7 @@ async function extractPackageFile(content, fileName, config) {
     if (npmrc) {
       if (
         npmrc.includes('=${') &&
-        !(config.global && config.global.exposeEnv)
+        !(config.global && config.global.trustLevel === 'high')
       ) {
         logger.info('Discarding .npmrc file with variables');
         npmrc = undefined;
diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js
index 0afee7daf16d8a31282931d7ad29ca8ddc06e4f3..6d877f018f8c84b102b4f9ecba63d5f5013ab195 100644
--- a/lib/manager/npm/post-update/index.js
+++ b/lib/manager/npm/post-update/index.js
@@ -345,7 +345,7 @@ async function getAdditionalFiles(config, packageFiles) {
   await fs.ensureDir(process.env.YARN_CACHE_FOLDER);
 
   const env =
-    config.global && config.global.exposeEnv
+    config.global && config.global.trustLevel === 'high'
       ? process.env
       : {
           HOME: process.env.HOME,
diff --git a/lib/workers/global/index.js b/lib/workers/global/index.js
index 17d814ba5f4a2e0e53f673b91213629711e4c826..82821326ad9f0bb9542188e91f86d08b8618bde3 100644
--- a/lib/workers/global/index.js
+++ b/lib/workers/global/index.js
@@ -39,7 +39,7 @@ async function start() {
         'Available now for GitLab: [Renovate Pro](https://renovatebot.com/pro) with real-time webhook handling and priority job queue.';
     }
     // Move global variables that we need to use later
-    const importGlobals = ['exposeEnv', 'prBanner', 'prFooter'];
+    const importGlobals = ['trustLevel', 'prBanner', 'prFooter'];
     config.global = {};
     importGlobals.forEach(key => {
       config.global[key] = config[key];
diff --git a/lib/workers/repository/init/apis.js b/lib/workers/repository/init/apis.js
index d40f1c2bd44b86c4fc229779bd325ec34d0b03ab..ebef7106c5b37644f434d2774a650f8e6dbb591c 100644
--- a/lib/workers/repository/init/apis.js
+++ b/lib/workers/repository/init/apis.js
@@ -22,7 +22,7 @@ async function initApis(input) {
   npmApi.resetMemCache();
   npmApi.setNpmrc(
     config.npmrc,
-    config.global ? config.global.exposeEnv : false
+    config.global ? config.global.trustLevel : 'low'
   );
   delete config.gitPrivateKey;
   return config;
diff --git a/lib/workers/repository/init/config.js b/lib/workers/repository/init/config.js
index 7e1bfec15e15f8d969cfffcfa7bcd52046cd3886..8bc2b5d2383b7041722907210011c2a295e6ce62 100644
--- a/lib/workers/repository/init/config.js
+++ b/lib/workers/repository/init/config.js
@@ -129,7 +129,7 @@ async function mergeRenovateConfig(config) {
     logger.debug('Found npmrc in decrypted config - setting');
     npmApi.setNpmrc(
       decryptedConfig.npmrc,
-      config.global ? config.global.exposeEnv : false
+      config.global ? config.global.trustLevel : 'low'
     );
   }
   // Decrypt after resolving in case the preset contains npm authentication instead
@@ -146,7 +146,7 @@ async function mergeRenovateConfig(config) {
     );
     npmApi.setNpmrc(
       resolvedConfig.npmrc,
-      config.global ? config.global.exposeEnv : false
+      config.global ? config.global.trustLevel : 'low'
     );
     resolvedConfig.ignoreNpmrcFile = true;
   }
diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap
index d71effdf6914340033d195e5b3603a7a07aceefb..85445846bb9fa200416ee93094ec4bf979fab9c3 100644
--- a/test/config/__snapshots__/migration.spec.js.snap
+++ b/test/config/__snapshots__/migration.spec.js.snap
@@ -32,6 +32,7 @@ Object {
     "automerge": true,
     "gitFs": "https",
     "schedule": "before 5am",
+    "trustLevel": "low",
   },
   "major": Object {
     "automerge": false,
@@ -130,6 +131,7 @@ Object {
   "travis": Object {
     "enabled": true,
   },
+  "trustLevel": "high",
 }
 `;
 
diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js
index d3e695e18da7f7d0c2f0702fb1cd22395fa05b75..0f9b16cb849ada2b0dbbebc34fcee4eae26e3ba0 100644
--- a/test/config/migration.spec.js
+++ b/test/config/migration.spec.js
@@ -57,7 +57,9 @@ describe('config/migration', () => {
             enabled: false,
           },
         ],
+        exposeEnv: true,
         lockFileMaintenance: {
+          exposeEnv: false,
           gitFs: true,
           automerge: 'any',
           schedule: 'before 5am every day',
diff --git a/test/datasource/npm.spec.js b/test/datasource/npm.spec.js
index 8bf3afdcd8b5eae267dcc59d81e7835f0ef4b154..715c4702e694addb9a593f16dbfbb5ba0ea08ffa 100644
--- a/test/datasource/npm.spec.js
+++ b/test/datasource/npm.spec.js
@@ -383,7 +383,7 @@ describe('api/npm', () => {
       .reply(200, npmResponse);
     process.env.REGISTRY = 'https://registry.from-env.com';
     // eslint-disable-next-line no-template-curly-in-string
-    npm.setNpmrc('registry=${REGISTRY}', true);
+    npm.setNpmrc('registry=${REGISTRY}', 'high');
     const res = await npm.getPkgReleases('foobar');
     expect(res).toMatchSnapshot();
   });
@@ -391,7 +391,7 @@ describe('api/npm', () => {
     let e;
     try {
       // eslint-disable-next-line no-template-curly-in-string
-      npm.setNpmrc('registry=${REGISTRY_MISSING}', true);
+      npm.setNpmrc('registry=${REGISTRY_MISSING}', 'high');
     } catch (err) {
       e = err;
     }
diff --git a/website/docs/self-hosted-configuration.md b/website/docs/self-hosted-configuration.md
index ef536422bc6386cc903ff33393d12d514a8949e2..54ff2f2fd4edf4d4e4510297892a6fe3d6596c09 100644
--- a/website/docs/self-hosted-configuration.md
+++ b/website/docs/self-hosted-configuration.md
@@ -19,8 +19,6 @@ Set this to 'global' if you wish Renovate to use globally-installed binaries (`n
 
 ## endpoint
 
-## exposeEnv
-
 ## force
 
 This object is used as a "force override" when you need to make sure certain configuration overrides whatever is configured in the repository. For example, forcing a null (no) schedule to make sure Renovate raises PRs on a run even if the repository itself or its preset defines a schedule that's currently in active.
@@ -80,4 +78,13 @@ By default, Renovate will use the most efficient approach to updating package fi
 
 ## token
 
+## trustLevel
+
+Setting trustLevel to "high" can make sense in may self-hosted cases where the bot operator trusts the content in each repository.
+
+Setting trustLevel=high means:
+
+- Child processes are run with full access to `env`
+- `.npmrc` files can have environment variable substitution performed
+
 ## username