@@ -14,25 +14,78 @@ module InsecureFeatureFlag {
1414 name .regexpMatch ( "(?i).*(secure|selfCert|selfSign|validat|verif|trust|(en|dis)able).*" )
1515 }
1616
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 ) {
1972 // a call like `cfg.disableVerification()`
20- exists ( DataFlow:: CallNode c | isFeatureFlagName ( c .getTarget ( ) .getName ( ) ) |
73+ exists ( DataFlow:: CallNode c | c .getTarget ( ) .getName ( ) = flagKind . getAFlagName ( ) |
2174 result = globalValueNumber ( c )
2275 )
2376 or
2477 // a variable or field like `insecure`
25- exists ( ValueEntity flag | isFeatureFlagName ( flag .getName ( ) ) |
78+ exists ( ValueEntity flag | flag .getName ( ) = flagKind . getAFlagName ( ) |
2679 result = globalValueNumber ( flag .getARead ( ) )
2780 )
2881 or
2982 // 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 ( ) |
3184 result = globalValueNumber ( const )
3285 )
3386 or
3487 // track feature flags through various operations
35- exists ( DataFlow:: Node flag | flag = getAFeatureFlag ( ) .getANode ( ) |
88+ exists ( DataFlow:: Node flag | flag = getAFlag ( flagKind ) .getANode ( ) |
3689 // tuple destructurings
3790 result = globalValueNumber ( DataFlow:: extractTupleElement ( flag , _) )
3891 or
@@ -66,6 +119,13 @@ module InsecureFeatureFlag {
66119 * Gets a control-flow node that represents a (likely) feature-flag check for certificate checking.
67120 */
68121 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 ( ) , _)
70130 }
71131}
0 commit comments