A GitOps control plane can look perfectly healthy while its trust boundary has already failed. A custom gRPC client may still decode yesterday’s protobufs; an operator may view logs through privileges nobody audited; a plain-HTTP OCI registry may be configured as an insecure exception. None of it produces a red Application badge. Argo CD v3.5 turns these soft assumptions into upgrade work.
That friction is deliberate. Welcome, too. Argo CD has become the deployment control plane for Kubernetes-heavy estates, so a minor-version upgrade deserves the same design review as a change to cluster ingress or identity. Teams that treat it as a Helm release with a maintenance window will hit sharp edges. Teams that treat GitOps as a security system will get clearer boundaries.
The core Argo CD v3.5 changes are source integrity, comprehensive Kubernetes impersonation, protocol compatibility, and an explicit TLS posture for Helm and OCI repositories. It also includes a React 19 UI migration and a first-class ApplicationSet view. The visible features are useful. The security semantics are the real release.
Argo CD v3.5 upgrades should start at the release train
Argo CD’s documented release process gives platform teams a practical planning signal. Minor releases ship on the first Tuesdays of February, May, August, and November. The first Release Candidate is cut seven weeks before General Availability, creating a feature-freeze period for stabilization and critical fixes. Dates can move slightly around holidays, but the cadence is stable enough to automate against.
Don’t wait for GA to learn that an internal dashboard compiled against an old React runtime no longer mounts, or that a repository service can’t decode a returned event. Promote the RC into a dedicated canary control plane. It needn’t mirror every production cluster, but it must cover every trust pattern: SSH Git, HTTPS Git with an internal CA, Helm HTTP exceptions, OCI dependencies, AppProject impersonation, and installed UI extensions.
Build a control-plane canary, not a disposable demo
Think of the test arrangement as four connected planes. Git repositories and OCI registries sit at the source edge. Argo CD repo-server resolves and renders those sources. argocd-server exposes UI, API, and gRPC access. For applicable Kubernetes API operations, Argo CD uses the AppProject-configured impersonated service account. A v3.5 canary must exercise every edge because each now has more explicit failure conditions.
Use the RC window to run synthetic Applications and ApplicationSets through real syncs, not just manifest rendering. Record render duration, sync duration, reconciliation failures, repository connection errors, authorization denials, and generated Application counts before and after the change. These aren’t published Argo CD v3.5 performance benchmarks; they are your regression baseline. A fleet with 400 generated Applications cares far more about its own p95 reconciliation behavior than a generic benchmark from somebody else’s cluster.
I’d rather hold an upgrade for one clean canary cycle than debug an authorization regression across production clusters during a release freeze. Argo CD’s RC cadence makes that inexpensive, provided the canary is declared infrastructure instead of an afterthought.
Argo CD v3.5 changes the gRPC and impersonation contract
The gRPC change is narrow but non-negotiable. Event-listing APIs now use an Argo CD-defined EventList rather than Kubernetes’ core EventList. The goal is compatibility with newer Kubernetes protobuf definitions without exporting the Kubernetes type directly. The Argo CD CLI does not consume these APIs, so CLI-only operations are unaffected. Custom consumers are different.
If a Go service, a TypeScript gateway, or an internal analytics worker generated stubs from the former service definition, regenerate them against the v3.5 protobuf contract and compile before the server rolls forward. Don’t paper over a type mismatch with JSON conversion at the boundary. That creates a second, unversioned contract exactly where the API contract needs discipline.
# Pin the v3.5 API definitions in the client build, then regenerate.
buf generate
go test ./...
go vet ./...
# Exercise the event path against the v3.5 canary server.
go test ./internal/argocdclient -run TestListEvents
The command sequence is intentionally ordinary. The control isn’t. Treat generated client code as a build artifact tied to the Argo CD server version, then reject a controller promotion if integration tests cannot list and process events. Python and Java clients deserve the same treatment through their respective protobuf generators; the language is incidental.
Impersonation now governs interactive operations too
Before v3.5, AppProject impersonation mainly shaped sync behavior. In v3.5, it applies to all Kubernetes API operations initiated from the UI or API: viewing logs, listing events, deleting resources, and running resource actions. The AppProject-configured impersonated service account becomes the effective identity across the operational surface, not just on the write path.
This is the right model. A person who cannot delete a Deployment through a constrained identity should not gain that power because the request came from an Argo CD button. The upgrade cost is that RBAC omissions become visible. A log view may need get against the relevant subresource; event inspection needs the appropriate read permission; deletion requires delete on the target resource; resource actions map to their own underlying API calls.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: payments-argo-operations
namespace: payments
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "events"]
verbs: ["get", "list"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["delete"]
Do not copy this Role blindly: it is a shape, not a universal policy. Map each AppProject’s permitted interactive workflow to actual Kubernetes verbs and resource names, then test allowed and denied paths with kubectl auth can-i using the same service account identity. Broad cluster-admin bindings make the upgrade appear painless while preserving the defect v3.5 is meant to expose. This is the wrong default for a shared fleet.

Explicit verification and constrained access turn pipeline security into a physical boundary.
Argo CD v3.5 makes TLS and Helm OCI exceptions explicit
The repository path is where convenience has traditionally beaten policy. Argo CD v3.5 deprecates --repo-server-strict-tls in favor of --repo-server-ca-cert-path. Mount the CA bundle at /app/config/server/tls, then configure argocd-server with --repo-server-ca-cert-path=/app/config/server/tls/ca.crt. For environment-driven deployments, use ARGOCD_SERVER_REPO_SERVER_CA_CERT_PATH.
The deprecated flag still works, and both settings can coexist with a warning. Don’t read that as permission to defer the migration indefinitely. A Boolean says little about which trust root is in use. An explicit path makes CA material inspectable, auditable, mountable through standard Kubernetes mechanisms, and separable across environments with different private PKI chains.
containers:
- name: argocd-server
args:
- --repo-server-ca-cert-path=/app/config/server/tls/ca.crt
volumeMounts:
- name: repo-server-ca
mountPath: /app/config/server/tls
readOnly: true
volumes:
- name: repo-server-ca
secret:
secretName: argocd-repo-server-ca
Helm 4.2.1 adds a related hardening point. Helm v4 requires an explicit --plain-http for OCI registries that do not serve TLS; it will not silently downgrade after finding a non-TLS endpoint. In Argo CD v3.5, existing plain-HTTP OCI repository configuration needs --insecure-oci-force-http --upsert through the CLI, or insecureOCIForceHttp: "true" in the Kubernetes Secret that manages the repository. OCI chart dependencies on those registries must also be added explicitly with the insecure setting.
That exception should be noisy in code review. It is a controlled admission that repository transport lacks TLS, not a tuning knob. Retire plain HTTP where possible; where it cannot yet be retired, isolate it, document an owner in repository configuration, and alert on its continued use. I’d rather accept a failed chart fetch than an invisible downgrade on the path to production.
SSH needs the same precision. With newer go-git behavior enforcing host-key validation more strictly, Argo CD now builds SSH authentication itself for repositories lacking configured credentials. Put trusted host keys in argocd-ssh-known-hosts-cm, rather than baking them into custom images or distributing ad hoc volume mounts. Kubernetes-native host trust is reviewable and can be reconciled from Git; image-local host trust is drift waiting for a maintenance window.
Source Integrity and ApplicationSets change what operators can prove
Argo CD v3.5 replaces its GnuPG key verification feature with Source Integrity. This is not a rename to apply casually. GnuPG verification concentrated on signatures for Git sources; Source Integrity provides a broader model for verifying application-source integrity. The project’s upgrade guidance explicitly directs operators through an “Upgrade to Source Integrity Verification” migration, which signals real configuration and policy work.
The practical design question is no longer only, “Which key signs this commit?” It is, “Which source properties must be verified before this Application may reconcile?” That framing fits organizations that combine signed commits, SBOM review, artifact signatures, and external attestation tooling. It also forces a decision about failure semantics: should a failed integrity check leave the last known good revision running, block a new sync, page the platform team, or all three?
Fast delivery without a declared source-trust policy is merely fast propagation.
Keep those decisions in version control beside AppProjects, repository definitions, and workload manifests. The GitOps repository should show the chain of trust without requiring someone to remember which controller flag was set two quarters ago. Argo CD release artifacts also continue to include sbom.tar.gz on normal GitHub releases, a useful reminder that controller supply-chain evidence belongs in the same operational discussion.
Use the ApplicationSet UI as a topology review surface
The React 16 to React 19 frontend move and the new first-class ApplicationSet UI deserve separate tests. UI extensions built for the previous React version may fail to load and should be rebuilt or validated against v3.5. Organizations without installed extensions have no migration action here, but they should still run operator acceptance tests against the updated interface.
ApplicationSets are especially useful in large fleets because one template can fan out through cluster, Git-directory, or list generators into many Applications. The new UI exposes generator details, relationships, and derived behavior beyond YAML. Use it before a broad template change: inspect the generated set, identify excluded clusters, compare expected destinations, and verify what the controller will actually manage. Human-readable topology does not replace Git review. It catches the kind of mistake that a 400-line generator diff makes easy to miss.
Make the Argo CD v3.5 gate a permanent control
A disciplined promotion gate for v3.5 should verify six conditions: regenerated custom gRPC clients, successful and denied impersonation actions, explicit CA-path connectivity, declared plain-HTTP OCI exceptions, expected Source Integrity failures, and React 19 extension loading. Run those checks on every RC, preserve their results with the controller version, and promote the same configuration shape into production.

A staged, well-governed upgrade path makes production change deliberately uneventful.
The concrete takeaway is simple: replace implicit trust with reviewed configuration before Argo CD v3.5 forces the issue. Start with one question in the canary cluster: when a user clicks “delete,” fetches an OCI chart, or syncs a commit, can you point to the exact identity, CA, host key, and integrity policy that authorized it? If not, the upgrade task has found its real scope.
