Skip to content

Commit ef7eafa

Browse files
authored
Merge pull request #2644 from RasmusWL/python-add-deprecated-keyword
Python: Add deprecated keyword to deprecated functions
2 parents 8a0089a + 7d9f1f0 commit ef7eafa

File tree

30 files changed

+119
-144
lines changed

30 files changed

+119
-144
lines changed
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
/**
22
* @name Use of a broken or weak cryptographic algorithm
33
* @description Using broken or weak cryptographic algorithms can compromise security.
4-
* @kind problem
4+
* @kind path-problem
55
* @problem.severity warning
66
* @precision high
77
* @id py/weak-cryptographic-algorithm
88
* @tags security
99
* external/cwe/cwe-327
1010
*/
11+
1112
import python
13+
import semmle.python.security.Paths
1214
import semmle.python.security.SensitiveData
1315
import semmle.python.security.Crypto
1416

1517
class BrokenCryptoConfiguration extends TaintTracking::Configuration {
16-
1718
BrokenCryptoConfiguration() { this = "Broken crypto configuration" }
1819

19-
override predicate isSource(TaintTracking::Source source) { source instanceof SensitiveDataSource }
20-
21-
override predicate isSink(TaintTracking::Sink sink) {
22-
sink instanceof WeakCryptoSink
20+
override predicate isSource(TaintTracking::Source source) {
21+
source instanceof SensitiveDataSource
2322
}
2423

24+
override predicate isSink(TaintTracking::Sink sink) { sink instanceof WeakCryptoSink }
2525
}
2626

27-
28-
from BrokenCryptoConfiguration config, SensitiveDataSource src, WeakCryptoSink sink
29-
where config.hasFlow(src, sink)
30-
31-
select sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", src , src.toString()
27+
from BrokenCryptoConfiguration config, TaintedPathSource src, TaintedPathSink sink
28+
where config.hasFlowPath(src, sink)
29+
select sink.getSink(), src, sink, "$@ is used in a broken or weak cryptographic algorithm.",
30+
src.getSource(), "Sensitive data"
Lines changed: 33 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @name Hard-coded credentials
33
* @description Credentials are hard coded in the source code of the application.
4-
* @kind problem
4+
* @kind path-problem
55
* @problem.severity error
66
* @precision medium
77
* @id py/hardcoded-credentials
@@ -12,22 +12,20 @@
1212
*/
1313

1414
import python
15+
import semmle.python.security.Paths
1516
import semmle.python.security.TaintTracking
1617
import semmle.python.filters.Tests
1718

1819
class HardcodedValue extends TaintKind {
19-
20-
HardcodedValue() {
21-
this = "hard coded value"
22-
}
23-
20+
HardcodedValue() { this = "hard coded value" }
2421
}
2522

2623
bindingset[char, fraction]
2724
predicate fewer_characters_than(StrConst str, string char, float fraction) {
2825
exists(string text, int chars |
2926
text = str.getText() and
30-
chars = count(int i | text.charAt(i) = char) |
27+
chars = count(int i | text.charAt(i) = char)
28+
|
3129
/* Allow one character */
3230
chars = 1 or
3331
chars < text.length() * fraction
@@ -46,118 +44,88 @@ predicate possible_reflective_name(string name) {
4644
exists(Object::builtin(name))
4745
}
4846

49-
int char_count(StrConst str) {
50-
result = count(string c | c = str.getText().charAt(_))
51-
}
47+
int char_count(StrConst str) { result = count(string c | c = str.getText().charAt(_)) }
5248

53-
predicate capitalized_word(StrConst str) {
54-
str.getText().regexpMatch("[A-Z][a-z]+")
55-
}
49+
predicate capitalized_word(StrConst str) { str.getText().regexpMatch("[A-Z][a-z]+") }
5650

57-
predicate format_string(StrConst str) {
58-
str.getText().matches("%{%}%")
59-
}
51+
predicate format_string(StrConst str) { str.getText().matches("%{%}%") }
6052

6153
predicate maybeCredential(ControlFlowNode f) {
6254
/* A string that is not too short and unlikely to be text or an identifier. */
63-
exists(StrConst str |
64-
str = f.getNode() |
55+
exists(StrConst str | str = f.getNode() |
6556
/* At least 10 characters */
6657
str.getText().length() > 9 and
6758
/* Not too much whitespace */
6859
fewer_characters_than(str, " ", 0.05) and
6960
/* or underscores */
7061
fewer_characters_than(str, "_", 0.2) and
7162
/* Not too repetitive */
72-
exists(int chars |
73-
chars = char_count(str) |
63+
exists(int chars | chars = char_count(str) |
7464
chars > 15 or
75-
chars*3 > str.getText().length()*2
65+
chars * 3 > str.getText().length() * 2
7666
) and
7767
not possible_reflective_name(str.getText()) and
7868
not capitalized_word(str) and
7969
not format_string(str)
8070
)
8171
or
8272
/* Or, an integer with over 32 bits */
83-
exists(IntegerLiteral lit |
84-
f.getNode() = lit
85-
|
73+
exists(IntegerLiteral lit | f.getNode() = lit |
8674
not exists(lit.getValue()) and
8775
/* Not a set of flags or round number */
8876
not lit.getN().matches("%00%")
8977
)
9078
}
9179

9280
class HardcodedValueSource extends TaintSource {
81+
HardcodedValueSource() { maybeCredential(this) }
9382

94-
HardcodedValueSource() {
95-
maybeCredential(this)
96-
}
97-
98-
override predicate isSourceOf(TaintKind kind) {
99-
kind instanceof HardcodedValue
100-
}
101-
83+
override predicate isSourceOf(TaintKind kind) { kind instanceof HardcodedValue }
10284
}
10385

10486
class CredentialSink extends TaintSink {
105-
10687
CredentialSink() {
10788
exists(string name |
10889
name.regexpMatch(getACredentialRegex()) and
109-
not name.suffix(name.length()-4) = "file"
110-
|
90+
not name.suffix(name.length() - 4) = "file"
91+
|
11192
any(FunctionObject func).getNamedArgumentForCall(_, name) = this
11293
or
113-
exists(Keyword k |
114-
k.getArg() = name and k.getValue().getAFlowNode() = this
115-
)
94+
exists(Keyword k | k.getArg() = name and k.getValue().getAFlowNode() = this)
11695
or
117-
exists(CompareNode cmp, NameNode n |
118-
n.getId() = name
119-
|
96+
exists(CompareNode cmp, NameNode n | n.getId() = name |
12097
cmp.operands(this, any(Eq eq), n)
12198
or
12299
cmp.operands(n, any(Eq eq), this)
123100
)
124101
)
125102
}
126103

127-
128-
override predicate sinks(TaintKind kind) {
129-
kind instanceof HardcodedValue
130-
}
131-
104+
override predicate sinks(TaintKind kind) { kind instanceof HardcodedValue }
132105
}
133106

134107
/**
135-
* Gets a regular expression for matching names of locations (variables, parameters, keys) that
136-
* indicate the value being held is a credential.
137-
*/
108+
* Gets a regular expression for matching names of locations (variables, parameters, keys) that
109+
* indicate the value being held is a credential.
110+
*/
138111
private string getACredentialRegex() {
139-
result = "(?i).*pass(wd|word|code|phrase)(?!.*question).*" or
140-
result = "(?i).*(puid|username|userid).*" or
141-
result = "(?i).*(cert)(?!.*(format|name)).*"
112+
result = "(?i).*pass(wd|word|code|phrase)(?!.*question).*" or
113+
result = "(?i).*(puid|username|userid).*" or
114+
result = "(?i).*(cert)(?!.*(format|name)).*"
142115
}
143116

144117
class HardcodedCredentialsConfiguration extends TaintTracking::Configuration {
145-
146118
HardcodedCredentialsConfiguration() { this = "Hardcoded coredentials configuration" }
147119

148-
override predicate isSource(TaintTracking::Source source) { source instanceof HardcodedValueSource }
149-
150-
override predicate isSink(TaintTracking::Sink sink) {
151-
sink instanceof CredentialSink
120+
override predicate isSource(TaintTracking::Source source) {
121+
source instanceof HardcodedValueSource
152122
}
153123

124+
override predicate isSink(TaintTracking::Sink sink) { sink instanceof CredentialSink }
154125
}
155126

156-
157-
158-
from HardcodedCredentialsConfiguration config, TaintSource src, TaintSink sink
159-
160-
where config.hasFlow(src, sink) and
161-
not any(TestScope test).contains(src.(ControlFlowNode).getNode())
162-
163-
select sink, "Use of hardcoded credentials from $@.", src, src.toString()
127+
from HardcodedCredentialsConfiguration config, TaintedPathSource src, TaintedPathSink sink
128+
where
129+
config.hasFlowPath(src, sink) and
130+
not any(TestScope test).contains(src.getAstNode())
131+
select sink.getSink(), src, sink, "Use of $@.", src.getSource(), "hardcoded credentials"

python/ql/src/Statements/ModificationOfLocals.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Object aFunctionLocalsObject() {
2525

2626

2727
predicate modification_of_locals(ControlFlowNode f) {
28-
f.(SubscriptNode).getValue().refersTo(aFunctionLocalsObject()) and (f.isStore() or f.isDelete())
28+
f.(SubscriptNode).getObject().refersTo(aFunctionLocalsObject()) and (f.isStore() or f.isDelete())
2929
or
3030
exists(string mname, AttrNode attr |
3131
attr = f.(CallNode).getFunction() and

python/ql/src/Statements/RedundantAssignment.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ predicate same_attribute(Attribute a1, Attribute a2) {
6565

6666
int pyflakes_commented_line(File file) {
6767
exists(Comment c | c.getText().toLowerCase().matches("%pyflakes%") |
68-
c.getLocation().hasLocationInfo(file.getName(), result, _, _, _)
68+
c.getLocation().hasLocationInfo(file.getAbsolutePath(), result, _, _, _)
6969
)
7070
}
7171

python/ql/src/Variables/UndefinedExport.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ predicate mutates_globals(ModuleValue m) {
3030
|
3131
exists(AttrNode attr | attr.getObject() = globals)
3232
or
33-
exists(SubscriptNode sub | sub.getValue() = globals and sub.isStore())
33+
exists(SubscriptNode sub | sub.getObject() = globals and sub.isStore())
3434
)
3535
or
3636
exists(Value enum_convert, ClassValue enum_class |

python/ql/src/analysis/Sanity.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ predicate file_sanity(string clsname, string problem, string what) {
206206
exists(File file, Folder folder |
207207
clsname = file.getAQlClass() and
208208
problem = "has same name as a folder" and
209-
what = file.getName() and
210-
what = folder.getName()
209+
what = file.getAbsolutePath() and
210+
what = folder.getAbsolutePath()
211211
) or
212212
exists(Container f |
213213
clsname = f.getAQlClass() and

python/ql/src/external/DuplicateBlock.ql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ predicate sorted_by_location(DuplicateBlock x, DuplicateBlock y) {
2121
if x.sourceFile() = y.sourceFile() then
2222
x.sourceStartLine() < y.sourceStartLine()
2323
else
24-
x.sourceFile().getName() < y.sourceFile().getName()
24+
x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath()
2525
}
2626

2727
from DuplicateBlock d, DuplicateBlock other
2828
where d.sourceLines() > 10 and
2929
other.getEquivalenceClass() = d.getEquivalenceClass() and
3030
sorted_by_location(other, d)
31-
select
32-
d,
31+
select
32+
d,
3333
"Duplicate code: " + d.sourceLines() + " lines are duplicated at " +
3434
other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString()

python/ql/src/semmle/python/Files.qll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ class File extends Container {
99
}
1010

1111
/** DEPRECATED: Use `getAbsolutePath` instead. */
12-
override string getName() {
13-
files(this, result, _, _, _)
12+
deprecated override string getName() {
13+
result = this.getAbsolutePath()
1414
}
1515

1616
/** DEPRECATED: Use `getAbsolutePath` instead. */
17-
string getFullName() {
18-
result = getName()
17+
deprecated string getFullName() {
18+
result = this.getAbsolutePath()
1919
}
2020

2121
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
22-
this.getName() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0
22+
this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0
2323
}
2424

2525
/** Whether this file is a source code file. */
@@ -97,17 +97,17 @@ class Folder extends Container {
9797
}
9898

9999
/** DEPRECATED: Use `getAbsolutePath` instead. */
100-
override string getName() {
101-
folders(this, result, _)
100+
deprecated override string getName() {
101+
result = this.getAbsolutePath()
102102
}
103103

104104
/** DEPRECATED: Use `getBaseName` instead. */
105-
string getSimple() {
105+
deprecated string getSimple() {
106106
folders(this, _, result)
107107
}
108108

109109
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
110-
this.getName() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0
110+
this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0
111111
}
112112

113113
override string getAbsolutePath() {
@@ -427,11 +427,11 @@ class Location extends @location {
427427
}
428428

429429
string toString() {
430-
result = this.getPath().getName() + ":" + this.getStartLine().toString()
430+
result = this.getPath().getAbsolutePath() + ":" + this.getStartLine().toString()
431431
}
432432

433433
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
434-
exists(File f | f.getName() = filepath |
434+
exists(File f | f.getAbsolutePath() = filepath |
435435
locations_default(this, f, bl, bc, el, ec)
436436
or
437437
exists(Module m | m.getFile() = f |
@@ -445,7 +445,7 @@ class Location extends @location {
445445
class Line extends @py_line {
446446

447447
predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) {
448-
exists(Module m | m.getFile().getName() = filepath and
448+
exists(Module m | m.getFile().getAbsolutePath() = filepath and
449449
el = bl and bc = 1 and
450450
py_line_lengths(this, m, bl, ec))
451451
}

python/ql/src/semmle/python/Flow.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ class SubscriptNode extends ControlFlowNode {
606606

607607
/** DEPRECATED: Use `getObject()` instead.
608608
* This will be formally deprecated before the end 2018 and removed in 2019.*/
609-
ControlFlowNode getValue() {
609+
deprecated ControlFlowNode getValue() {
610610
exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and
611611
result.getBasicBlock().dominates(this.getBasicBlock()))
612612
}

python/ql/src/semmle/python/dataflow/Configuration.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ module TaintTracking {
123123
/* Old query API */
124124

125125
/* deprecated */
126-
predicate hasFlow(Source src, Sink sink) {
126+
deprecated predicate hasFlow(Source src, Sink sink) {
127127
exists(PathSource psrc, PathSink psink |
128128
this.hasFlowPath(psrc, psink) and
129129
src = psrc.getNode().asCfgNode() and

0 commit comments

Comments
 (0)