Using @-hashes doesn't assure you of not getting pwned the same way here. How are you getting the @-hash, if not just looking at what the tag points to?
Sure, the image is changing now only at intentional times (as opposed to just any restart), but you're still not getting an assurance that a "trusted" upstream isn't going to RCE you. Security updates & patches come out with such frequency that the number of windows of opportunity are still plentiful.
Better advice would be to use tags, but to vendor the images somewhere and point at the vendored copies. You still get the "doesn't change on random restart", you have an idea of what version you're on that the hash doesn't tell you, you don't have to deal with Docker hashes being the weird AF things they are (e.g., you side-step the confusion that library/foo@sha256:XXXXX == vendored/foo@sha256:YYYYY), and you're more respectful of upstream's bandwidth and you're not dependent on their reliability concerns.
(And frankly, given how poorly most of the industry handles security updates, I'd argue that sitting on a very loose tag might be more secure overall, because then security patches might be happening at random times, as opposed to not at all. The trade-off of the RCE is worth it, and there are ways for upstreams to mitigate the risk there, centrally. Most companies struggle with just vendoring, and few get to actually keeping that up-to-date, IME due to a lack of willingness to apply the necessary resources to the problem.)
> Using @-hashes doesn't assure you of not getting pwned the same way here
It does, changes to the image could be pushed to "latest" or a specific tag, but the hash cannot change, once you've established that a specific hash is secure, it'll remain secure (or rather, as secure as you first established it as).
I think the parent comments point was that it’s difficult, if not impossible, to verify the security of even a particular hash. It’s still vulnerable to the same dependency chain vulnerabilities as pinning to latest, but instead locking in a particular version and _hoping_ that it wasn’t pwned. Additionally, you are then not getting any exploit fixes that may be included in newer versions, so even if there was a vulnerability you are now stuck with it until you decide to manually update.
To be honest if you’re that concerned with dependency attacks like that then you should just be hosting your own image registry and building your images yourself, and then only being vulnerable to dependency attacks within the OS distributions and such.
You can use a image like golang:1.20.1-alpine3.17@sha256:48f336ef8366b9d6246293e3047259d0f614ee167db1869bdbc343d6e09aed8a and be able to both see the version (human-parseable)and the hash (machine-parseable)
Dependabot will update both the version and hash parts of the tag in a pull request. Pretty magical if you ask me. I haven't found a way for it to auto-apply yet but Renovate can do it if you want automatic updates.
A future compromise of a publisher key by a malware injecting party cannot compromise you if you don't update. Pulling from a tag leaves you open to this at any time without warning if the image publisher is compromised.
Sure, the image is changing now only at intentional times (as opposed to just any restart), but you're still not getting an assurance that a "trusted" upstream isn't going to RCE you. Security updates & patches come out with such frequency that the number of windows of opportunity are still plentiful.
Better advice would be to use tags, but to vendor the images somewhere and point at the vendored copies. You still get the "doesn't change on random restart", you have an idea of what version you're on that the hash doesn't tell you, you don't have to deal with Docker hashes being the weird AF things they are (e.g., you side-step the confusion that library/foo@sha256:XXXXX == vendored/foo@sha256:YYYYY), and you're more respectful of upstream's bandwidth and you're not dependent on their reliability concerns.
(And frankly, given how poorly most of the industry handles security updates, I'd argue that sitting on a very loose tag might be more secure overall, because then security patches might be happening at random times, as opposed to not at all. The trade-off of the RCE is worth it, and there are ways for upstreams to mitigate the risk there, centrally. Most companies struggle with just vendoring, and few get to actually keeping that up-to-date, IME due to a lack of willingness to apply the necessary resources to the problem.)