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