Skip to content

Commit 1a3ee45

Browse files
authoredJul 13, 2024
[flake8-bandit] Avoid S310 violations for HTTP-safe f-strings (#12305)
this resolves #12245
1 parent 6584886 commit 1a3ee45

File tree

3 files changed

+210
-99
lines changed

3 files changed

+210
-99
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,37 @@
11
import urllib.request
22

33
urllib.request.urlopen(url='http://www.google.com')
4+
urllib.request.urlopen(url=f'http://www.google.com')
45
urllib.request.urlopen(url='http://www.google.com', **kwargs)
6+
urllib.request.urlopen(url=f'http://www.google.com', **kwargs)
57
urllib.request.urlopen('http://www.google.com')
8+
urllib.request.urlopen(f'http://www.google.com')
69
urllib.request.urlopen('file:///foo/bar/baz')
710
urllib.request.urlopen(url)
811

9-
urllib.request.Request(url='http://www.google.com', **kwargs)
1012
urllib.request.Request(url='http://www.google.com')
13+
urllib.request.Request(url=f'http://www.google.com')
14+
urllib.request.Request(url='http://www.google.com', **kwargs)
15+
urllib.request.Request(url=f'http://www.google.com', **kwargs)
1116
urllib.request.Request('http://www.google.com')
17+
urllib.request.Request(f'http://www.google.com')
1218
urllib.request.Request('file:///foo/bar/baz')
1319
urllib.request.Request(url)
1420

15-
urllib.request.URLopener().open(fullurl='http://www.google.com', **kwargs)
1621
urllib.request.URLopener().open(fullurl='http://www.google.com')
22+
urllib.request.URLopener().open(fullurl=f'http://www.google.com')
23+
urllib.request.URLopener().open(fullurl='http://www.google.com', **kwargs)
24+
urllib.request.URLopener().open(fullurl=f'http://www.google.com', **kwargs)
1725
urllib.request.URLopener().open('http://www.google.com')
26+
urllib.request.URLopener().open(f'http://www.google.com')
1827
urllib.request.URLopener().open('file:///foo/bar/baz')
1928
urllib.request.URLopener().open(url)
2029

2130
urllib.request.urlopen(url=urllib.request.Request('http://www.google.com'))
31+
urllib.request.urlopen(url=urllib.request.Request(f'http://www.google.com'))
2232
urllib.request.urlopen(url=urllib.request.Request('http://www.google.com'), **kwargs)
33+
urllib.request.urlopen(url=urllib.request.Request(f'http://www.google.com'), **kwargs)
2334
urllib.request.urlopen(urllib.request.Request('http://www.google.com'))
35+
urllib.request.urlopen(urllib.request.Request(f'http://www.google.com'))
2436
urllib.request.urlopen(urllib.request.Request('file:///foo/bar/baz'))
2537
urllib.request.urlopen(urllib.request.Request(url))

‎crates/ruff_linter/src/rules/flake8_bandit/rules/suspicious_function_call.rs

+48-11
Original file line numberDiff line numberDiff line change
@@ -850,16 +850,28 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, call: &ExprCall) {
850850
// MarkSafe
851851
["django", "utils", "safestring" | "html", "mark_safe"] => Some(SuspiciousMarkSafeUsage.into()),
852852
// URLOpen (`Request`)
853-
["urllib", "request","Request"] |
853+
["urllib", "request", "Request"] |
854854
["six", "moves", "urllib", "request","Request"] => {
855-
// If the `url` argument is a string literal, allow `http` and `https` schemes.
855+
// If the `url` argument is a string literal or an f string, allow `http` and `https` schemes.
856856
if call.arguments.args.iter().all(|arg| !arg.is_starred_expr()) && call.arguments.keywords.iter().all(|keyword| keyword.arg.is_some()) {
857-
if let Some(Expr::StringLiteral(ast::ExprStringLiteral { value, .. })) = &call.arguments.find_argument("url", 0) {
857+
match call.arguments.find_argument("url", 0) {
858+
// If the `url` argument is a string literal, allow `http` and `https` schemes.
859+
Some(Expr::StringLiteral(ast::ExprStringLiteral { value, .. })) => {
858860
let url = value.to_str().trim_start();
859861
if url.starts_with("http://") || url.starts_with("https://") {
860862
return None;
861863
}
862-
864+
},
865+
// If the `url` argument is an f-string literal, allow `http` and `https` schemes.
866+
Some(Expr::FString(ast::ExprFString { value, .. })) => {
867+
if let Some(ast::FStringElement::Literal(ast::FStringLiteralElement { value, .. })) = value.elements().next() {
868+
let url = value.trim_start();
869+
if url.starts_with("http://") || url.starts_with("https://") {
870+
return None;
871+
}
872+
}
873+
},
874+
_ => {}
863875
}
864876
}
865877
Some(SuspiciousURLOpenUsage.into())
@@ -868,27 +880,52 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, call: &ExprCall) {
868880
["urllib", "request", "urlopen" | "urlretrieve" ] |
869881
["six", "moves", "urllib", "request", "urlopen" | "urlretrieve" ] => {
870882
if call.arguments.args.iter().all(|arg| !arg.is_starred_expr()) && call.arguments.keywords.iter().all(|keyword| keyword.arg.is_some()) {
871-
if let Some(arg) = &call.arguments.find_argument("url", 0) {
883+
match call.arguments.find_argument("url", 0) {
872884
// If the `url` argument is a string literal, allow `http` and `https` schemes.
873-
if let Expr::StringLiteral(ast::ExprStringLiteral { value, .. }) = arg {
885+
Some(Expr::StringLiteral(ast::ExprStringLiteral { value, .. })) => {
874886
let url = value.to_str().trim_start();
875887
if url.starts_with("http://") || url.starts_with("https://") {
876888
return None;
877889
}
878-
}
890+
},
891+
892+
// If the `url` argument is an f-string literal, allow `http` and `https` schemes.
893+
Some(Expr::FString(ast::ExprFString { value, .. })) => {
894+
if let Some(ast::FStringElement::Literal(ast::FStringLiteralElement { value, .. })) = value.elements().next() {
895+
let url = value.trim_start();
896+
if url.starts_with("http://") || url.starts_with("https://") {
897+
return None;
898+
}
899+
}
900+
},
879901

880902
// If the `url` argument is a `urllib.request.Request` object, allow `http` and `https` schemes.
881-
if let Expr::Call(ExprCall { func, arguments, .. }) = arg {
903+
Some(Expr::Call(ExprCall { func, arguments, .. })) => {
882904
if checker.semantic().resolve_qualified_name(func.as_ref()).is_some_and(|name| name.segments() == ["urllib", "request", "Request"]) {
883-
if let Some( Expr::StringLiteral(ast::ExprStringLiteral { value, .. })) = arguments.find_argument("url", 0) {
905+
match arguments.find_argument("url", 0) {
906+
// If the `url` argument is a string literal, allow `http` and `https` schemes.
907+
Some(Expr::StringLiteral(ast::ExprStringLiteral { value, .. })) => {
884908
let url = value.to_str().trim_start();
885909
if url.starts_with("http://") || url.starts_with("https://") {
886910
return None;
887911
}
888-
912+
},
913+
914+
// If the `url` argument is an f-string literal, allow `http` and `https` schemes.
915+
Some(Expr::FString(ast::ExprFString { value, .. })) => {
916+
if let Some(ast::FStringElement::Literal(ast::FStringLiteralElement { value, .. })) = value.elements().next() {
917+
let url = value.trim_start();
918+
if url.starts_with("http://") || url.starts_with("https://") {
919+
return None;
920+
}
921+
}
922+
},
923+
_ => {}
889924
}
890925
}
891-
}
926+
},
927+
928+
_ => {}
892929
}
893930
}
894931
Some(SuspiciousURLOpenUsage.into())

0 commit comments

Comments
 (0)