# v3.4 to 3.5

## Breaking Changes

###  Helm was upgraded to `4.2.0`. 

In Helm v4, the OCI implementation is more strict: if the registry doesn't speak TLS, it is required to explicitly use `--plain-http` upon `helm push`, `helm registry login` and upon `helm dependency build`. 

This is a breaking change for Argo CD users with plain HTTP OCI registries. Two actions may be required:

#### Set --insecure-oci-force-http on existing OCI repos

For any existing OCI repository that uses plain HTTP (not HTTPS), add the flag via CLI (CLI version 3.5): `repo add ... --insecure-oci-force-http --upsert`   
Or set it directly in the Kubernetes secret:
```yaml
stringData:
   insecureOCIForceHttp: "true"
```

#### Explicitly register plain HTTP dependency repos

If your Helm charts have OCI dependencies (Chart.yaml dependencies with repository: `oci://...`) hosted on plain HTTP registries, those dependency repos must now be explicitly added to Argo CD with the `--insecure-oci-force-http` flag, the same way as described above. With Helm v3 this was not required — plain HTTP OCI dependency registries were accessed transparently without registration. With Helm v4, Argo CD needs to know which dependency registries use plain HTTP in order to pass `--plain-http` to `helm dependency build`.

#### Known limitation — conflicting TLS flags (Helm v4)

For Argo CD OCI repo, setting both `--insecure-skip-server-verification` (passed to Helm as `--insecure-skip-tls-verify`) and `--insecure-oci-force-http` (passed to Helm as `--plain-http`) causes Helm v4 to silently drop `--plain-http`, as `--insecure-skip-tls-verify` takes internal precedence. Plain HTTP registry operations then fail with `http: server gave HTTP response to HTTPS client`. This affects:

- Argo CD repos with `type=helm` with `--enable-oci`: having both flags on the same repo causes the chart pull to fail.
- Argo CD repos with `type=oci` and `type=helm` with dependencies: `--insecure-skip-server-verification` on the main repo combined with `--insecure-oci-force-http` on any dependency repo causes dependency build to fail.

There is no workaround when both configurations are legitimately required in the same chain. 

#### Applications with spec.source.helm.version setting

If you historically have the following setting on your Helm application, the setting is ignored and Argo CD will use Helm v4 only to render your charts:

```yaml
spec:
  source:
    helm:
      version: v3
```

You are not required to update or remove this field, and can leave this setting as is.

### UI extensions must externalize `react/jsx-runtime`

The Argo CD UI was upgraded from React 16 to React 19 in 3.5. UI extensions built against an older Argo CD UI may fail to load with a `TypeError` until they are rebuilt to externalize `react/jsx-runtime`.

The host UI surfaces the failure as:

```
Extension <name>.js failed to load: TypeError: Cannot read properties of undefined (reading '<prop>')
```

See [UI Extensions: React 19 Upgrade](./ui-extensions-react-19-upgrading.md) for the full remediation guide.

No action is required for users that do not install UI extensions.

### Event-listing gRPC methods now return an Argo CD `EventList` type

Argo CD 3.5 changes the gRPC response type of the event-listing APIs from
`k8s.io.api.core.v1.EventList` to an Argo CD-defined `EventList` type to remain
compatible with newer Kubernetes protobuf definitions without exposing the
Kubernetes protobuf type directly in Argo CD's public gRPC surface.

The affected gRPC methods are:

- `application.ApplicationService/ListResourceEvents`
- `applicationset.ApplicationSetService/ListResourceEvents`
- `project.ProjectService/ListEvents`

#### Impact on gRPC clients

Any generated or custom gRPC client that calls these methods must be
regenerated or upgraded together with the Argo CD 3.5 server.

This includes any program or script that directly invokes the affected
event-listing RPCs. Using the grpc-web protocol is not a compatibility
workaround for this change.

The Argo CD CLI does not use these APIs and so it **is not** affected.

#### Impact on REST clients and the UI

The REST endpoints and paths remain unchanged:

- `GET /api/v1/applications/{name}/events`
- `GET /api/v1/applicationsets/{name}/events`
- `GET /api/v1/projects/{name}/events`

The JSON response body continues to use the same `EventList`-shaped
payload, so the Argo CD UI and any REST integrations that consume
these endpoints as JSON are not impacted.

#### OpenAPI / schema note

Although the REST paths and JSON payload remain the same, the generated OpenAPI
schema for these endpoints now uses Argo CD's `eventsEventList` definition
instead of `io.k8s.api.core.v1.EventList`.

If you generate REST clients from Argo CD's OpenAPI definition, treat this as a
schema-level breaking change and regenerate or update those clients during the
upgrade.

## Behavioral Improvements / Fixes

### Impersonation extended to server operations

When [impersonation](../app-sync-using-impersonation.md) is enabled, it now applies to all API server operations, not just sync operations. This means that actions triggered through the UI or API (viewing logs, listing events, deleting resources, running resource actions, etc.) will use the impersonated service account derived from the AppProject's `destinationServiceAccounts` configuration.

Previously, impersonation only applied to sync operations.

**Affected operations and required permissions:**

| Operation | Kubernetes API call | Required RBAC verbs |
|---|---|---|
| Get resource | `GET` on the target resource | `get` |
| Patch resource | `PATCH` on the target resource | `get`, `patch` |
| Delete resource | `DELETE` on the target resource | `delete` |
| List resource events | `LIST` on `events` (core/v1) | `list` |
| View pod logs | `GET` on `pods` and `pods/log` | `get` |
| Run resource action | `GET`, `CREATE`, `PATCH` on the target resource | `get`, `create`, `patch` |

This list covers built-in operations. Custom resource actions may require additional permissions depending on what Kubernetes API calls they make.

Users with impersonation enabled must ensure the service accounts configured in `destinationServiceAccounts` have permissions for these operations.

No action is required for users who do not have impersonation enabled.

### SSH `known_hosts` now used for repositories without configured credentials

Argo CD upgraded `go-git` to v5.19.x, which tightens SSH host-key verification. To keep host-key validation working against the Argo CD–managed `argocd-ssh-known-hosts-cm` ConfigMap (and to avoid `knownhosts: key mismatch` handshake failures with the new go-git), Argo CD now builds the SSH auth itself for repositories that don't have explicit credentials configured.

Previously, when an SSH repository URL had no credentials configured in Argo CD, the repo server let go-git fall back to its default auth builder, which constructs an `ssh-agent`-based auth and reads `known_hosts` from `~/.ssh/known_hosts` (or `$SSH_KNOWN_HOSTS`) inside the repo-server container. Now, Argo CD builds the same `ssh-agent`-based auth itself but wires the host-key callback to the `argocd-ssh-known-hosts-cm` ConfigMap, matching the behavior of repositories that *do* have credentials configured.

If your repo server image / pod previously relied on a custom `~/.ssh/known_hosts` (e.g. baked into a custom image or mounted in via a volume) for SSH repositories without configured credentials, add those host keys to `argocd-ssh-known-hosts-cm` instead.

No action is required for users who only access SSH repositories with credentials configured in Argo CD, or who access only HTTPS repositories.

### GnuPG signature verification replaced by Source Integrity

The GnuPG key verification feature has been replaced by [Source Integrity](../../user-guide/source-integrity.md), a more versatile subsystem for verifying the integrity of application sources.

Consult [Upgrade to Source Integrity Verification](../../user-guide/source-integrity-git-gpg.md#upgrade-to-source-integrity-verification) section for the migration details.

Legacy configurations will continue to function temporarily (issuing a warning) to facilitate migration.

No action is required for users that do not use GnuPG signature verification.

## API Changes

## Security Changes

## Deprecated Items

### GnuPG signature configuration

- Modification of project signature keys using `argocd proj add-signature-key` and `argocd proj remove-signature-key` is deprecated.
- Declaring `.spec.signatureKeys` in `AppProject` is deprecated.

Configure `sourceIntegrity` in `AppProject` YAML instead.

### GnuPG signature verification result

- Reading GnuPG verification results from `verifyResult` in REST API is deprecated.

Consume structured result from `sourceIntegrityResult` field instead.

## Kustomize Upgraded

## Helm Upgraded

Helm was upgraded to `4.2.1`, resulting in some breaking changes described in the `Breaking changes` section of this doc.

## Custom Healthchecks Added

## Other Changes

### Release `sbom.tar.gz` contents

For normal GitHub releases, **`sbom.tar.gz`** still includes **`bom-go-mod.spdx`** (Go dependencies, tag-value SPDX from `spdx-sbom-generator`) and **`bom-docker-image.spdx`** (the published release image, tag-value SPDX from `sigs.k8s.io/bom`). The UI dependency list is now **`bom-ui-pnpm.spdx.json`**: **SPDX 2.3 JSON** from **`pnpm sbom`**, replacing the old tag-value **`./ui`** output from `spdx-sbom-generator`.

If you consume this archive with tooling that only looked at **`*.spdx`** files, extend it to handle **`bom-ui-pnpm.spdx.json`** as well, or verify **`sbom.tar.gz`** using **`argocd-sbom.intoto.jsonl`** without depending on a fixed internal file list.

### mTLS support for repo-server

mTLS is opt-in and disabled by default — no action is required for operators who do not configure it.

To enable mTLS, create the `argocd-repo-server-mtls` Secret with the following keys:

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: argocd-repo-server-mtls
  namespace: argocd
type: Opaque
stringData:
  client-ca.crt: |
    <PEM-encoded CA certificate that signed the client certs>
  client.crt: |
    <PEM-encoded shared client certificate>
  client.key: |
    <PEM-encoded private key for the shared client certificate>
```

The Secret is automatically mounted at `/app/config/reposerver/mtls` in every relevant pod. All components default to reading their cert/key/CA files from that mount path, so **mTLS is enabled automatically as soon as the Secret exists** — no ConfigMap changes, flag overrides, or additional configuration are required.

Key points:

- Repo server (server-side):
  - `--client-ca-path` defaults to `/app/config/reposerver/mtls/client-ca.crt` (the auto-mounted Secret path). mTLS is enabled when the file exists; silently skipped if absent.
  - Cannot be combined with `--disable-tls`.
  - Server TLS cert/key are loaded from `/app/config/reposerver/tls/tls.crt` and `/app/config/reposerver/tls/tls.key`.
- Clients (argocd-server, application-controller, applicationset-controller, notifications-controller):
  - `--repo-server-client-cert-path` defaults to `/app/config/reposerver/mtls/client.crt`; mTLS client cert is skipped if the file does not exist.
  - `--repo-server-client-cert-key-path` defaults to `/app/config/reposerver/mtls/client.key`; mTLS client cert is skipped if the file does not exist.
  - `--repo-server-ca-cert-path` is optional and used if the repo-server’s server certificate is signed by a custom CA.

Operational notes:

- When mTLS is enabled on repo-server, it automatically generates an ephemeral client certificate for its own liveness self-check; you do not need to modify probes.
- Equivalent environment variables and `argocd-cmd-params-cm` ConfigMap keys exist for all settings above; see the linked docs for names and examples.

See the dedicated [mTLS documentation](../mtls.md) for full setup instructions, per-component cert options, verification steps, and troubleshooting.


### The --repo-server-strict-tls flag (deprecated in favor of --repo-server-ca-cert-path)

The `--repo-server-strict-tls` boolean flag is deprecated across all components:
- `argocd-server`
- `argocd-application-controller`
- `argocd-applicationset-controller`
- `argocd-notification`

**Reason for deprecation:** The old flag used implicit behavior (automatically loading embedded certificates from `/app/config/server/tls/`),
making it difficult to maintain consistency across components. The new approach is more explicit and aligns with Kubernetes Secret mounting patterns.

**Important:** This deprecation does **NOT** affect TLS capabilities. Operators can still configure TLS-only connections (without mTLS) using the new flag.

#### Migration Guide

The deprecated flag will continue to work in 3.5 (with warnings), but you should migrate to the new approach:

**Option 1: Migrate to `--repo-server-ca-cert-path` (Recommended)**

Replace the deprecated flag with an explicit CA certificate path:

```bash
# Before (3.4 and earlier):
argocd-server \
  --repo-server-strict-tls

# After (3.5):
argocd-server \
  --repo-server-ca-cert-path=/app/config/server/tls/ca.crt
```

**Kubernetes manifests:**

```yaml
# Before:
spec:
  containers:
  - name: argocd-server
    args:
    - argocd-server
    - --repo-server-strict-tls
    volumeMounts:
    - name: server-tls
      mountPath: /app/config/server/tls

# After:
spec:
  containers:
  - name: argocd-server
    args:
    - argocd-server
    - --repo-server-ca-cert-path=/app/config/server/tls/ca.crt
    volumeMounts:
    - name: server-tls
      mountPath: /app/config/server/tls
```

**Option 2: Use environment variable (Alternative)**

Instead of a flag, use the corresponding environment variable:

```bash
# Before:
argocd-server --repo-server-strict-tls

# After:
export ARGOCD_SERVER_REPO_SERVER_CA_CERT_PATH=/app/config/server/tls/ca.crt
argocd-server
```

**Option 3: Continue using deprecated flag (Not recommended, temporary only)**

The flag will continue to work in 3.5 but will issue a deprecation warning. Using both flags together is supported:

```bash
# This continues to work in 3.5 (but will show deprecation warning):
argocd-server \
  --repo-server-strict-tls \
  --repo-server-ca-cert-path=/app/config/server/tls/ca.crt
```

#### Backward Compatibility

- Both flags work together using OR semantics: if either is set to true, strict validation is enabled
- No functionality is lost; TLS validation capabilities remain unchanged
- The new flag is more explicit and maintainable

#### Timeline

- **v3.5:** Deprecated flag still works (with warnings)
- **v3.6+:** Flag may be removed; plan migration accordingly

All components affected (server, application-controller, applicationset-controller, notification-controller) follow the same migration pattern.