diff --git a/lib/modules/manager/npm/extract/index.spec.ts b/lib/modules/manager/npm/extract/index.spec.ts
index 0b966aab70a2cb9b6e4317a58e3bacb8652c280f..6ed0df8fb39ed07fac130f6691f8dbf1705b51bf 100644
--- a/lib/modules/manager/npm/extract/index.spec.ts
+++ b/lib/modules/manager/npm/extract/index.spec.ts
@@ -1,9 +1,12 @@
 import { Fixtures } from '../../../../../test/fixtures';
+import { fs } from '../../../../../test/util';
 import { getConfig } from '../../../../config/defaults';
-import * as _fs from '../../../../util/fs';
 import * as npmExtract from '.';
 
-const fs: any = _fs;
+jest.mock('../../../../util/fs');
+const realFs = jest.requireActual<typeof import('../../../../util/fs')>(
+  '../../../../util/fs'
+);
 
 // TODO: fix types
 const defaultConfig = getConfig();
@@ -22,8 +25,10 @@ const invalidNameContent = Fixtures.get('invalid-name.json', '..');
 describe('modules/manager/npm/extract/index', () => {
   describe('.extractPackageFile()', () => {
     beforeEach(() => {
-      fs.readLocalFile = jest.fn(() => null);
-      fs.localPathExists = jest.fn(() => false);
+      jest.resetAllMocks();
+      fs.readLocalFile.mockResolvedValue(null);
+      fs.localPathExists.mockResolvedValue(false);
+      fs.getSiblingFileName.mockImplementation(realFs.getSiblingFileName);
     });
 
     it('returns null if cannot parse', async () => {
@@ -140,11 +145,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds a lock file', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'yarn.lock') {
-          return '# yarn.lock';
+          return Promise.resolve('# yarn.lock');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -155,11 +160,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds and filters .npmrc', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === '.npmrc') {
-          return 'save-exact = true\npackage-lock = false\n';
+          return Promise.resolve('save-exact = true\npackage-lock = false\n');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -170,7 +175,7 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('uses config.npmrc if no .npmrc exists', async () => {
-      fs.readLocalFile = jest.fn(() => null);
+      fs.readLocalFile.mockResolvedValueOnce(null);
       const res = await npmExtract.extractPackageFile(
         input01Content,
         'package.json',
@@ -180,11 +185,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('uses config.npmrc if .npmrc does exist but npmrcMerge=false', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === '.npmrc') {
-          return 'repo-npmrc\n';
+          return Promise.resolve('repo-npmrc\n');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -195,11 +200,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('merges config.npmrc and repo .npmrc when npmrcMerge=true', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === '.npmrc') {
-          return 'repo-npmrc\n';
+          return Promise.resolve('repo-npmrc\n');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -210,11 +215,13 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds and filters .npmrc with variables', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === '.npmrc') {
-          return 'registry=https://registry.npmjs.org\n//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\n';
+          return Promise.resolve(
+            'registry=https://registry.npmjs.org\n//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}\n'
+          );
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -225,11 +232,30 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('reads registryUrls from .yarnrc.yml', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === '.yarnrc.yml') {
-          return 'npmRegistryServer: https://registry.example.com';
+          return Promise.resolve(
+            'npmRegistryServer: https://registry.example.com'
+          );
+        }
+        return Promise.resolve(null);
+      });
+      const res = await npmExtract.extractPackageFile(
+        input02Content,
+        'package.json',
+        {}
+      );
+      expect(
+        res?.deps.flatMap((dep) => dep.registryUrls)
+      ).toBeArrayIncludingOnly(['https://registry.example.com']);
+    });
+
+    it('reads registryUrls from .yarnrc', async () => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
+        if (fileName === '.yarnrc') {
+          return Promise.resolve('registry "https://registry.example.com"');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input02Content,
@@ -242,11 +268,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds lerna', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'lerna.json') {
-          return '{}';
+          return Promise.resolve('{}');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -261,11 +287,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds "npmClient":"npm" in lerna.json', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'lerna.json') {
-          return '{ "npmClient": "npm" }';
+          return Promise.resolve('{ "npmClient": "npm" }');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -280,11 +306,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds "npmClient":"yarn" in lerna.json', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'lerna.json') {
-          return '{ "npmClient": "yarn" }';
+          return Promise.resolve('{ "npmClient": "yarn" }');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         input01Content,
@@ -299,11 +325,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds simple yarn workspaces', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'lerna.json') {
-          return '{}';
+          return Promise.resolve('{}');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         workspacesSimpleContent,
@@ -314,11 +340,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds simple yarn workspaces with lerna.json and useWorkspaces: true', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'lerna.json') {
-          return '{"useWorkspaces": true}';
+          return Promise.resolve('{"useWorkspaces": true}');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         workspacesSimpleContent,
@@ -329,11 +355,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('finds complex yarn workspaces', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'lerna.json') {
-          return '{}';
+          return Promise.resolve('{}');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const res = await npmExtract.extractPackageFile(
         workspacesContent,
@@ -676,11 +702,11 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('extracts npm package alias', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName: string): Promise<any> => {
         if (fileName === 'package-lock.json') {
-          return '{}';
+          return Promise.resolve('{}');
         }
-        return null;
+        return Promise.resolve(null);
       });
       const pJson = {
         dependencies: {
@@ -705,16 +731,16 @@ describe('modules/manager/npm/extract/index', () => {
     });
 
     it('sets skipInstalls false if Yarn zero-install is used', async () => {
-      fs.readLocalFile = jest.fn((fileName) => {
+      fs.readLocalFile.mockImplementation((fileName): Promise<any> => {
         if (fileName === 'yarn.lock') {
-          return '# yarn.lock';
+          return Promise.resolve('# yarn.lock');
         }
         if (fileName === '.yarnrc.yml') {
-          return 'pnpEnableInlining: false';
+          return Promise.resolve('pnpEnableInlining: false');
         }
-        return null;
+        return Promise.resolve(null);
       });
-      fs.localPathExists = jest.fn(() => true);
+      fs.localPathExists.mockResolvedValueOnce(true);
       const res = await npmExtract.extractPackageFile(
         input01Content,
         'package.json',
diff --git a/lib/modules/manager/npm/extract/index.ts b/lib/modules/manager/npm/extract/index.ts
index a4425de015b5efff5e3ee30eb3351c2d2eeafeb2..7bdb16c5283bbd7274832319d340d90514ea54c5 100644
--- a/lib/modules/manager/npm/extract/index.ts
+++ b/lib/modules/manager/npm/extract/index.ts
@@ -22,6 +22,7 @@ import type { NpmPackage, NpmPackageDependency } from './types';
 import { isZeroInstall } from './yarn';
 import {
   YarnConfig,
+  loadConfigFromLegacyYarnrc,
   loadConfigFromYarnrcYml,
   resolveRegistryUrl,
 } from './yarnrc';
@@ -149,6 +150,12 @@ export async function extractPackageFile(
     yarnConfig = loadConfigFromYarnrcYml(repoYarnrcYml);
   }
 
+  const legacyYarnrcFileName = getSiblingFileName(fileName, '.yarnrc');
+  const repoLegacyYarnrc = await readLocalFile(legacyYarnrcFileName, 'utf8');
+  if (is.string(repoLegacyYarnrc)) {
+    yarnConfig = loadConfigFromLegacyYarnrc(repoLegacyYarnrc);
+  }
+
   let lernaJsonFile: string | undefined;
   let lernaPackages: string[] | undefined;
   let lernaClient: 'yarn' | 'npm' | undefined;
diff --git a/lib/modules/manager/npm/extract/yarnrc.spec.ts b/lib/modules/manager/npm/extract/yarnrc.spec.ts
index 0b77d7ccf34cf9ebe314e536292901c315b2e30a..be41b1593cbd547b50fa92104bc10e7f81413c39 100644
--- a/lib/modules/manager/npm/extract/yarnrc.spec.ts
+++ b/lib/modules/manager/npm/extract/yarnrc.spec.ts
@@ -1,5 +1,9 @@
 import { codeBlock } from 'common-tags';
-import { loadConfigFromYarnrcYml, resolveRegistryUrl } from './yarnrc';
+import {
+  loadConfigFromLegacyYarnrc,
+  loadConfigFromYarnrcYml,
+  resolveRegistryUrl,
+} from './yarnrc';
 
 describe('modules/manager/npm/extract/yarnrc', () => {
   describe('resolveRegistryUrl()', () => {
@@ -108,4 +112,51 @@ describe('modules/manager/npm/extract/yarnrc', () => {
       expect(config).toEqual(expectedConfig);
     });
   });
+
+  describe('loadConfigFromLegacyYarnrc()', () => {
+    it.each([
+      [
+        codeBlock`
+          # yarn lockfile v1
+          registry "https://npm.example.com"
+        `,
+        {
+          npmRegistryServer: 'https://npm.example.com',
+        },
+      ],
+      [
+        codeBlock`
+          disturl "https://npm-dist.example.com"
+          registry https://npm.example.com
+          sass_binary_site "https://node-sass.example.com"
+        `,
+        {
+          npmRegistryServer: 'https://npm.example.com',
+        },
+      ],
+      [
+        codeBlock`
+          --install.frozen-lockfile true
+          "registry" "https://npm.example.com"
+          "@foo:registry" "https://npm-foo.example.com"
+          "@bar:registry" "https://npm-bar.example.com"
+        `,
+        {
+          npmRegistryServer: 'https://npm.example.com',
+          npmScopes: {
+            foo: {
+              npmRegistryServer: 'https://npm-foo.example.com',
+            },
+            bar: {
+              npmRegistryServer: 'https://npm-bar.example.com',
+            },
+          },
+        },
+      ],
+    ])('produces expected config (%s)', (legacyYarnrc, expectedConfig) => {
+      const config = loadConfigFromLegacyYarnrc(legacyYarnrc);
+
+      expect(config).toEqual(expectedConfig);
+    });
+  });
 });
diff --git a/lib/modules/manager/npm/extract/yarnrc.ts b/lib/modules/manager/npm/extract/yarnrc.ts
index 49e32e218436a4a59e317ee8dccf1704ea818347..06e5d9caf0141f9a54e84f372796f17a67f1235f 100644
--- a/lib/modules/manager/npm/extract/yarnrc.ts
+++ b/lib/modules/manager/npm/extract/yarnrc.ts
@@ -1,6 +1,8 @@
+import is from '@sindresorhus/is';
 import { load } from 'js-yaml';
 import { z } from 'zod';
 import { logger } from '../../../../logger';
+import { regEx } from '../../../../util/regex';
 
 const YarnrcYmlSchema = z.object({
   npmRegistryServer: z.string().optional(),
@@ -15,6 +17,31 @@ const YarnrcYmlSchema = z.object({
 
 export type YarnConfig = z.infer<typeof YarnrcYmlSchema>;
 
+const registryRegEx = regEx(
+  /^"?(@(?<scope>[^:]+):)?registry"? "?(?<registryUrl>[^"]+)"?$/gm
+);
+
+export function loadConfigFromLegacyYarnrc(
+  legacyYarnrc: string
+): YarnConfig | null {
+  const registryMatches = [...legacyYarnrc.matchAll(registryRegEx)]
+    .map((m) => m.groups)
+    .filter(is.truthy);
+
+  const yarnConfig: YarnConfig = {};
+  for (const registryMatch of registryMatches) {
+    if (registryMatch.scope) {
+      yarnConfig.npmScopes ??= {};
+      yarnConfig.npmScopes[registryMatch.scope] ??= {};
+      yarnConfig.npmScopes[registryMatch.scope].npmRegistryServer =
+        registryMatch.registryUrl;
+    } else {
+      yarnConfig.npmRegistryServer = registryMatch.registryUrl;
+    }
+  }
+  return yarnConfig;
+}
+
 export function loadConfigFromYarnrcYml(yarnrcYml: string): YarnConfig | null {
   try {
     const obj = load(yarnrcYml, {