mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #18645 from fabienpe/main
Added missing "GOOD" and "BAD" to some examples
This commit is contained in:
@@ -4,6 +4,7 @@ public class SQLInjection extends HttpServlet {
|
||||
|
||||
StringBuilder sqlQueryBuilder = new StringBuilder();
|
||||
sqlQueryBuilder.append("SELECT * FROM user WHERE user_id='");
|
||||
// BAD: a request parameter is concatenated directly into a SQL query
|
||||
sqlQueryBuilder.append(request.getParameter("user_id"));
|
||||
sqlQueryBuilder.append("'");
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
public class PartialPathTraversalBad {
|
||||
public void example(File dir, File parent) throws IOException {
|
||||
// BAD: dir.getCanonicalPath() not slash-terminated
|
||||
if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath())) {
|
||||
throw new IOException("Path traversal attempt: " + dir.getCanonicalPath());
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import java.io.File;
|
||||
|
||||
public class PartialPathTraversalGood {
|
||||
public void example(File dir, File parent) throws IOException {
|
||||
// GOOD: Check if dir.Path() is normalised
|
||||
if (!dir.toPath().normalize().startsWith(parent.toPath())) {
|
||||
throw new IOException("Path traversal attempt: " + dir.getCanonicalPath());
|
||||
}
|
||||
|
||||
@@ -20,4 +20,5 @@ webview.addJavaScriptInterface(new ExposedObject(), "exposedObject");
|
||||
webview.loadData("", "text/html", null);
|
||||
|
||||
String name = "Robert'; DROP TABLE students; --";
|
||||
// BAD: Untrusted input loaded into WebView
|
||||
webview.loadUrl("javascript:alert(exposedObject.studentEmail(\""+ name +"\"))");
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
WebSettings settings = webview.getSettings();
|
||||
settings.setJavaScriptEnabled(false);
|
||||
settings.setJavaScriptEnabled(false); // GOOD: webview has JavaScript disabled
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
WebSettings settings = webview.getSettings();
|
||||
settings.setJavaScriptEnabled(true);
|
||||
settings.setJavaScriptEnabled(true); // BAD: webview has JavaScript enabled
|
||||
|
||||
@@ -2,26 +2,26 @@ public class GroovyInjection {
|
||||
void injectionViaClassLoader(HttpServletRequest request) {
|
||||
String script = request.getParameter("script");
|
||||
final GroovyClassLoader classLoader = new GroovyClassLoader();
|
||||
Class groovy = classLoader.parseClass(script);
|
||||
Class groovy = classLoader.parseClass(script); // BAD: Groovy code injection
|
||||
GroovyObject groovyObj = (GroovyObject) groovy.newInstance();
|
||||
}
|
||||
|
||||
void injectionViaEval(HttpServletRequest request) {
|
||||
String script = request.getParameter("script");
|
||||
Eval.me(script);
|
||||
Eval.me(script); // BAD: Groovy code injection
|
||||
}
|
||||
|
||||
void injectionViaGroovyShell(HttpServletRequest request) {
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
shell.evaluate(script);
|
||||
shell.evaluate(script); // BAD: Groovy code injection
|
||||
}
|
||||
|
||||
void injectionViaGroovyShellGroovyCodeSource(HttpServletRequest request) {
|
||||
GroovyShell shell = new GroovyShell();
|
||||
String script = request.getParameter("script");
|
||||
GroovyCodeSource gcs = new GroovyCodeSource(script, "test", "Test");
|
||||
shell.evaluate(gcs);
|
||||
shell.evaluate(gcs); // BAD: Groovy code injection
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.io.File;
|
||||
File file = new File(Environment.getExternalStorageDirectory(), "myapp.apk");
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
/* Set the mimetype to APK */
|
||||
// BAD: The file may be altered by another app
|
||||
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
|
||||
|
||||
startActivity(intent);
|
||||
|
||||
@@ -21,6 +21,7 @@ try (InputStream is = getAssets().open(assetName);
|
||||
|
||||
/* Expose temporary file with FileProvider */
|
||||
File toInstall = new File(this.getFilesDir(), tempFilename);
|
||||
// GOOD: The file is protected by FileProvider
|
||||
Uri applicationUri = FileProvider.getUriForFile(this, "com.example.apkprovider", toInstall);
|
||||
|
||||
/* Create Intent and set data to APK file. */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// GOOD: Package installed using PackageInstaller
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInstaller;
|
||||
|
||||
@@ -14,6 +14,7 @@ public class VelocitySSTI {
|
||||
|
||||
StringWriter w = new StringWriter();
|
||||
// evaluate( Context context, Writer out, String logTag, String instring )
|
||||
// BAD: code is controlled by the user
|
||||
Velocity.evaluate(context, w, "mystring", code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class VelocitySSTI {
|
||||
|
||||
String s = "We are using $project $name to render this.";
|
||||
StringWriter w = new StringWriter();
|
||||
Velocity.evaluate(context, w, "mystring", s);
|
||||
Velocity.evaluate(context, w, "mystring", s); // GOOD: s is a constant string
|
||||
System.out.println(" string : " + w);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ public void evaluate(Socket socket) throws IOException {
|
||||
|
||||
JexlSandbox onlyMath = new JexlSandbox(false);
|
||||
onlyMath.white("java.lang.Math");
|
||||
JexlEngine jexl = new JexlBuilder().sandbox(onlyMath).create();
|
||||
JexlEngine jexl = new JexlBuilder().sandbox(onlyMath).create(); // GOOD: using a sandbox
|
||||
|
||||
String input = reader.readLine();
|
||||
JexlExpression expression = jexl.createExpression(input);
|
||||
|
||||
@@ -6,7 +6,7 @@ public void evaluate(Socket socket) throws IOException {
|
||||
JexlEngine jexl = new JexlBuilder().uberspect(sandbox).create();
|
||||
|
||||
String input = reader.readLine();
|
||||
JexlExpression expression = jexl.createExpression(input);
|
||||
JexlExpression expression = jexl.createExpression(input); // GOOD: jexl uses a sandbox
|
||||
JexlContext context = new MapContext();
|
||||
expression.evaluate(context);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@ public Object evaluate(Socket socket) throws IOException {
|
||||
|
||||
String string = reader.readLine();
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
// AVOID: string is controlled by the user
|
||||
Expression expression = parser.parseExpression(string);
|
||||
SimpleEvaluationContext context
|
||||
= SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
// OK: Untrusted expressions are evaluated in a restricted context
|
||||
return expression.getValue(context);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ public void evaluate(Socket socket) throws IOException {
|
||||
|
||||
String input = reader.readLine();
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
// BAD: input is controlled by the user
|
||||
JexlExpression expression = jexl.createExpression(input);
|
||||
JexlContext context = new MapContext();
|
||||
expression.evaluate(context);
|
||||
|
||||
@@ -4,6 +4,7 @@ public Object evaluate(Socket socket) throws IOException {
|
||||
|
||||
String string = reader.readLine();
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
// BAD: string is controlled by the user
|
||||
Expression expression = parser.parseExpression(string);
|
||||
return expression.getValue();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
byte[] iv = new byte[16]; // all zeroes
|
||||
byte[] iv = new byte[16]; // BAD: all zeroes
|
||||
GCMParameterSpec params = new GCMParameterSpec(128, iv);
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, params);
|
||||
@@ -1,6 +1,6 @@
|
||||
byte[] iv = new byte[16];
|
||||
SecureRandom random = SecureRandom.getInstanceStrong();
|
||||
random.nextBytes(iv);
|
||||
random.nextBytes(iv); // GOOD: random initialization vector
|
||||
GCMParameterSpec params = new GCMParameterSpec(128, iv);
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, params);
|
||||
@@ -1,2 +1,2 @@
|
||||
TextView pwView = getViewById(R.id.pw_text);
|
||||
pwView.setText("Your password is: " + password);
|
||||
pwView.setText("Your password is: " + password); // BAD: password is shown immediately
|
||||
@@ -5,6 +5,6 @@ pwView.setText("Your password is: " + password);
|
||||
Button showButton = findViewById(R.id.show_pw_button);
|
||||
showButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
pwView.setVisibility(View.VISIBLE);
|
||||
pwView.setVisibility(View.VISIBLE); // GOOD: password is only shown when the user clicks the button
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
WebSettings settings = webview.getSettings();
|
||||
|
||||
// GOOD: WebView is configured to disallow content access
|
||||
settings.setAllowContentAccess(false);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
WebSettings settings = webview.getSettings();
|
||||
|
||||
// BAD: WebView is configured to allow content access
|
||||
settings.setAllowContentAccess(true);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
WebSettings settings = view.getSettings();
|
||||
|
||||
// GOOD: WebView is configured to disallow file access
|
||||
settings.setAllowFileAccess(false);
|
||||
settings.setAllowFileAccessFromURLs(false);
|
||||
settings.setAllowUniversalAccessFromURLs(false);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
WebSettings settings = view.getSettings();
|
||||
|
||||
// BAD: WebView is configured to allow file access
|
||||
settings.setAllowFileAccess(true);
|
||||
settings.setAllowFileAccessFromURLs(true);
|
||||
settings.setAllowUniversalAccessFromURLs(true);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Random r = new Random();
|
||||
Random r = new Random(); // BAD: Random is not cryptographically secure
|
||||
|
||||
byte[] bytes = new byte[16];
|
||||
r.nextBytes(bytes);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SecureRandom r = new SecureRandom();
|
||||
SecureRandom r = new SecureRandom(); // GOOD: SecureRandom is cryptographically secure
|
||||
|
||||
byte[] bytes = new byte[16];
|
||||
r.nextBytes(bytes);
|
||||
|
||||
@@ -12,14 +12,14 @@ class Resource {
|
||||
|
||||
public synchronized void bad(Resource r) {
|
||||
if (r.isReady()) {
|
||||
// r might no longer be ready, another thread might
|
||||
// BAD: r might no longer be ready, another thread might
|
||||
// have called setReady(false)
|
||||
r.act();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void good(Resource r) {
|
||||
synchronized(r) {
|
||||
synchronized(r) { // GOOD: r is locked
|
||||
if (r.isReady()) {
|
||||
r.act();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@ public MyObject {
|
||||
|
||||
public MyObject deserialize(Socket sock) {
|
||||
try(ObjectInputStream in = new ObjectInputStream(sock.getInputStream())) {
|
||||
return (MyObject)in.readObject(); // unsafe
|
||||
return (MyObject)in.readObject(); // BAD: in is from untrusted source
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
public MyObject deserialize(Socket sock) {
|
||||
try(DataInputStream in = new DataInputStream(sock.getInputStream())) {
|
||||
return new MyObject(in.readInt());
|
||||
return new MyObject(in.readInt()); // GOOD: read only an int
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// BAD: LDAP authentication is used
|
||||
String ldapUrl = "ldap://ad.your-server.com:389";
|
||||
Hashtable<String, String> environment = new Hashtable<String, String>();
|
||||
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// GOOD: LDAP connection using LDAPS
|
||||
String ldapUrl = "ldaps://ad.your-server.com:636";
|
||||
Hashtable<String, String> environment = new Hashtable<String, String>();
|
||||
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// GOOD: LDAP is used but SASL authentication is enabled
|
||||
String ldapUrl = "ldap://ad.your-server.com:389";
|
||||
Hashtable<String, String> environment = new Hashtable<String, String>();
|
||||
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
public void parse(Socket sock) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
builder.parse(sock.getInputStream()); //unsafe
|
||||
builder.parse(sock.getInputStream()); // BAD: DTD parsing is enabled
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ public void disableDTDParse(Socket sock) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
builder.parse(sock.getInputStream()); //safe
|
||||
builder.parse(sock.getInputStream()); // GOOD: DTD parsing is disabled
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import com.amazonaws.auth.BasicAWSCredentials;
|
||||
|
||||
public class HardcodedAWSCredentials {
|
||||
public static void main(String[] args) {
|
||||
//Hardcoded credentials for connecting to AWS services
|
||||
// BAD: Hardcoded credentials for connecting to AWS services
|
||||
//To fix the problem, use other approaches including AWS credentials file, environment variables, or instance/container credentials instead
|
||||
AWSCredentials creds = new BasicAWSCredentials("ACCESS_KEY", "SECRET_KEY"); //sensitive call
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
private static final String p = "123456"; // hard-coded credential
|
||||
private static final String p = "123456"; // BAD: hard-coded credential
|
||||
|
||||
public static void main(String[] args) throws SQLException {
|
||||
String url = "jdbc:mysql://localhost/test";
|
||||
String u = "admin"; // hard-coded credential
|
||||
String u = "admin"; // BAD: hard-coded credential
|
||||
|
||||
getConn(url, u, p);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
for (int i=0; i<10; i++) {
|
||||
for (int j=0; i<10; j++) {
|
||||
for (int j=0; i<10; j++) { // BAD: Potential infinite loop: i should be j
|
||||
// do stuff
|
||||
if (shouldBreak()) break;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
for (int i=0; i<10; i++) {
|
||||
for (int j=0; j<10; j++) {
|
||||
for (int j=0; j<10; j++) { // GOOD: correct variable j
|
||||
// do stuff
|
||||
if (shouldBreak()) break;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
public class ShutdownReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
// BAD: The code does not check if the intent is an ACTION_SHUTDOWN intent
|
||||
mainActivity.saveLocalData();
|
||||
mainActivity.stopActivity();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
public class ShutdownReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
// GOOD: The code checks if the intent is an ACTION_SHUTDOWN intent
|
||||
if (!intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user