@@ -3,71 +3,15 @@ import experimental.semmle.python.Concepts
33import semmle.python.dataflow.new.DataFlow
44import semmle.python.ApiGraphs
55import semmle.python.dataflow.new.TaintTracking
6+ import WebAppConstantSecretKeySource
67
78module DjangoConstantSecretKeyConfig {
89 /**
910 * Sources are Constants that without any Tainting reach the Sinks.
1011 * Also Sources can be the default value of getenv or similar methods
1112 * in a case that no value is assigned to Desired SECRET_KEY environment variable
1213 */
13- predicate isSource ( DataFlow:: Node source ) {
14- (
15- // because Env return an Exeption if there isan't any value (instead of none) we should check whether
16- // there is a default value of there is a config file which mostly these config files have a default value
17- exists ( API:: Node env | env = API:: moduleImport ( "environ" ) .getMember ( "Env" ) |
18- (
19- // has default value
20- exists ( env .getKeywordParameter ( "SECRET_KEY" ) .asSource ( ) )
21- or
22- // get value from a config file which is not best security practice
23- exists ( env .getReturn ( ) .getMember ( "read_env" ) )
24- ) and
25- source = env .getReturn ( ) .getReturn ( ) .asSource ( )
26- )
27- or
28- source .asExpr ( ) .isConstant ( )
29- or
30- exists ( API:: Node cn |
31- cn =
32- [
33- API:: moduleImport ( "configparser" )
34- .getMember ( [ "ConfigParser" , "RawConfigParser" ] )
35- .getReturn ( ) ,
36- // legacy API https://docs.python.org/3/library/configparser.html#legacy-api-examples
37- API:: moduleImport ( "configparser" )
38- .getMember ( [ "ConfigParser" , "RawConfigParser" ] )
39- .getReturn ( )
40- .getMember ( "get" )
41- .getReturn ( )
42- ] and
43- source = cn .asSource ( )
44- )
45- or
46- exists ( API:: CallNode cn |
47- cn =
48- [
49- API:: moduleImport ( "os" ) .getMember ( "getenv" ) .getACall ( ) ,
50- API:: moduleImport ( "os" ) .getMember ( "environ" ) .getMember ( "get" ) .getACall ( )
51- ] and
52- (
53- // this can be ideal if we assume that best security practice is that
54- // we don't get SECRET_KEY from env and we always assign a secure generated random string to it
55- cn .getNumArgument ( ) = 1
56- or
57- cn .getNumArgument ( ) = 2 and
58- DataFlow:: localFlow ( any ( DataFlow:: Node n | n .asExpr ( ) .isConstant ( ) ) , cn .getArg ( 1 ) )
59- ) and
60- source .asExpr ( ) = cn .asExpr ( )
61- )
62- or
63- source = API:: moduleImport ( "os" ) .getMember ( "environ" ) .getASubscript ( ) .asSource ( )
64- ) and
65- // followings will sanitize the get_random_secret_key of django.core.management.utils and similar random generators which we have their source code and some of them can be tracking by taint tracking because they are initilized by a constant!
66- exists ( source .getScope ( ) .getLocation ( ) .getFile ( ) .getRelativePath ( ) ) and
67- not source .getScope ( ) .getLocation ( ) .getFile ( ) .inStdlib ( ) and
68- // special sanitize case for get_random_secret_key and django-environ
69- not source .getScope ( ) .getLocation ( ) .getFile ( ) .getBaseName ( ) = [ "environ.py" , "crypto.py" ]
70- }
14+ predicate isSource ( DataFlow:: Node source ) { source instanceof WebAppConstantSecretKeySource }
7115
7216 /**
7317 * A sink like following SECRET_KEY Assignments
0 commit comments