Introduction | Codemodder (original) (raw)
/** Turns {@link java.util.Random} into {@link java.security.SecureRandom}. */
@Codemod(
id = "pixee:java/secure-random",
reviewGuidance = ReviewGuidance.MERGE_WITHOUT_REVIEW)
public final class SecureRandomCodemod extends SarifPluginJavaParserChanger<ObjectCreationExpr> {
private static final String DETECTION_RULE =
"""
rules:
- id: secure-random
pattern: new Random()
""";
@Inject
public SecureRandomCodemod(@SemgrepScan(yaml = DETECTION_RULE) RuleSarif sarif) {
super(sarif, ObjectCreationExpr.class);
}
@Override
public boolean onResultFound(
final CodemodInvocationContext context,
final CompilationUnit cu,
final ObjectCreationExpr objectCreationExpr,
final Result result) {
objectCreationExpr.setType("SecureRandom");
addImportIfMissing(cu, SecureRandom.class.getName());
return true;
}
}
This codemod, which would be easy to implement even without the need for a fancy static analysis tool, uses Semgrep to find all the constructor calls for java.util.Random
. These are the locations we want to change to SecureRandom
instead.
The codemodder framework then hands off all those locations Semgrep found to the onResultfound()
method, where the code just has to change the type and add the missing import. It takes care of a lot of annoying work -- the execution of static analysis tools, the parsing of its results, aligning the results to the code that handles them, the formatting of the resulting code, etc. All you specify is how to find the code to change and what change do you want to make. We handle the rest.
For more real-world examples, check out our core Java codemods, which are codemods maintained by the framework and made for general use. We also provide utilities for building and testing these codemods to make the whole process seamless.