diff --git a/lib/modules/manager/flux/__fixtures__/helmChart.yaml b/lib/modules/manager/flux/__fixtures__/helmChart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a96fbe201d7c493a0a74c2e9f9074e8f9c9f1846
--- /dev/null
+++ b/lib/modules/manager/flux/__fixtures__/helmChart.yaml
@@ -0,0 +1,14 @@
+apiVersion: source.toolkit.fluxcd.io/v1
+kind: HelmChart
+metadata:
+  name: sealed-secrets
+  namespace: kube-system
+spec:
+  interval: 10m
+  chart: sealed-secrets
+  sourceRef:
+    kind: HelmRepository
+    name: sealed-secrets
+  version: "2.0.2"
+  valuesFiles:
+    - values-prod.yaml
diff --git a/lib/modules/manager/flux/__fixtures__/helmChartRefRelease.yaml b/lib/modules/manager/flux/__fixtures__/helmChartRefRelease.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a25c42a14325bc43d84ef7884d2170b1948ae306
--- /dev/null
+++ b/lib/modules/manager/flux/__fixtures__/helmChartRefRelease.yaml
@@ -0,0 +1,13 @@
+apiVersion: helm.toolkit.fluxcd.io/v2
+kind: HelmRelease
+metadata:
+  name: sealed-secrets
+  namespace: kube-system
+spec:
+  interval: 10m
+  chartRef:
+    kind: HelmChart
+    name: sealed-secrets
+    namespace: kube-system
+  values:
+    replicaCount: 2
diff --git a/lib/modules/manager/flux/extract.spec.ts b/lib/modules/manager/flux/extract.spec.ts
index eb90d5add9e6fbaa4ae7ba4780f126b580854666..c2cb2c866163855295bc6866b20e8cd39f752809 100644
--- a/lib/modules/manager/flux/extract.spec.ts
+++ b/lib/modules/manager/flux/extract.spec.ts
@@ -14,6 +14,9 @@ import { extractAllPackageFiles, extractPackageFile } from '.';
 
 const config: ExtractConfig = {};
 const adminConfig: RepoGlobalConfig = { localDir: '' };
+const fixtureHelmSource = Fixtures.get('helmSource.yaml');
+const fixtureHelmChart = Fixtures.get('helmChart.yaml');
+const fixtureHelmChartRefRelease = Fixtures.get('helmChartRefRelease.yaml');
 
 describe('modules/manager/flux/extract', () => {
   beforeEach(() => {
@@ -162,6 +165,22 @@ describe('modules/manager/flux/extract', () => {
       });
     });
 
+    it('ignores HelmRelease resources without any chart reference', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          apiVersion: helm.toolkit.fluxcd.io/v2beta1
+          kind: HelmRelease
+          metadata:
+            name: sealed-secrets
+            namespace: kube-system
+          spec:
+            interval: 10m
+        `,
+        'test.yaml',
+      );
+      expect(result).toBeNull();
+    });
+
     it('ignores HelmRelease resources without a chart name', () => {
       const result = extractPackageFile(
         codeBlock`
@@ -240,7 +259,7 @@ describe('modules/manager/flux/extract', () => {
     it('does not match HelmRelease resources without a sourceRef', () => {
       const result = extractPackageFile(
         codeBlock`
-          ${Fixtures.get('helmSource.yaml')}
+          ${fixtureHelmSource}
           ---
           apiVersion: helm.toolkit.fluxcd.io/v2beta1
           kind: HelmRelease
@@ -270,7 +289,7 @@ describe('modules/manager/flux/extract', () => {
     it('does not match HelmRelease resources without a namespace', () => {
       const result = extractPackageFile(
         codeBlock`
-          ${Fixtures.get('helmSource.yaml')}
+          ${fixtureHelmSource}
           ---
           apiVersion: helm.toolkit.fluxcd.io/v2beta1
           kind: HelmRelease
@@ -337,6 +356,182 @@ describe('modules/manager/flux/extract', () => {
       });
     });
 
+    it('ignores HelmRelease resources using an invalid chartRef', () => {
+      const result = extractPackageFile(
+        fixtureHelmChartRefRelease,
+        'test.yaml',
+      );
+      expect(result).toBeNull();
+    });
+
+    it('ignores HelmRelease resources using a chartRef targetting a HelmChart', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          ${fixtureHelmChartRefRelease}
+          ---
+          ${fixtureHelmChart}
+          ---
+          ${fixtureHelmSource}
+        `,
+        'test.yaml',
+      );
+      // HelmRelease is ignored, only HelmChart itself is processed (-> no duplicates expected)
+      expect(result).toEqual({
+        deps: [
+          {
+            currentValue: '2.0.2',
+            datasource: HelmDatasource.id,
+            depName: 'sealed-secrets',
+            registryUrls: ['https://bitnami-labs.github.io/sealed-secrets'],
+          },
+        ],
+      });
+    });
+
+    it('ignores HelmRelease resources using a chartRef targetting an OCIRepository', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          ${Fixtures.get('ociSource.yaml')}
+          ---
+          apiVersion: helm.toolkit.fluxcd.io/v2
+          kind: HelmRelease
+          metadata:
+            name: kyverno-controller
+            namespace: kube-system
+          spec:
+            chartRef:
+              kind: OCIRepository
+              name: kyverno-controller
+              namespace: kube-system
+        `,
+        'test.yaml',
+      );
+      // HelmRelease is ignored, only OCIRepository itself is processed (-> no duplicates expected)
+      expect(result).toEqual({
+        deps: [
+          {
+            autoReplaceStringTemplate:
+              '{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}',
+            currentDigest: undefined,
+            currentValue: 'v1.8.2',
+            depName: 'ghcr.io/kyverno/manifests/kyverno',
+            packageName: 'ghcr.io/kyverno/manifests/kyverno',
+            datasource: DockerDatasource.id,
+            replaceString: 'v1.8.2',
+          },
+        ],
+      });
+    });
+
+    it('extracts HelmChart version', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          ${fixtureHelmSource}
+          ---
+          ${fixtureHelmChart}
+        `,
+        'test.yaml',
+      );
+      expect(result).toEqual({
+        deps: [
+          {
+            currentValue: '2.0.2',
+            datasource: HelmDatasource.id,
+            depName: 'sealed-secrets',
+            registryUrls: ['https://bitnami-labs.github.io/sealed-secrets'],
+          },
+        ],
+      });
+    });
+
+    it('does not match HelmChart resources without a namespace', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          ${fixtureHelmSource}
+          ---
+          apiVersion: source.toolkit.fluxcd.io/v1
+          kind: HelmChart
+          metadata:
+            name: sealed-secrets
+          spec:
+            interval: 10m
+            chart: sealed-secrets
+            sourceRef:
+              kind: HelmRepository
+              name: sealed-secrets
+            version: "2.0.2"
+        `,
+        'test.yaml',
+      );
+      expect(result).toEqual({
+        deps: [
+          {
+            currentValue: '2.0.2',
+            datasource: HelmDatasource.id,
+            depName: 'sealed-secrets',
+            skipReason: 'unknown-registry',
+          },
+        ],
+      });
+    });
+
+    it('ignores HelmChart resources using git sources', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          apiVersion: source.toolkit.fluxcd.io/v1
+          kind: HelmChart
+          metadata:
+            name: sealed-secrets
+            namespace: kube-system
+          spec:
+            interval: 10m
+            chart: ./helm/sealed-secrets
+            sourceRef:
+              kind: GitRepository
+              name: sealed-secrets
+        `,
+        'test.yaml',
+      );
+      expect(result).toBeNull();
+    });
+
+    it('ignores HelmChart resources using bucket sources', () => {
+      const result = extractPackageFile(
+        codeBlock`
+          apiVersion: source.toolkit.fluxcd.io/v1
+          kind: Bucket
+          metadata:
+            name: sealed-secrets
+            namespace: kube-system
+          spec:
+            interval: 5m0s
+            endpoint: sealed-secrets.example.com
+            bucketName: example
+          ---
+          apiVersion: source.toolkit.fluxcd.io/v1
+          kind: HelmChart
+          metadata:
+            name: sealed-secrets
+            namespace: kube-system
+          spec:
+            interval: 10m
+            chart: ./helm/sealed-secrets
+            sourceRef:
+              kind: Bucket
+              name: sealed-secrets
+        `,
+        'test.yaml',
+      );
+      expect(result).toEqual({
+        deps: [
+          {
+            depName: './helm/sealed-secrets',
+            skipReason: 'unsupported-datasource',
+          },
+        ],
+      });
+    });
+
     it('ignores GitRepository without a tag nor a commit', () => {
       const result = extractPackageFile(
         codeBlock`
@@ -897,5 +1092,26 @@ describe('modules/manager/flux/extract', () => {
       ]);
       expect(result).toBeNull();
     });
+
+    it('should pick correct package file when using HelmRepository with chartRef', async () => {
+      const result = await extractAllPackageFiles(config, [
+        'lib/modules/manager/flux/__fixtures__/helmChartRefRelease.yaml',
+        'lib/modules/manager/flux/__fixtures__/helmChart.yaml',
+        'lib/modules/manager/flux/__fixtures__/helmSource.yaml',
+      ]);
+      expect(result).toEqual([
+        {
+          deps: [
+            {
+              currentValue: '2.0.2',
+              datasource: HelmDatasource.id,
+              depName: 'sealed-secrets',
+              registryUrls: ['https://bitnami-labs.github.io/sealed-secrets'],
+            },
+          ],
+          packageFile: 'lib/modules/manager/flux/__fixtures__/helmChart.yaml',
+        },
+      ]);
+    });
   });
 });
diff --git a/lib/modules/manager/flux/extract.ts b/lib/modules/manager/flux/extract.ts
index 85a0a13b92421f6e087b5d1a0e410a9ab36184f9..cce6fd742216f37cb1822314545029a39d0735e4 100644
--- a/lib/modules/manager/flux/extract.ts
+++ b/lib/modules/manager/flux/extract.ts
@@ -164,6 +164,17 @@ function resolveResourceManifest(
   for (const resource of manifest.resources) {
     switch (resource.kind) {
       case 'HelmRelease': {
+        if (resource.spec.chartRef) {
+          logger.trace(
+            'HelmRelease using chartRef was found, skipping as version will be handled via referenced resource directly',
+          );
+          continue;
+        }
+        if (!resource.spec.chart) {
+          logger.debug('invalid or incomplete HelmRelease spec, skipping');
+          continue;
+        }
+
         const chartSpec = resource.spec.chart.spec;
         const depName = chartSpec.chart;
         const dep: PackageDependency = {
@@ -194,6 +205,37 @@ function resolveResourceManifest(
         }
         break;
       }
+
+      case 'HelmChart': {
+        if (resource.spec.sourceRef.kind === 'GitRepository') {
+          logger.trace(
+            'HelmChart using GitRepository was found, skipping as version will be handled via referenced resource directly',
+          );
+          continue;
+        }
+
+        const dep: PackageDependency = {
+          depName: resource.spec.chart,
+        };
+
+        if (resource.spec.sourceRef.kind === 'HelmRepository') {
+          dep.currentValue = resource.spec.version;
+          dep.datasource = HelmDatasource.id;
+
+          const matchingRepositories = helmRepositories.filter(
+            (rep) =>
+              rep.kind === resource.spec.sourceRef?.kind &&
+              rep.metadata.name === resource.spec.sourceRef.name &&
+              rep.metadata.namespace === resource.metadata?.namespace,
+          );
+          resolveHelmRepository(dep, matchingRepositories, registryAliases);
+        } else {
+          dep.skipReason = 'unsupported-datasource';
+        }
+        deps.push(dep);
+        break;
+      }
+
       case 'GitRepository': {
         const dep: PackageDependency = {
           depName: resource.metadata.name,
diff --git a/lib/modules/manager/flux/readme.md b/lib/modules/manager/flux/readme.md
index 508331962138f00f928922acb0f62f2f6a283156..bf23458a8401bc22f0cc728f1f707dd97aad5c77 100644
--- a/lib/modules/manager/flux/readme.md
+++ b/lib/modules/manager/flux/readme.md
@@ -10,13 +10,15 @@ This manager parses [Flux](https://fluxcd.io/) YAML manifests and supports:
 Extracts `helm` dependencies from `HelmRelease` resources.
 
 The `flux` manager extracts `helm` dependencies for `HelmRelease` resources linked to `HelmRepository` or `GitRepository` sources.
+`HelmRepository` resources can be referenced via `spec.chart` or indirectly via a `HelmChart` when
+using [`spec.chartRef`](https://fluxcd.io/flux/components/helm/helmreleases/#chart-reference).
 Renovate supports OCI `HelmRepository` sources, those with `type: oci`.
 Renovate will then extract the `docker` dependencies for the referenced `HelmRelease` resources.
 
 In addition, for the `flux` manager to properly link `HelmRelease` and `HelmRepository` resources, _both_ of the following conditions must be met:
 
-1. The `HelmRelease` resource must either have its `metadata.namespace` property set or its `spec.chart.spec.sourceRef.namespace` property set
-2. The referenced `HelmRepository` resource must have its `metadata.namespace` property set
+1. The `HelmRelease` resource must either have its `metadata.namespace` property set or its `spec.chart.spec.sourceRef.namespace` property (when not using `chartRef`) set
+2. The referenced `HelmRepository` and `HelmChart` (when using `chartRef`) resources must have their `metadata.namespace` property set
 
 Namespaces will not be inferred from the context (e.g. from the parent `Kustomization`).
 
diff --git a/lib/modules/manager/flux/schema.ts b/lib/modules/manager/flux/schema.ts
index d76ff8fb5b2222a53f3181dc3098c42c86581ef7..87535be52551333780eb053e6c693de583c33273 100644
--- a/lib/modules/manager/flux/schema.ts
+++ b/lib/modules/manager/flux/schema.ts
@@ -16,22 +16,32 @@ export const HelmRelease = KubernetesResource.extend({
   apiVersion: z.string().startsWith('helm.toolkit.fluxcd.io/'),
   kind: z.literal('HelmRelease'),
   spec: z.object({
-    chart: z.object({
-      spec: z.object({
-        chart: z.string(),
-        version: z.string().optional(),
-        sourceRef: z
-          .object({
-            kind: z.string().optional(),
-            name: z.string().optional(),
-            namespace: z.string().optional(),
-          })
-          .optional(),
-      }),
-    }),
+    chart: z
+      .object({
+        spec: z.object({
+          chart: z.string(),
+          version: z.string().optional(),
+          sourceRef: z
+            .object({
+              kind: z.string().optional(),
+              name: z.string().optional(),
+              namespace: z.string().optional(),
+            })
+            .optional(),
+        }),
+      })
+      .optional(),
+    chartRef: z
+      .object({
+        kind: z.string().optional(),
+        name: z.string().optional(),
+        namespace: z.string().optional(),
+      })
+      .optional(),
     values: z.record(z.unknown()).optional(),
   }),
 });
+export type HelmRelease = z.infer<typeof HelmRelease>;
 
 export const HelmRepository = KubernetesResource.extend({
   apiVersion: z.string().startsWith('source.toolkit.fluxcd.io/'),
@@ -43,6 +53,20 @@ export const HelmRepository = KubernetesResource.extend({
 });
 export type HelmRepository = z.infer<typeof HelmRepository>;
 
+export const HelmChart = KubernetesResource.extend({
+  apiVersion: z.string().startsWith('source.toolkit.fluxcd.io/'),
+  kind: z.literal('HelmChart'),
+  spec: z.object({
+    chart: z.string(),
+    version: z.string().optional(),
+    sourceRef: z.object({
+      kind: z.string().optional(),
+      name: z.string().optional(),
+    }),
+  }),
+});
+export type HelmChart = z.infer<typeof HelmChart>;
+
 export const GitRepository = KubernetesResource.extend({
   apiVersion: z.string().startsWith('source.toolkit.fluxcd.io/'),
   kind: z.literal('GitRepository'),
@@ -89,6 +113,7 @@ export const Kustomization = KubernetesResource.extend({
 });
 
 export const FluxResource = HelmRelease.or(HelmRepository)
+  .or(HelmChart)
   .or(GitRepository)
   .or(OCIRepository)
   .or(Kustomization);