Skip to content

Commit aa78050

Browse files
Implement checks for elements hidden by their xml attributes
1 parent 6081f18 commit aa78050

File tree

5 files changed

+82
-9
lines changed

5 files changed

+82
-9
lines changed

java/ql/lib/semmle/code/java/frameworks/android/Layout.qll

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,10 @@ class AndroidLayoutXmlFile extends XmlFile {
1111

1212
/** A component declared in an Android layout file. */
1313
class AndroidLayoutXmlElement extends XmlElement {
14-
AndroidXmlAttribute id;
14+
AndroidLayoutXmlElement() { this.getFile() instanceof AndroidLayoutXmlFile }
1515

16-
AndroidLayoutXmlElement() {
17-
this.getFile() instanceof AndroidLayoutXmlFile and
18-
id = this.getAttribute("id")
19-
}
20-
21-
/** Gets the ID of this component. */
22-
string getId() { result = id.getValue() }
16+
/** Gets the ID of this component, if any. */
17+
string getId() { result = this.getAttribute("id").getValue() }
2318

2419
/** Gets the class of this component. */
2520
Class getClass() {

java/ql/lib/semmle/code/java/security/SensitiveUiQuery.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ private module TextFieldTrackingConfig implements DataFlow::ConfigSig {
7373
/** Holds if the given may be masked. */
7474
private predicate viewIsMasked(AndroidLayoutXmlElement view) {
7575
DataFlow::localExprFlow(getAUseOfViewWithId(view.getId()), any(MaskCall mcall).getQualifier())
76+
or
77+
view.getAttribute("inputType")
78+
.(AndroidXmlAttribute)
79+
.getValue()
80+
.regexpMatch("(?i).*(text|number)(web)?password.*")
81+
or
82+
view.getAttribute("visibility").(AndroidXmlAttribute).getValue().toLowerCase() =
83+
["invisible", "gone"]
7684
}
7785

7886
/** Holds if the qualifier of `call` is also called with a method that may mask the information displayed. */

java/ql/test/query-tests/security/CWE-200/semmle/tests/SensitiveTextView/R.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ public static final class id {
77
public static final int test3 = 3;
88
public static final int test4 = 4;
99
public static final int test5 = 5;
10+
public static final int test6 = 6;
11+
public static final int test7 = 7;
12+
public static final int test8 = 8;
13+
public static final int test9 = 9;
14+
public static final int test10 = 10;
15+
public static final int test11 = 11;
16+
public static final int test12 = 12;
1017
}
1118

1219
public static final class string {

java/ql/test/query-tests/security/CWE-200/semmle/tests/SensitiveTextView/Test.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,55 @@
1010
class Test extends Activity {
1111
void test(String password) {
1212
EditText test1 = findViewById(R.id.test1);
13+
// BAD: Exposing sensitive data to text view
1314
test1.setText(password); // $sensitive-text
1415
test1.setHint(password); // $sensitive-text
1516
test1.append(password); // $sensitive-text
16-
test1.setText(R.string.password_prompt);
17+
// GOOD: resource constant is not sensitive info
18+
test1.setText(R.string.password_prompt);
1719

20+
// GOOD: Visibility is dynamically set
1821
TextView test2 = findViewById(R.id.test2);
1922
test2.setVisibility(View.INVISIBLE);
2023
test2.setText(password);
2124

25+
// GOOD: Input type is dynamically set
2226
EditText test3 = findViewById(R.id.test3);
2327
test3.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
2428
test3.setText(password);
2529

30+
// GOOD: Visibility of parent is dynamically set
2631
LinearLayout test4 = findViewById(R.id.test4);
2732
TextView test5 = findViewById(R.id.test5);
2833
test4.setVisibility(View.INVISIBLE);
2934
test5.setText(password);
35+
36+
// GOOD: Input type set to textPassword in XML
37+
EditText test6 = findViewById(R.id.test6);
38+
test6.setText(password);
39+
40+
// GOOD: Input type set to textWebPassword in XML
41+
EditText test7 = findViewById(R.id.test7);
42+
test7.setText(password);
43+
44+
// GOOD: Input type set to numberPassword in XML
45+
EditText test8 = findViewById(R.id.test8);
46+
test8.setText(password);
47+
48+
// BAD: Input type set to textVisiblePassword in XML, which is not hidden
49+
EditText test9 = findViewById(R.id.test9);
50+
test9.setText(password); // $sensitive-text
51+
52+
// GOOD: Visibility set to invisible in XML
53+
EditText test10 = findViewById(R.id.test10);
54+
test10.setText(password);
55+
56+
// GOOD: Visibility set to gone in XML
57+
EditText test11 = findViewById(R.id.test11);
58+
test11.setText(password);
59+
60+
// GOOD: Visibility of parent set to invisible in XML
61+
EditText test12 = findViewById(R.id.test12);
62+
test12.setText(password);
3063
}
3164
}

java/ql/test/query-tests/security/CWE-200/semmle/tests/SensitiveTextView/res/layout/Test.xml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,34 @@
2020
android:id="@+id/test5"/>
2121
</LinearLayout>
2222

23+
<EditText
24+
android:id="@+id/test6"
25+
android:inputType="textPassword"/>
26+
27+
<EditText
28+
android:id="@+id/test7"
29+
android:inputType="textWebPassword"/>
30+
31+
<EditText
32+
android:id="@+id/test8"
33+
android:inputType="numberPassword"/>
34+
35+
<EditText
36+
android:id="@+id/test9"
37+
android:inputType="textVisiblePassword"/>
38+
39+
<EditText
40+
android:id="@+id/test10"
41+
android:visibility="invisible"/>
42+
43+
<EditText
44+
android:id="@+id/test11"
45+
android:visibility="gone"/>
46+
47+
<LinearLayout
48+
android:visibility="invisible">
49+
<TextView
50+
android:id="@+id/test12"/>
51+
</LinearLayout>
52+
2353
</LinearLayout>

0 commit comments

Comments
 (0)