@@ -30,39 +30,50 @@ module InsecureRandomness {
3030 override InvokeExpr astNode ;
3131
3232 DefaultSource ( ) {
33- exists ( DataFlow:: ModuleImportNode mod , string name | mod .getPath ( ) = name |
34- // require("random-number")();
35- name = "random-number" and
36- this = mod .getACall ( )
33+ not this .getContainer ( ) = getASecureRandomGeneratingFunction ( ) and
34+ (
35+ exists ( DataFlow:: ModuleImportNode mod , string name | mod .getPath ( ) = name |
36+ // require("random-number")();
37+ name = "random-number" and
38+ this = mod .getACall ( )
39+ or
40+ // require("random-int")();
41+ name = "random-int" and
42+ this = mod .getACall ( )
43+ or
44+ // require("random-float")();
45+ name = "random-float" and
46+ this = mod .getACall ( )
47+ or
48+ // require('random-seed').create()();
49+ name = "random-seed" and
50+ this = mod .getAMemberCall ( "create" ) .getACall ( )
51+ or
52+ // require('unique-random')()();
53+ name = "unique-random" and
54+ this = mod .getACall ( ) .getACall ( )
55+ )
3756 or
38- // require("random-int")();
39- name = "random-int" and
40- this = mod .getACall ( )
57+ // Math.random()
58+ this = DataFlow:: globalVarRef ( "Math" ) .getAMemberCall ( "random" )
4159 or
42- // require("random-float")();
43- name = "random-float" and
44- this = mod .getACall ( )
60+ // (new require('chance')).<name>()
61+ this = DataFlow:: moduleImport ( "chance" ) .getAnInstantiation ( ) .getAMemberInvocation ( _)
4562 or
46- // require('random-seed').create()();
47- name = "random-seed" and
48- this = mod .getAMemberCall ( "create" ) .getACall ( )
49- or
50- // require('unique-random')()();
51- name = "unique-random" and
52- this = mod .getACall ( ) .getACall ( )
63+ // require('crypto').pseudoRandomBytes()
64+ this = DataFlow:: moduleMember ( "crypto" , "pseudoRandomBytes" ) .getAnInvocation ( )
5365 )
54- or
55- // Math.random()
56- this = DataFlow:: globalVarRef ( "Math" ) .getAMemberCall ( "random" )
57- or
58- // (new require('chance')).<name>()
59- this = DataFlow:: moduleImport ( "chance" ) .getAnInstantiation ( ) .getAMemberInvocation ( _)
60- or
61- // require('crypto').pseudoRandomBytes()
62- this = DataFlow:: moduleMember ( "crypto" , "pseudoRandomBytes" ) .getAnInvocation ( )
6366 }
6467 }
6568
69+ /**
70+ * Gets a container that at some point generates a secure random value.
71+ */
72+ pragma [ noinline]
73+ private StmtContainer getASecureRandomGeneratingFunction ( ) {
74+ result = randomBufferSource ( ) .getContainer ( )
75+ }
76+
6677 /**
6778 * A sensitive write, considered as a sink for random values that are not cryptographically
6879 * secure.
@@ -94,4 +105,24 @@ module InsecureRandomness {
94105 succ = mc
95106 )
96107 }
108+
109+ /**
110+ * Gets a Buffer/TypedArray containing cryptographically secure random numbers.
111+ */
112+ DataFlow:: SourceNode randomBufferSource ( ) {
113+ result = DataFlow:: moduleMember ( "crypto" , [ "randomBytes" , "randomFillSync" ] ) .getACall ( )
114+ or
115+ exists ( DataFlow:: CallNode call |
116+ call = DataFlow:: moduleMember ( "crypto" , [ "randomFill" , "randomFillSync" ] ) and
117+ result = call .getArgument ( 0 ) .getALocalSource ( )
118+ )
119+ or
120+ result = DataFlow:: globalVarRef ( "crypto" ) .getAMethodCall ( "getRandomValues" )
121+ or
122+ result = DataFlow:: moduleImport ( "secure-random" ) .getACall ( )
123+ or
124+ result =
125+ DataFlow:: moduleImport ( "secure-random" )
126+ .getAMethodCall ( [ "randomArray" , "randomUint8Array" , "randomBuffer" ] )
127+ }
97128}
0 commit comments