@@ -274,6 +274,34 @@ private module NodeJSCrypto {
274
274
* A model of the crypto-js library.
275
275
*/
276
276
private module CryptoJS {
277
+ private class InstantiatedAlgorithm extends DataFlow:: CallNode {
278
+ CryptographicAlgorithm algorithm ; // non-functional
279
+
280
+ InstantiatedAlgorithm ( ) {
281
+ /*
282
+ * ```
283
+ * const crypto = require("crypto-js");
284
+ * const cipher = crypto.algo.SHA256.create();
285
+ * ```
286
+ * matched as:
287
+ * ```
288
+ * const crypto = require("crypto-js");
289
+ * const cipher = crypto.algo.<algorithmName>.create();
290
+ * ```
291
+ */
292
+
293
+ exists ( DataFlow:: SourceNode mod , DataFlow:: PropRead propRead |
294
+ mod = DataFlow:: moduleImport ( "crypto-js" ) and
295
+ propRead = mod .getAPropertyRead ( "algo" ) .getAPropertyRead ( ) and
296
+ this = propRead .getAMemberCall ( "create" ) and
297
+ not isStrongPasswordHashingAlgorithm ( propRead .getPropertyName ( ) )
298
+ )
299
+ }
300
+
301
+ CryptographicAlgorithm getAlgorithm ( ) { result = algorithm }
302
+ }
303
+
304
+
277
305
/**
278
306
* Matches `CryptoJS.<algorithmName>` and `require("crypto-js/<algorithmName>")`
279
307
*/
@@ -325,13 +353,39 @@ private module CryptoJS {
325
353
input = result .getParameter ( 0 )
326
354
}
327
355
356
+ private DataFlow:: CallNode getUpdatedApplication ( DataFlow:: Node input , InstantiatedAlgorithm instantiation ) {
357
+ /*
358
+ * ```
359
+ * var CryptoJS = require("crypto-js");
360
+ * var hash = CryptoJS.algo.SHA256.create();
361
+ * hash.update('message');
362
+ * hash.update('password');
363
+ * var hashInHex = hash.finalize();
364
+ * ```
365
+ * Matched as:
366
+ * ```
367
+ * var CryptoJS = require("crypto-js");
368
+ * var hash = CryptoJS.algo.<algorithmName>.create();
369
+ * hash.update(<input>);
370
+ * hash.update(<input>);
371
+ * var hashInHex = hash.finalize();
372
+ * ```
373
+ * Also matches where `CryptoJS.algo.<algorithmName>` has been
374
+ * replaced by `require("crypto-js/<algorithmName>")`
375
+ */
376
+
377
+ result = instantiation .getAMemberCall ( "update" ) and
378
+ input = result .getArgument ( 0 )
379
+ }
380
+
328
381
private class Apply extends CryptographicOperation:: Range instanceof API:: CallNode {
329
382
API:: Node input ;
330
383
CryptographicAlgorithm algorithm ; // non-functional
331
384
332
385
Apply ( ) {
333
386
this = getEncryptionApplication ( input , algorithm ) or
334
- this = getDirectApplication ( input , algorithm )
387
+ this = getDirectApplication ( input , algorithm ) or
388
+ this = getUpdatedApplication ( input , instantiation )
335
389
}
336
390
337
391
override DataFlow:: Node getAnInput ( ) { result = input .asSink ( ) }
0 commit comments