diff --git a/docs/configuration.md b/docs/configuration.md
index a678802f7eb3bc3b6e644fd9feb179615493ddf1..df100fcaa69a84b7a0b80ad72bf3f50aa71ac229 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -83,6 +83,7 @@ $ node renovate --help
     --github-app-id <integer>            GitHub App ID (enables GitHub App functionality if set)
     --github-app-key <string>            GitHub App Private Key (.pem file contents)
     --package-files <list>               Package file paths
+    --ignore-node-modules [boolean]      Skip any package.json files found within node_modules folders
     --dep-types <list>                   Dependency types
     --ignore-deps <list>                 Dependencies to ignore
     --pin-versions [boolean]             Convert ranged versions in package.json to pinned versions
@@ -278,12 +279,20 @@ Obviously, you can't set repository or package file location with this method.
   <td>`RENOVATE_PACKAGE_FILES`</td>
   <td>`--package-files`<td>
 </tr>
+<tr>
+  <td>`ignoreNodeModules`</td>
+  <td>Skip any package.json files found within node_modules folders</td>
+  <td>boolean</td>
+  <td><pre>true</pre></td>
+  <td>`RENOVATE_IGNORE_NODE_MODULES`</td>
+  <td>`--ignore-node-modules`<td>
+</tr>
 <tr>
   <td>`depTypes`</td>
   <td>Dependency types</td>
   <td>list</td>
   <td><pre>[
-  {"depType": "dependencies", "semanticPrefix": "fix: "},
+  {"depType": "dependencies", "semanticPrefix": "fix(deps): "},
   "devDependencies",
   "optionalDependencies"
 ]</pre></td>
@@ -358,7 +367,7 @@ Obviously, you can't set repository or package file location with this method.
   <td>`semanticPrefix`</td>
   <td>Prefix to use if semantic commits are enabled</td>
   <td>string</td>
-  <td><pre>"chore: "</pre></td>
+  <td><pre>"chore(deps): "</pre></td>
   <td>`RENOVATE_SEMANTIC_PREFIX`</td>
   <td>`--semantic-prefix`<td>
 </tr>
@@ -460,7 +469,7 @@ Obviously, you can't set repository or package file location with this method.
   "branchName": "renovate/lock-files",
   "commitMessage": "{{semanticPrefix}}Update lock file",
   "prTitle": "{{semanticPrefix}}Lock file maintenance",
-  "prBody": "This PR regenerates lock files to keep them up-to-date.",
+  "prBody": "This {{#if isGitHub}}Pull{{else}}Merge{{/if}} Request updates `package.json` lock files to use the latest dependency versions.\n\n{{#if schedule}}\n**Note**: This PR was created on a configured schedule (\"{{schedule}}\"{{#if timezone}} in timezone `{{timezone}}`{{/if}}) and will not receive updates outside those times.\n{{/if}}\n\n{{#if hasErrors}}\n\n---\n\n### Errors\n\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\n\n{{#each errors as |error|}}\n-   `{{error.depName}}`: {{error.message}}\n{{/each}}\n{{/if}}\n\n{{#if hasWarnings}}\n\n---\n\n### Warnings\n\nPlease make sure the following warnings are safe to ignore:\n\n{{#each warnings as |warning|}}\n-   `{{warning.depName}}`: {{warning.message}}\n{{/each}}\n{{/if}}\n\n---\n\nThis {{#if isGitHub}}PR{{else}}MR{{/if}} has been generated by [Renovate Bot](https://keylocation.sg/our-tech/renovate).",
   "schedule": "before 5am on monday"
 }</pre></td>
   <td></td>
diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index 79267bd22ddd2c3d8ab2c4a543e49f2a371d4f2c..3197d852f4b7b10b3775bc1933ef49558dfd8780 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -141,6 +141,14 @@ const options = [
     type: 'list',
     stage: 'repository',
   },
+  {
+    name: 'ignoreNodeModules',
+    description:
+      'Skip any package.json files found within node_modules folders',
+    type: 'boolean',
+    stage: 'repository',
+    onboarding: false,
+  },
   {
     name: 'depTypes',
     description: 'Dependency types',
diff --git a/lib/workers/repository/apis.js b/lib/workers/repository/apis.js
index 391060afc1a9c73393579ebd5311b752c0e06f2c..ea643bc6f680a39a99afbd09a245b10b6a9cd32c 100644
--- a/lib/workers/repository/apis.js
+++ b/lib/workers/repository/apis.js
@@ -110,10 +110,32 @@ async function mergeRenovateJson(config, branchName) {
   return returnConfig;
 }
 
-async function detectPackageFiles(config) {
+async function detectPackageFiles(input) {
+  const config = Object.assign({}, input);
   config.logger.trace({ config }, 'detectPackageFiles');
-  const packageFiles = await config.api.findFilePaths('package.json');
-  config.logger.debug(`Found ${packageFiles.length} package file(s)`);
-  const detectedPackageFiles = true;
-  return Object.assign({}, config, { packageFiles, detectedPackageFiles });
+  config.packageFiles = await config.api.findFilePaths('package.json');
+  config.logger.debug(`Found ${config.packageFiles.length} package file(s)`);
+  config.logger.trace(JSON.stringify(config.packageFiles));
+  if (config.ignoreNodeModules) {
+    const skippedPackageFiles = [];
+    config.packageFiles = config.packageFiles.filter(packageFile => {
+      if (packageFile.indexOf('node_modules/') === -1) {
+        return true;
+      }
+      skippedPackageFiles.push(packageFile);
+      return false;
+    });
+    if (skippedPackageFiles.length) {
+      config.foundNodeModules = true;
+      config.warnings.push({
+        depName: 'packageFiles',
+        message: `Skipped package.json files found within node_modules subfolders: \`${skippedPackageFiles}\``,
+      });
+      config.logger.debug(
+        `Now have ${config.packageFiles.length} package file(s) after filtering`
+      );
+    }
+  }
+  config.detectedPackageFiles = true;
+  return config;
 }
diff --git a/lib/workers/repository/onboarding.js b/lib/workers/repository/onboarding.js
index 169a4d5e4e22619262c8530b7dacf740e1d8c5f1..b168b19cc31bba7caa86eb2da6f40e27a1ef0b64 100644
--- a/lib/workers/repository/onboarding.js
+++ b/lib/workers/repository/onboarding.js
@@ -51,6 +51,9 @@ async function createBranch(config) {
     config.logger.debug('Repo is not private - unpinning versions');
     onboardingConfig.depTypes[0].pinVersions = false;
   }
+  if (config.foundNodeModules) {
+    onboardingConfig.ignoreNodeModules = true;
+  }
   const onboardingConfigString = `${stringify(onboardingConfig)}\n`;
   await config.api.commitFilesToBranch(
     onboardBranchName,
diff --git a/test/workers/repository/__snapshots__/apis.spec.js.snap b/test/workers/repository/__snapshots__/apis.spec.js.snap
index b04b5d0311ec55760ba28f78bed6b1e2a5e6ada6..9cfb0ef22e78290f26267da85034e9ce6eac7acf 100644
--- a/test/workers/repository/__snapshots__/apis.spec.js.snap
+++ b/test/workers/repository/__snapshots__/apis.spec.js.snap
@@ -7,6 +7,23 @@ Array [
 ]
 `;
 
+exports[`workers/repository/apis detectPackageFiles(config) ignores node modules 1`] = `
+Array [
+  "package.json",
+]
+`;
+
+exports[`workers/repository/apis detectPackageFiles(config) ignores node modules 2`] = `true`;
+
+exports[`workers/repository/apis detectPackageFiles(config) ignores node modules 3`] = `
+Array [
+  Object {
+    "depName": "packageFiles",
+    "message": "Skipped package.json files found within node_modules subfolders: \`node_modules/backend/package.json\`",
+  },
+]
+`;
+
 exports[`workers/repository/apis initApis(config) throws if unknown platform 1`] = `"Unknown platform: foo"`;
 
 exports[`workers/repository/apis mergeRenovateJson(config) returns error in JSON.parse 1`] = `
diff --git a/test/workers/repository/__snapshots__/onboarding.spec.js.snap b/test/workers/repository/__snapshots__/onboarding.spec.js.snap
index b46c692780824086c1befe5e42a3e10f054a51eb..7eb6b081e8476174bc8788113a127093667da834 100644
--- a/test/workers/repository/__snapshots__/onboarding.spec.js.snap
+++ b/test/workers/repository/__snapshots__/onboarding.spec.js.snap
@@ -232,7 +232,8 @@ Array [
   \\"commitMessage\\": \\"{{semanticPrefix}}Update dependency {{depName}} to version {{newVersion}}\\",
   \\"labels\\": [],
   \\"assignees\\": [],
-  \\"reviewers\\": []
+  \\"reviewers\\": [],
+  \\"ignoreNodeModules\\": true
 }
 ",
       "name": "renovate.json",
@@ -273,7 +274,8 @@ Array [
   \\"commitMessage\\": \\"{{semanticPrefix}}Update dependency {{depName}} to version {{newVersion}}\\",
   \\"labels\\": [],
   \\"assignees\\": [],
-  \\"reviewers\\": []
+  \\"reviewers\\": [],
+  \\"ignoreNodeModules\\": true
 }
 ",
       "name": "renovate.json",
@@ -314,7 +316,8 @@ Array [
   \\"commitMessage\\": \\"{{semanticPrefix}}Update dependency {{depName}} to version {{newVersion}}\\",
   \\"labels\\": [],
   \\"assignees\\": [],
-  \\"reviewers\\": []
+  \\"reviewers\\": [],
+  \\"ignoreNodeModules\\": true
 }
 ",
       "name": "renovate.json",
diff --git a/test/workers/repository/apis.spec.js b/test/workers/repository/apis.spec.js
index 3331e32a92fe30e77066f6bf81b3304b32b901eb..c86a30be32251cda4772c31721c2cc80d8945437 100644
--- a/test/workers/repository/apis.spec.js
+++ b/test/workers/repository/apis.spec.js
@@ -134,10 +134,28 @@ describe('workers/repository/apis', () => {
           ]),
         },
         logger,
+        warnings: [],
       };
       const res = await apis.detectPackageFiles(config);
       expect(res).toMatchObject(config);
       expect(res.packageFiles).toMatchSnapshot();
     });
+    it('ignores node modules', async () => {
+      const config = {
+        ignoreNodeModules: true,
+        api: {
+          findFilePaths: jest.fn(() => [
+            'package.json',
+            'node_modules/backend/package.json',
+          ]),
+        },
+        logger,
+        warnings: [],
+      };
+      const res = await apis.detectPackageFiles(config);
+      expect(res.packageFiles).toMatchSnapshot();
+      expect(res.foundNodeModules).toMatchSnapshot();
+      expect(res.warnings).toMatchSnapshot();
+    });
   });
 });
diff --git a/test/workers/repository/onboarding.spec.js b/test/workers/repository/onboarding.spec.js
index fec0365ed4b4651cb28127fe64c8a1b0f04c11fc..52ebd5f33e67380f344116f0a9f1c927a058d831 100644
--- a/test/workers/repository/onboarding.spec.js
+++ b/test/workers/repository/onboarding.spec.js
@@ -206,6 +206,7 @@ describe('lib/workers/repository/onboarding', () => {
         getPr: jest.fn(() => {}),
         getCommitMessages: jest.fn(),
       };
+      config.foundNodeModules = true;
       config.logger = logger;
       config.detectedPackageFiles = true;
       onboarding.isRepoPrivate = jest.fn();