@@ -30,7 +30,11 @@ private DataFlow::Node getAValueExportedByPackage() {
30
30
getAnExportFromModule ( any ( PackageJSON pack | exists ( pack .getPackageName ( ) ) ) .getMainModule ( ) )
31
31
or
32
32
// module.exports.bar.baz = result;
33
- result = getAValueExportedByPackage ( ) .( DataFlow:: PropWrite ) .getRhs ( )
33
+ exists ( DataFlow:: PropWrite write |
34
+ write = getAValueExportedByPackage ( ) and
35
+ write .getPropertyName ( ) = publicPropertyName ( ) and
36
+ result = write .getRhs ( )
37
+ )
34
38
or
35
39
// class Foo {
36
40
// bar() {} // <- result
@@ -39,15 +43,17 @@ private DataFlow::Node getAValueExportedByPackage() {
39
43
exists ( DataFlow:: SourceNode callee |
40
44
callee = getAValueExportedByPackage ( ) .( DataFlow:: NewNode ) .getCalleeNode ( ) .getALocalSource ( )
41
45
|
42
- result = callee .getAPropertyRead ( "prototype" ) .getAPropertyWrite ( ) .getRhs ( )
46
+ result = callee .getAPropertyRead ( "prototype" ) .getAPropertyWrite ( publicPropertyName ( ) ) .getRhs ( )
43
47
or
44
- result = callee .( DataFlow:: ClassNode ) .getAnInstanceMethod ( )
48
+ result = callee .( DataFlow:: ClassNode ) .getInstanceMethod ( publicPropertyName ( ) ) and
49
+ not isPrivateMethodDeclaration ( result )
45
50
)
46
51
or
47
52
result = getAValueExportedByPackage ( ) .getALocalSource ( )
48
53
or
49
54
// Nested property reads.
50
- result = getAValueExportedByPackage ( ) .( DataFlow:: SourceNode ) .getAPropertyReference ( )
55
+ result =
56
+ getAValueExportedByPackage ( ) .( DataFlow:: SourceNode ) .getAPropertyReference ( publicPropertyName ( ) )
51
57
or
52
58
// module.exports.foo = require("./other-module.js");
53
59
exists ( Module mod |
@@ -61,9 +67,12 @@ private DataFlow::Node getAValueExportedByPackage() {
61
67
// static baz() {} // <- result
62
68
// constructor() {} // <- result
63
69
// };
64
- exists ( DataFlow:: ClassNode cla | cla = getAValueExportedByPackage ( ) |
65
- result = cla .getAnInstanceMethod ( ) or
66
- result = cla .getAStaticMethod ( ) or
70
+ exists ( DataFlow:: ClassNode cla |
71
+ cla = getAValueExportedByPackage ( ) and
72
+ not isPrivateMethodDeclaration ( result )
73
+ |
74
+ result = cla .getInstanceMethod ( publicPropertyName ( ) ) or
75
+ result = cla .getStaticMethod ( publicPropertyName ( ) ) or
67
76
result = cla .getConstructor ( )
68
77
)
69
78
or
@@ -120,7 +129,8 @@ private DataFlow::Node getAValueExportedByPackage() {
120
129
or
121
130
// Object.defineProperty
122
131
exists ( CallToObjectDefineProperty call |
123
- [ call , call .getBaseObject ( ) ] = getAValueExportedByPackage ( )
132
+ [ call , call .getBaseObject ( ) ] = getAValueExportedByPackage ( ) and
133
+ call .getPropertyName ( ) = publicPropertyName ( )
124
134
|
125
135
result = call .getPropertyDescriptor ( ) .getALocalSource ( ) .getAPropertyReference ( "value" )
126
136
or
@@ -164,9 +174,31 @@ private DataFlow::Node getAValueExportedByPackage() {
164
174
* Gets an exported node from the module `mod`.
165
175
*/
166
176
private DataFlow:: Node getAnExportFromModule ( Module mod ) {
167
- result = mod .getAnExportedValue ( _ )
177
+ result = mod .getAnExportedValue ( publicPropertyName ( ) )
168
178
or
169
179
result = mod .getABulkExportedNode ( )
170
180
or
171
181
result .analyze ( ) .getAValue ( ) = TAbstractModuleObject ( mod )
172
182
}
183
+
184
+ /**
185
+ * Gets a property name that we consider to be public.
186
+ *
187
+ * This only allows properties whose first character is a letter or number.
188
+ */
189
+ bindingset [ result ]
190
+ private string publicPropertyName ( ) { result .regexpMatch ( "[a-zA-Z0-9].*" ) }
191
+
192
+ /**
193
+ * Holds if the given function is part of a private (or protected) method declaration.
194
+ */
195
+ private predicate isPrivateMethodDeclaration ( DataFlow:: FunctionNode func ) {
196
+ exists ( MethodDeclaration decl |
197
+ decl .getBody ( ) = func .getFunction ( ) and
198
+ (
199
+ decl .isPrivate ( )
200
+ or
201
+ decl .isProtected ( )
202
+ )
203
+ )
204
+ }
0 commit comments