One of the thing, that I think it missing here is the idea to run all crates in secure-sandboxed environment by default, with no network access and no file system access. This will make sure that all crates are do what supposed to do, for example: linter lib should be just read and write and cannot access any network.
This is a good idea. It combines something like the permission system of Android with the behavioural analysis done on malware in the latest AV solutions. Hereās an implementation plan, or proof-of-concept:
a) Create a system that allows for analyzing a crate based on 1) The dependencies that are included 2) the functions that it has permissions to perform.
b) separate the permission-list owner from the crate owner, perhaps using double review on approval for the permission-list only.
c)Add guidelines to API-guidelines to add a fuzzing test for the crate to the RustSec auditor repo (create a system for this) that calls all the functions and procedures, traits etc - such that all the code in that crate is forced to run when the fuzz test is called. This will naturally end up catching code bugs as well, because all security issues are in varying degrees code bugs. So, to kill two birds with one stone, the test should target the confirming the expected functionality of the crate.
d) As the fuzz test runs, the RustSec auditor checks to see if the permissions list of the crate is being honored - i.e no network access, or no access to crypto libraries, - but this must be a whitelist because a blacklist just doesnāt work so well. i.e allow permission for crates tagged x,y,z (that and only that). If the permission is violated with a call to somewhere else, then the audit fails and the permission list needs to be updated by the relevant owners, or the the functionality must be taken out and added to a crate that is more suitable for it.
e) The permission list becomes a description of the functionality of the crate, so the tags need to have the correct (to be discussed) level of granularity to not over or under specify the permissions or functionality, in other words not be a hinderance.
f) A crate that calls a dependency will not inherit the full scope of that dependencyās permissions. Instead one of several means can be used: using the crate needs to be accompanied by the permission tag that is being accessed by that crate. In other words, I have a crate with tags a,b,c, I use a crate with tags c,d,e, but I only intend to use functionality c and e. I place the tags c,e next to the import of the crate, and the auditor will see that the usage is enlarging the permission set of my crate to a,b,c,e. The permission list will get updated and the change approval requested on the Merge. When the auditor runs, and my crate now also runs syscalls to functionality d, the test fails and the issue is escalated to the owners to check what happened. Finer implementation details should be relegated to actual code implementation.
e) I am vague on the implementation details for the underlying functionality flagging for the analysis. @bascule, do you (or anyone else), know whether the syscalls that the code generates can be reasonably tagged (like calls to the windows cryptographic libraries are tagged āCryptoā). And, at which level is this best implemented? That is, for building the āsandboxā environment that will catch calls outside of the permissions. We can and perhaps should use work others have done : https://cuckoosandbox.org/ to help with this. I will contact an expert on behavioural malware analysis to weigh in on this as well. He has done it on several levels in the OS stack - but using compiled code. So we can have the auditor compile the fuzz test and run it on Cuckoo - that will definitely turn up malware behaviour with reasonable (perhaps 80%) probability, but Iām wondering if this can/should be implemented higher up in the compiler process.
Furthermore, much of this can already be coded into a proof-of-concept I think.