The critical detail that makes this whole flow secure: step 5 happens server-to-server, away from the browser entirely. The access token — the credential that actually grants access to data — never appears in a URL, a browser history entry, a server access log, or anywhere a malicious script running in the page or a nosy browser extension could intercept it.
The authorization code that does pass through the browser (in step 4's redirect URL) is deliberately weak by itself: it's short-lived (typically valid for under a minute), single-use (Google invalidates it the instant it's redeemed, and treats a second redemption attempt as a signal of possible theft), and useless without the client_secret — a value that only your backend server holds and that never touches the browser at any point. An attacker who somehow captures the code from a redirect URL (via a referrer leak, a compromised network, a browser history sync) still can't exchange it for anything without also having your server's secret.
This is precisely why the Authorization Code flow requires a confidential client — an application with a backend that can safely hold a client_secret without exposing it. A pure single-page app or mobile app, with no backend server and no way to keep a secret truly secret (anything shipped to the client can be extracted from it), can't safely use this flow as originally specified — which is the exact gap PKCE closes.