10
10
*/
11
11
12
12
import javascript
13
-
14
- /**
15
- * Provides heuristics for identifying names related to sensitive information.
16
- *
17
- * INTERNAL: Do not use directly.
18
- */
19
- module HeuristicNames {
20
- /**
21
- * Gets a regular expression that identifies strings that may indicate the presence of secret
22
- * or trusted data.
23
- */
24
- string maybeSecret ( ) { result = "(?is).*((?<!is)secret|(?<!un|is)trusted).*" }
25
-
26
- /**
27
- * Gets a regular expression that identifies strings that may indicate the presence of
28
- * user names or other account information.
29
- */
30
- string maybeAccountInfo ( ) {
31
- result = "(?is).*acc(ou)?nt.*" or
32
- result = "(?is).*(puid|username|userid).*"
33
- }
34
-
35
- /**
36
- * Gets a regular expression that identifies strings that may indicate the presence of
37
- * a password or an authorization key.
38
- */
39
- string maybePassword ( ) {
40
- result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or
41
- result = "(?is).*(auth(entication|ori[sz]ation)?)key.*"
42
- }
43
-
44
- /**
45
- * Gets a regular expression that identifies strings that may indicate the presence of
46
- * a certificate.
47
- */
48
- string maybeCertificate ( ) { result = "(?is).*(cert)(?!.*(format|name)).*" }
49
-
50
- /**
51
- * Gets a regular expression that identifies strings that may indicate the presence
52
- * of sensitive data, with `classification` describing the kind of sensitive data involved.
53
- */
54
- string maybeSensitive ( SensitiveExpr:: Classification classification ) {
55
- result = maybeSecret ( ) and classification = SensitiveExpr:: secret ( )
56
- or
57
- result = maybeAccountInfo ( ) and classification = SensitiveExpr:: id ( )
58
- or
59
- result = maybePassword ( ) and classification = SensitiveExpr:: password ( )
60
- or
61
- result = maybeCertificate ( ) and classification = SensitiveExpr:: certificate ( )
62
- }
63
-
64
- /**
65
- * Gets a regular expression that identifies strings that may indicate the presence of data
66
- * that is hashed or encrypted, and hence rendered non-sensitive, or contains special characters
67
- * suggesting nouns within the string do not represent the meaning of the whole string (e.g. a URL or a SQL query).
68
- */
69
- string notSensitive ( ) {
70
- result = "(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|((?<!un)(en))?(crypt|code)).*"
71
- }
72
- }
73
-
13
+ import semmle.javascript.security.internal.SensitiveDataHeuristics
74
14
private import HeuristicNames
75
15
76
16
/** An expression that might contain sensitive data. */
@@ -79,56 +19,44 @@ abstract class SensitiveExpr extends Expr {
79
19
abstract string describe ( ) ;
80
20
81
21
/** Gets a classification of the kind of sensitive data this expression might contain. */
82
- abstract SensitiveExpr :: Classification getClassification ( ) ;
22
+ abstract SensitiveDataClassification getClassification ( ) ;
83
23
}
84
24
85
- module SensitiveExpr {
86
- /**
87
- * A classification of different kinds of sensitive data:
88
- *
89
- * - secret: generic secret or trusted data;
90
- * - id: a user name or other account information;
91
- * - password: a password or authorization key;
92
- * - certificate: a certificate.
93
- *
94
- * While classifications are represented as strings, this should not be relied upon.
95
- * Instead, use the predicates below to work with classifications.
96
- */
97
- class Classification extends string {
98
- Classification ( ) { this = "secret" or this = "id" or this = "password" or this = "certificate" }
99
- }
25
+ /** DEPRECATED: Use `SensitiveDataClassification` and helpers instead. */
26
+ deprecated module SensitiveExpr {
27
+ /** DEPRECATED: Use `SensitiveDataClassification` instead. */
28
+ deprecated class Classification = SensitiveDataClassification ;
100
29
101
- /** Gets the classification for secret or trusted data . */
102
- Classification secret ( ) { result = " secret" }
30
+ /** DEPRECATED: Use `SensitiveDataClassification:: secret` instead . */
31
+ deprecated predicate secret = SensitiveDataClassification :: secret / 0 ;
103
32
104
- /** Gets the classification for user names or other account information . */
105
- Classification id ( ) { result = "id" }
33
+ /** DEPRECATED: Use `SensitiveDataClassification::id` instead . */
34
+ deprecated predicate id = SensitiveDataClassification :: id / 0 ;
106
35
107
- /** Gets the classification for passwords or authorization keys . */
108
- Classification password ( ) { result = " password" }
36
+ /** DEPRECATED: Use `SensitiveDataClassification::password` instead . */
37
+ deprecated predicate password = SensitiveDataClassification :: password / 0 ;
109
38
110
- /** Gets the classification for certificates . */
111
- Classification certificate ( ) { result = " certificate" }
39
+ /** DEPRECATED: Use `SensitiveDataClassification::certificate` instead . */
40
+ deprecated predicate certificate = SensitiveDataClassification :: certificate / 0 ;
112
41
}
113
42
114
43
/** A function call that might produce sensitive data. */
115
44
class SensitiveCall extends SensitiveExpr , InvokeExpr {
116
- SensitiveExpr :: Classification classification ;
45
+ SensitiveDataClassification classification ;
117
46
118
47
SensitiveCall ( ) {
119
48
classification = this .getCalleeName ( ) .( SensitiveDataFunctionName ) .getClassification ( )
120
49
or
121
50
// This is particularly to pick up methods with an argument like "password", which
122
51
// may indicate a lookup.
123
52
exists ( string s | this .getAnArgument ( ) .mayHaveStringValue ( s ) |
124
- s .regexpMatch ( maybeSensitive ( classification ) ) and
125
- not s .regexpMatch ( notSensitive ( ) )
53
+ nameIndicatesSensitiveData ( s , classification )
126
54
)
127
55
}
128
56
129
57
override string describe ( ) { result = "a call to " + getCalleeName ( ) }
130
58
131
- override SensitiveExpr :: Classification getClassification ( ) { result = classification }
59
+ override SensitiveDataClassification getClassification ( ) { result = classification }
132
60
}
133
61
134
62
/** An access to a variable or property that might contain sensitive data. */
@@ -152,13 +80,10 @@ abstract class SensitiveWrite extends DataFlow::Node { }
152
80
153
81
/** A write to a variable or property that might contain sensitive data. */
154
82
private class BasicSensitiveWrite extends SensitiveWrite {
155
- SensitiveExpr :: Classification classification ;
83
+ SensitiveDataClassification classification ;
156
84
157
85
BasicSensitiveWrite ( ) {
158
- exists ( string name |
159
- name .regexpMatch ( maybeSensitive ( classification ) ) and
160
- not name .regexpMatch ( notSensitive ( ) )
161
- |
86
+ exists ( string name | nameIndicatesSensitiveData ( name , classification ) |
162
87
exists ( DataFlow:: PropWrite pwn |
163
88
pwn .getPropertyName ( ) = name and
164
89
pwn .getRhs ( ) = this
@@ -173,18 +98,16 @@ private class BasicSensitiveWrite extends SensitiveWrite {
173
98
}
174
99
175
100
/** Gets a classification of the kind of sensitive data the write might handle. */
176
- SensitiveExpr :: Classification getClassification ( ) { result = classification }
101
+ SensitiveDataClassification getClassification ( ) { result = classification }
177
102
}
178
103
179
104
/** An access to a variable or property that might contain sensitive data. */
180
105
private class BasicSensitiveVariableAccess extends SensitiveVariableAccess {
181
- SensitiveExpr :: Classification classification ;
106
+ SensitiveDataClassification classification ;
182
107
183
- BasicSensitiveVariableAccess ( ) {
184
- name .regexpMatch ( maybeSensitive ( classification ) ) and not name .regexpMatch ( notSensitive ( ) )
185
- }
108
+ BasicSensitiveVariableAccess ( ) { nameIndicatesSensitiveData ( name , classification ) }
186
109
187
- override SensitiveExpr :: Classification getClassification ( ) { result = classification }
110
+ override SensitiveDataClassification getClassification ( ) { result = classification }
188
111
}
189
112
190
113
/** A function name that suggests it may be sensitive. */
@@ -199,16 +122,16 @@ abstract class SensitiveFunctionName extends string {
199
122
/** A function name that suggests it may produce sensitive data. */
200
123
abstract class SensitiveDataFunctionName extends SensitiveFunctionName {
201
124
/** Gets a classification of the kind of sensitive data this function may produce. */
202
- abstract SensitiveExpr :: Classification getClassification ( ) ;
125
+ abstract SensitiveDataClassification getClassification ( ) ;
203
126
}
204
127
205
128
/** A method that might return sensitive data, based on the name. */
206
129
class CredentialsFunctionName extends SensitiveDataFunctionName {
207
- SensitiveExpr :: Classification classification ;
130
+ SensitiveDataClassification classification ;
208
131
209
- CredentialsFunctionName ( ) { this . regexpMatch ( maybeSensitive ( classification ) ) }
132
+ CredentialsFunctionName ( ) { nameIndicatesSensitiveData ( this , classification ) }
210
133
211
- override SensitiveExpr :: Classification getClassification ( ) { result = classification }
134
+ override SensitiveDataClassification getClassification ( ) { result = classification }
212
135
}
213
136
214
137
/**
@@ -240,11 +163,13 @@ class ProtectCall extends DataFlow::CallNode {
240
163
241
164
/** An expression that might contain a clear-text password. */
242
165
class CleartextPasswordExpr extends SensitiveExpr {
243
- CleartextPasswordExpr ( ) { this .( SensitiveExpr ) .getClassification ( ) = SensitiveExpr:: password ( ) }
166
+ CleartextPasswordExpr ( ) {
167
+ this .( SensitiveExpr ) .getClassification ( ) = SensitiveDataClassification:: password ( )
168
+ }
244
169
245
170
override string describe ( ) { none ( ) }
246
171
247
- override SensitiveExpr :: Classification getClassification ( ) { none ( ) }
172
+ override SensitiveDataClassification getClassification ( ) { none ( ) }
248
173
}
249
174
250
175
/**
0 commit comments