Jigsawyers, I've been trying to get some mechanisms we (at Google) use in our Bezel build system to help security specialists guide developers towards more secure code-patterns and limit the amount of an application that has to be reviewed to confidently say that a particular security property holds.
I've written a static dependency scanner that works well enough (though is unsound in the face of java.lang.reflect and custom classloaders), and I'm trying to figure out how the same could be done on top of jigsaw but am having trouble understanding how the pieces fit together. Could I bother people to comment on the following. 1. jdeps provides access to the static module dependency graph, so a build system could be augmented to provide an artifact that could be later used to check constraints of the form "The module graph does not contain any edges from a module not on a white-list to a sensitive module com.example.unsafe" and provide error messages crafted by the authors/maintainers of those module. 2. jdeps provides no access to dynamic configurations but could be used to get a reasonably tight bound on the set of modules that can dynamically load other modules. Are there ways for part of a program to observe module loading to maintain constraints of there form? 3. If one has an instance of a concrete class in hand then one can reflect over its methods or fields regardless of the module in which it was defined >From a particular module, one can only load classes by name that are available via transitive dependencies of that module. 4. Reflection can still be used to violate constraints like the above that are based on directly reachable edges, but static reachability analysis and module graph analysis can still probably give reasonably tight bounds on the modules that might do so. 5. Embedded scripting languages have access to the transitive dependencies of the module that defines their interpreter unless compiled to bytecode and loaded into a module. Thanks in advance, mike If you're interested, here's the use case that I'm trying to satisfy. Sorry for the wall of text. A project architect integrates the work of a large development group. The group includes a large number of application developers, and smaller teams of specialists. Sally, a security specialist, produces a carefully crafted API that is hard to misuse. Behind this there are a number of package-private classes that need to be carefully used correctly. She gets this closely reviewed by skeptical eyes and tests it thoroughly. Sally then realizes that large chunks of her work are generally useful, and the approach is itself extensible. She thinks about splitting it into 3 packages 1. org.example which contains the safe APIs, 2. org.example.unsafe which exports the previously package-private APIs that need to be used carefully 3. com.example which contains code specific to her employer which is not open-sourced. Sally now needs to control access to the second package. She works with the tech lead to (details of previously mentioned unsound static dependency scanner elided). Sally gets requests to approve some third party libraries that build on org.example.unsafe and reviews them. Aaron, an app developer with a deadline, stumbles across org.example.unsafe. Instead of reading the documentation he uses Eclipse auto-complete to feel his way to something that seems right. His code compiles but the module does not validate, so Aaron looks at his dashboard, sees an error message written by Sally that suggests a safe API and points to a help forum. Aaron doesn't quite understand so he sends a terse email asking for help, and continues his work disabling validation locally. Sally responds to Aaron's question. When Aaron sends off a pull request, the validation failure is flagged in the review tool. His reviewer asks him to fix it. Aaron remembers seeing a response in his mail, fixes the issue, and submits a pull request that validates. Pat the build master puts together a release candidate. The application validates and everyone lives happily ever after.