Skip to content
Prev Previous commit
Next Next commit
Tighten up CompareExprSanitizer
- Document
- Only actually consider comparisons
- Don't sanitize literals
  • Loading branch information
smowton committed Jun 2, 2022
commit b48a07e7b82484d7df2d087d6f963bc743d3ccdd
13 changes: 9 additions & 4 deletions go/ql/src/experimental/CWE-321/HardcodedKeysLib.qll
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,18 @@ module HardcodedKeys {
}

/**
* Mark any comparision expression where any operand is tainted as a
* sanitizer for all instances of the taint
* Sanitizes any other use of an operand to a comparison, on the assumption that this may filter
* out special constant values -- for example, in context `if key != "invalid_key" { ... }`,
* if `"invalid_key"` is indeed the only dangerous key then guarded uses of `key` are likely
* to be safe.
*
* TODO: Before promoting this query look at replacing this with something more principled.
*/
private class CompareExprSanitizer extends Sanitizer {
CompareExprSanitizer() {
exists(BinaryExpr c |
c.getAnOperand().getGlobalValueNumber() = this.asExpr().getGlobalValueNumber()
exists(ComparisonExpr c |
c.getAnOperand().getGlobalValueNumber() = this.asExpr().getGlobalValueNumber() and
not this.asExpr() instanceof Literal
)
}
}
Comment on lines +160 to +171
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried removing this sanitizer, and it doesn't seem to be useful:

  • It handles a few cases where an empty string is returned alongside an error value, but this would be better handled by looking for the pattern of an empty string "" guarded by a test if x != nil, where x is of error type.
  • The other two cases were truly unreachable code: x := "hello"; if x != "hello" { ... }, which doesn't seem like a useful test (but perhaps you could change the test to better represent a real-world situation?)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smowton

It handles a few cases where an empty string is returned alongside an error value, but this would be better handled by looking for the pattern of an empty string "" guarded by a test if x != nil, where x is of error type.

This may not be ideal. There could be multiple instances where a error code may be returned without a test to nil, say for ex:

func t()(string, error){
    if config.hasKey(){
        key:= config.getKey()
        return key,nil
    } else {
    return getDefaultKey(), errors.New("no key")
}

To avoid this, I just check for cases where there the taint is compared with anything and mark that as sanitized. This handles the if x!=nil and if y !="" cases very well.

The other two cases were truly unreachable code: x := "hello"; if x != "hello" { ... }, which doesn't seem like a useful test (but perhaps you could change the test to better represent a real-world situation?)

I have added a better test case now. The test case for this sanitizer was earlier in main.go. I have moved that to sanitizer.go. Also, I have removed the test-case you mention.

Expand Down