A secret never lives in the code, nor in the git repo. It lives in the environment, injected at runtime. The code reads process.env; it never knows the value.
A .env committed once stays in git history forever, even if deleted later. The only real fix: rotate (revoke + regenerate) the exposed secret.
Masked CI/CD variables are exactly those from using GitLab CI/CD well.
Two reflexes: never put a secret in a NEXT_PUBLIC_ variable (it ends up in the client bundle), and validate that secrets are present at boot rather than discovering one is missing mid-request in prod.
The NEXT_PUBLIC_ boundary is the same trap as in the basic security holes in a Next.js app.