@@ -14,25 +14,78 @@ module InsecureFeatureFlag {
14
14
name .regexpMatch ( "(?i).*(secure|selfCert|selfSign|validat|verif|trust|(en|dis)able).*" )
15
15
}
16
16
17
- /** Gets a global value number representing a (likely) feature flag for certificate checking. */
18
- GVN getAFeatureFlag ( ) {
17
+ /**
18
+ * Holds if `name` suggests an old or legacy version.
19
+ *
20
+ * We accept 'intermediate' because it appears to be common for TLS users
21
+ * to define three profiles: modern, intermediate, legacy/old, perhaps based
22
+ * on https://wiki.mozilla.org/Security/Server_Side_TLS (though note the
23
+ * 'intermediate' used there would now pass muster according to this query)
24
+ */
25
+ bindingset [ name]
26
+ predicate isLegacyFlagName ( string name ) { name .regexpMatch ( "(?i).*(old|intermediate|legacy).*" ) }
27
+
28
+ /**
29
+ * A kind of flag that may indicate security expectations regarding the code it guards.
30
+ */
31
+ abstract class FlagKind extends string {
32
+ FlagKind ( ) { this = "feature" or this = "legacy" }
33
+
34
+ /**
35
+ * Returns a flag name of this type.
36
+ */
37
+ abstract string getAFlagName ( ) ;
38
+ }
39
+
40
+ /**
41
+ * Flags suggesting an optional feature, perhaps deliberately insecure.
42
+ */
43
+ class FeatureFlag extends FlagKind {
44
+ FeatureFlag ( ) { this = "feature" }
45
+
46
+ bindingset [ result ]
47
+ override string getAFlagName ( ) { isFeatureFlagName ( result ) }
48
+ }
49
+
50
+ /**
51
+ * Flags suggesting an optional feature, perhaps deliberately insecure.
52
+ */
53
+ string featureFlag ( ) { result = "feature" }
54
+
55
+ /**
56
+ * Flags suggesting support for an old or legacy feature.
57
+ */
58
+ class LegacyFlag extends FlagKind {
59
+ LegacyFlag ( ) { this = "legacy" }
60
+
61
+ bindingset [ result ]
62
+ override string getAFlagName ( ) { isLegacyFlagName ( result ) }
63
+ }
64
+
65
+ /**
66
+ * Flags suggesting support for an old or legacy feature.
67
+ */
68
+ string legacyFlag ( ) { result = "legacy" }
69
+
70
+ /** Gets a global value number representing a (likely) security flag. */
71
+ GVN getAFlag ( FlagKind flagKind ) {
19
72
// a call like `cfg.disableVerification()`
20
- exists ( DataFlow:: CallNode c | isFeatureFlagName ( c .getTarget ( ) .getName ( ) ) |
73
+ exists ( DataFlow:: CallNode c | c .getTarget ( ) .getName ( ) = flagKind . getAFlagName ( ) |
21
74
result = globalValueNumber ( c )
22
75
)
23
76
or
24
77
// a variable or field like `insecure`
25
- exists ( ValueEntity flag | isFeatureFlagName ( flag .getName ( ) ) |
78
+ exists ( ValueEntity flag | flag .getName ( ) = flagKind . getAFlagName ( ) |
26
79
result = globalValueNumber ( flag .getARead ( ) )
27
80
)
28
81
or
29
82
// a string constant such as `"insecure"` or `"skipVerification"`
30
- exists ( DataFlow:: Node const | isFeatureFlagName ( const .getStringValue ( ) ) |
83
+ exists ( DataFlow:: Node const | const .getStringValue ( ) = flagKind . getAFlagName ( ) |
31
84
result = globalValueNumber ( const )
32
85
)
33
86
or
34
87
// track feature flags through various operations
35
- exists ( DataFlow:: Node flag | flag = getAFeatureFlag ( ) .getANode ( ) |
88
+ exists ( DataFlow:: Node flag | flag = getAFlag ( flagKind ) .getANode ( ) |
36
89
// tuple destructurings
37
90
result = globalValueNumber ( DataFlow:: extractTupleElement ( flag , _) )
38
91
or
@@ -66,6 +119,13 @@ module InsecureFeatureFlag {
66
119
* Gets a control-flow node that represents a (likely) feature-flag check for certificate checking.
67
120
*/
68
121
ControlFlow:: ConditionGuardNode getAFeatureFlagCheck ( ) {
69
- result .ensures ( getAFeatureFlag ( ) .getANode ( ) , _)
122
+ result .ensures ( getAFlag ( featureFlag ( ) ) .getANode ( ) , _)
123
+ }
124
+
125
+ /**
126
+ * Gets a control-flow node that represents a (likely) feature-flag check for certificate checking.
127
+ */
128
+ ControlFlow:: ConditionGuardNode getALegacyVersionCheck ( ) {
129
+ result .ensures ( getAFlag ( legacyFlag ( ) ) .getANode ( ) , _)
70
130
}
71
131
}
0 commit comments