Proposal Details
Recently, there have been more and more news like https://socket.dev/blog/11-malicious-go-packages-distribute-obfuscated-remote-payloads or https://alexandear.github.io/posts/2025-02-28-malicious-go-programs/ etc I propose to implement at the api level the ability to monitor and modify a variety of system calls. Following the example of how it's already done in python https://docs.python.org/3/library/audit_events.html But it's done very poorly there, and it would be useful to implement a full-fledged hook subsystem like
audit.Handle(os.RemoveAll, func(path string) error {
fmt.Println("Path remove request for:", path)
switch path {
case "/bin":
return nil // deny
case "/tmp/old":
return os.Rename(path, "/tmp/new") // replace call
case "/home":
path = "/tmp/trash" // replace argument
}
return os.RemoveAll(path)
})
or
audit.Handle(http.Get, func(url string) (resp *http.Response, err error) {
fmt.Println("Http get request for:", url)
switch url {
case "some.malware.host":
return nil, nil
default:
url = "http://127.0.0.1:8080"
}
return http.Get(url)
})
All this can be done anyway if start inject handler code directly in the golang source code, but why spoil it if you can add a separate powerful subsystem.
Comment From: seankhliao
I believe this is generally considered out of scope. See also #50632
Comment From: mwriter
I believe
And what right do you have to put your faith above technical discussions? You put your personal preferences above the interests of the community.
See also #50632
There's a completely different question there
Comment From: zigo101
It looks seankhliao thinks he is the new Go leader. :D
Comment From: dominikh
There's a completely different question there
They address the same need and both suffer the same limitation, see https://github.com/golang/go/issues/50632#issuecomment-1013783694.
It is not the process's job to audit itself.
Comment From: mwriter
It is not the process's job to audit itself.
The process doesn't do anything by itself, the hooks are created by the programmer to monitor events. If the hooks are not added manually, then there will be no additional impact on performance. This is a completely different approach compared to the one proposed there by writing rules in go.mod by analogy with AndroidManifest.xml. By the way, Android has a similar system of hooks at runtime for a long time. Even if it's an outside party. And the idea itself fits perfectly conceptually, whether it's in a language or an operating system.
Comment From: mwriter
And most importantly, anyone can implement this subsystem by injecting their own handlers to the golang source codes. This is the main argument in favor of the easy possibility of implementing such a subsystem. It was much more difficult to implement this in python. But even there it was done. Albeit very clumsily.
Comment From: zigo101
@seankhliao
Did you hide @mwriter's comment: https://github.com/golang/go/issues/75059#issuecomment-3194478315? It is hard to say that comment is off-topic. It contains relevant explanation.
Please be polite to Go community members.
Comment From: ianlancetaylor
The proposed facility would not be sufficient to prevent malicious packages from doing nefarious things. Go provides too many mechanisms for programs to invoke system calls, such as assembler code and C code. With Go, preventing in-process behavior can only be reliably done out of process, such as by sandboxing. It can't be done in-process.
A more feasible approach for handling malicious packages (other than sandboxing) might be analyzers that verified that imported packages only used certain facilities. Those analyzers could explicitly call out assembler and C code which would have to be examined manually.
Comment From: mwriter
The proposed facility would not be sufficient to prevent malicious packages from doing nefarious things.
But it's not just about security. In python auditing doesn't cover security issues at all either. It's mainly about the possibility of general monitoring, logging and tracing. First of all, it's about what dynamic execution analysis tools golang provides. There are still a lot of advantages from such an implementation. Moreover, it's not difficult to add the simplest implementation, unlike python.
Comment From: mwriter
Those analyzers could explicitly call out assembler and C code which would have to be examined manually.
By the way, the question is in this regard. After all, during golang runtime, is there any way to detect that C or assembler codes are being called? If there are variants, then can inject hooks on generally switch to such calls and interrupt their execution according to the proposed scenario. Then in this case, even the most complete security is possible, unlike python. Because standard APIs will be processed in separate hooks, and the transition to doing anything non-standard can simply be blocked in general hook. And as a result, we will get a semblance of a virtual machine at the golang runtime level :) Or, when compiled, do all the codes turn into a single binary assembler code that cannot be separated by the original type?
Comment From: mwriter
@cugu
The only exceptions here would be the use of C and assembler code which can be detected as well.
Here, you wrote that once. Can you tell in more detail how easy it is to do this in golang? Maybe you'll be interested in this discussion as a whole. Because if it's possible to implement checks at the level of individual hooks, then it will be possible to extend to the most complex scenarios at the level of the entire module management, which you suggested.
Comment From: ianlancetaylor
But it's not just about security.
Well, OK, but the examples in the original proposal seem to all be about security.
For that matter it occurs to me that implementing this feature would tend to make Go programs less secure against malicious packages, because any package that could call audit.Handle
could radically change the behavior of the program.
is there any way to detect that C or assembler codes are being called?
In the current implementation: C: yes, in general, barring some complex tricks that a package could engage in. Assembler: no.