StalkR
blog.stalkr.net · Personal blog · on HN since 2013
StalkR writes about security research, with posts on exploiting Go data races, heap corruption, and capture-the-flag challenges.
What HN saysHN commenters cite his 2015 post as the main evidence that Go is not memory safe when data races involve multiword values.
24HN people shared it
22linked it in comments
3stories submitted
63story points
10 months agolast shared
2013people per year2026
Most-shared posts
- 1Golang data races to break memory safety15 people · 1 points · first shared 2016 · discussion on HN
- 2Universal Go exploit using data races, no imports6 people · 2 points · first shared 2022 · discussion on HN
- 3Golang heap corruption during garbage collection2 people · 60 points · first shared 2013 · 29 comments on HN
- 4Golang data races to break memory safety2 people · first shared 2019
- 5The gomium browser google ctf 20191 people · first shared 2022
- 6Login notifications pamexec scripting1 people · first shared 2016
What HN people wrote when they linked it
Jweb_Guru · 2018-08-30
It's worth noting that Go's value types are not actually memory safe, however, since it allows nontrivial concurrent mutations to shared multiword objects (as described in https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe… Unless that got fixed recently somehow?
I believe in most of the other languages you mention, value types are restricted in various ways to avoid that problem (for instance, mutations are only allowed to value types on the stack that don't escape, or multiword value types can only be updated in ways that preserve data structure validity even if updates "tear", or multiword value types are immutable).
K0nserv · 2025-12-26
Changes to multi-word pointers can cause UB due to race conditions in Go because only changes at the word level are atomic.
See: https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
codys · 2025-12-26
Go can have memory unsafety leading to arbitrary memory reads and writes by having an interface replaced by another thread (go interfaces use 2 words, one for the vtable and another for the data. It does not replace these in a thread safe way, so one can use a vtable to work with an unexpected data pointer.
Folks have shown this allows the kinds of arbitrary memory reads/writes that folks normally ban in their definition of memory safe (and this post's website has a definition does as well):
https://research.swtch.com/gorace
https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
https://www.ralfj.de/blog/2025/07/24/memory-safety.html
sapiogram · 2024-02-18
> Level 2 - memory safe and data races allowed
> Languages where parallelism is memory safe, but can still lead to data races.
> This includes Java and Go.
Despite this common misconception, parallel Go is absolutely not memory safe: https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
throwaway858 · 2023-12-19
The current implementation is not memory safe. Go uses 128 bit structs for interfaces and slices and assumes that they are updated atomically (when they are not).
It's possible to exploit this to read/write arbitrary memory and to execute arbitrary code. It appears that in practice this is very difficult so the issue is ignored.
https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
jonnytran · 2023-12-12
The same author has a post from 2022 [1].
> Is it possible to achieve arbitrary code execution on any Go version, even with PIE, and with no package import at all, just builtins? Yes!
Whether it's capture the flag is irrelevant, IMO, because anything that's allowed by the compiler will emerge given enough complexity.
1: https://blog.stalkr.net/2022/01/universal-go-exploit-using-data-races.…
gunapologist99 · 2022-11-11
Very interesting, thank you!
Looking at the attack vector (https://blog.stalkr.net/2019/11/the-gomium-browser-google-ctf-2019.htm… this is a pretty tightly constrained circumstance where you are permitting an attacker to execute unknown Golang code within the context of your process. (perhaps like the Go Playground, if that's not starting a new process for each user.)
I don't personally think that's really that applicable to regular golang users, unless they're trying to sandbox Golang code somehow within the language itself. (And if you are allowing untrusted code, then it's basically game over anyway).
But it's still interesting and I added a note to my comment above about your point.
mirashii · 2022-11-11
> In other words, golang changes the risk of a data race from being a vulnerability to just a program-crashing bug.
I don't believe this is true, people have demonstrated using data races to build arbitrary code execution primitives. See for example https://blog.stalkr.net/2022/01/universal-go-exploit-using-data-races.…
suremarc · 2022-11-08
Indeed, this person showed that you can read/write to arbitrary memory addresses inside of a Go program: https://blog.stalkr.net/2022/01/universal-go-exploit-using-data-races.…
Although, it's pretty useless as an exploit, since it requires you to be able to run arbitrary Go code to begin with (the author admits as much). It's _very_ unlikely that a remote attacker could exploit a data race in a regular Go program.
fulafel · 2022-10-29
> this has ever been proven exploitable
I agree (typo exploit!)
See eg
https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe… & https://blog.stalkr.net/2022/01/universal-go-exploit-using-data-races.…
(And also people shouldn't take "nobody developed an exploit for this vulnerability yet" as any kind of strong evidence, attacks techniques always get better, never worse, over time etc - crypto algorithm people have it right when they start bracing for impact quite early after signs of a theoretical break)
masklinn · 2022-06-11
> Memory safe [...] trivial concurrent programming
As this post demonstrates, data races are trivial and common in Go.
Because many of the core types (interface, slice, map) are non-thread-safe multiword structures, they also break memory safety: https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
ngrilly · 2022-06-03
> I can assure you that you cannot access undefined memory regions by doing this in Go.
Current implementation of slices and interfaces in Go is not memory safe in presence of data races:
https://blog.stalkr.net/2022/01/universal-go-exploit-using-data-races.…
staticassertion · 2021-07-27
To be clear, yes. The issue is with how Go's "interface{}"s (and some other types - like slices, etc) work - it's two pointers that can't be written to atomically, which means you can get into a situation where your objects are invalid.
https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
Here you can find a POC.
You could argue that this is contrived, but it's also not going to be fixed. This is in contrast to Rust, where there may be implementation flaws leading to unsafety in safe code, but the language retains the right to fix those, even if it breaks code.
Still, I think there's really no question that Go is a major step up over C and C++.
nyanpasu64 · 2021-07-21
I've seen Qt Creator segfault due to the CMake plugin doing some strange QStringList operations on an inconsistent "implicitly shared" collection, that I guess broke due to multithreading (though I'm not sure exactly what happened). In RSS Guard, performing two different "background sync" operations causes two different threads to touch the same list collections, producing a segfault. (These are due to multiple threads touching the same collection/pointers; racing on primitive values is probably less directly going to lead to memory unsafety.)
Apparently in Golang, you can achieve memory unsafety through data races: https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe… (though I'm not sure if a workaround has been added to prevent memory unsafety).
voidnullnil · 2021-07-13
The slice is simply unsynchronized, so a user of the slice may pull out one array but a length that was for a different array.
https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
scottlamb · 2020-05-24
>> 70% of security defects in memory-safe languages are probably also memory safety problems.
> That doesn't make any sense at all
I'm sure it's not true—70% is way too high—but the real number isn't 0% as you might expect.
In particular, (most? all?) non-Rust languages that claim or appear to be memory-safe can have data races. In Go for example, those can be exploitable. [1]
And Rust is memory-safe...in safe code, with a bug-free compiler. Real programs have some unsafe code in their transitive dependencies and are compiled with the real, buggy compiler. [2] The percentage of security bugs in Rust code that are due to memory safety problems is more than 0%.
[1] https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
[2] https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%…
bouncycastle · 2019-11-02
The race condition exploits you're thinking of are not trivial and need specific code to pull off, unlikely to be a mistake like in C/C++. You just don't find them in normal Go programs.
Source (scroll down to the conclusion section):
https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
millstone · 2018-03-25
Go is not memory safe (though is certainly safer than C++). Various Go constructs like interfaces and slices are implemented via non-atomic multiword structs, and data races may result in invalid values leading to memory corruption, etc. See https://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safe…
Animats · 2016-12-25
Search for "go language slice race condition": [1]
[1] http://blog.stalkr.net/2015/04/golang-data-races-to-break-memory-safet…
taylorhughes · 2016-01-22
pam_exec seems to be a more robust solution to login notifications than /etc/profile http://blog.stalkr.net/2010/11/login-notifications-pamexec-scripting.h…
lawl · 2014-04-07
What? Sorry, that doesn't make the least amount of sense.
If you have a VM your code is DATA! You can have say format string bugs in managed languages too, see for example: http://blog.stalkr.net/2013/06/golang-heap-corruption-during-garbage.h…
I'm sorry, but you're agrument here is plain bullshit.
Using your logic the whole kernel/browsers etc should be written in a managed language.
A browser is basically a VM for webpages though. I'd bet that chrome/firefox/IE have more severe vulnerabilities than openssl per time though.
I just... You can't argue with bullshit sorry.
Your might get less buffer overruns okay, but is it more secure in the end without any doubt?
I doubt it.
ameliaquining · 2025-07-24
https://blog.stalkr.net/2022/01/universal-go-exploit-using-data-races.…
This example hardcodes the payload, but (unless I've badly misunderstood how the exploit works) that's not necessary, it could instead be input from the network (and you wouldn't have to pass that input to any APIs that are marked unsafe). The payload is just hardcoded so that the example could be reproduced on the public Go Playground, which sandboxes the code it runs and so can't accept network input.
Note that what tptacek is asking for is more stringent than this; he wants a proof-of-concept exploitation of a memory safety vulnerability caused by the data-race loopholes in the Go memory model, in a real program that someone is running in production. I do think it's interesting that nobody has demonstrated that yet, but I'm not sure what it tells us about how sure we can be that those vulnerabilities don't exist.