Skip to content

Commit

Permalink
Add module level import rules
Browse files Browse the repository at this point in the history
  • Loading branch information
qdegraaf committed Dec 1, 2023
1 parent 66a9330 commit 6641d4f
Show file tree
Hide file tree
Showing 14 changed files with 322 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
import dill # S403
from dill import objects # S403
import shelve
from shelve import open
import cPickle
from cPickle import load
import pickle
from pickle import load
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
import lxml # S410
from lxml import etree # S410
from lxml import etree # S410
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import wsgiref.handlers # S413
from twisted.internet import reactor # S413
from twisted.web import static, server, twcgi # S413
import wsgiref.handlers # S412
from twisted.internet import reactor # S412
from twisted.web import static, server, twcgi # S412
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pyghmi # S415
from pyghmi import foo # S415

24 changes: 20 additions & 4 deletions crates/ruff_linter/src/checkers/ast/analyze/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,16 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
if checker.enabled(Rule::DeprecatedMockImport) {
pyupgrade::rules::deprecated_mock_import(checker, stmt);
}
if checker.enabled(Rule::SuspiciousTelnetlibImport) {
flake8_bandit::rules::suspicious_imports(checker, stmt)
if checker.any_enabled(&[
Rule::SuspiciousTelnetlibImport,
Rule::SuspiciousFtplibImport,
Rule::SuspiciousPickleImport,
Rule::SuspiciousSubprocessImport,
Rule::SuspiciousLxmlImport,
Rule::SuspiciousXmlrpclibImport,
Rule::SuspiciousPyghmiImport,
]) {
flake8_bandit::rules::suspicious_imports(checker, stmt);
}

for alias in names {
Expand Down Expand Up @@ -759,8 +767,16 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pyupgrade::rules::unnecessary_builtin_import(checker, stmt, module, names);
}
}
if checker.enabled(Rule::SuspiciousTelnetlibImport) {
flake8_bandit::rules::suspicious_imports(checker, stmt)
if checker.any_enabled(&[
Rule::SuspiciousTelnetlibImport,
Rule::SuspiciousFtplibImport,
Rule::SuspiciousPickleImport,
Rule::SuspiciousSubprocessImport,
Rule::SuspiciousLxmlImport,
Rule::SuspiciousXmlrpclibImport,
Rule::SuspiciousPyghmiImport,
]) {
flake8_bandit::rules::suspicious_imports(checker, stmt);
}
if checker.enabled(Rule::BannedApi) {
if let Some(module) =
Expand Down
6 changes: 6 additions & 0 deletions crates/ruff_linter/src/rules/flake8_bandit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ mod tests {
#[test_case(Rule::SuspiciousURLOpenUsage, Path::new("S310.py"))]
#[test_case(Rule::SuspiciousTelnetUsage, Path::new("S312.py"))]
#[test_case(Rule::SuspiciousTelnetlibImport, Path::new("S401.py"))]
#[test_case(Rule::SuspiciousFtplibImport, Path::new("S402.py"))]
#[test_case(Rule::SuspiciousPickleImport, Path::new("S403.py"))]
#[test_case(Rule::SuspiciousSubprocessImport, Path::new("S404.py"))]
#[test_case(Rule::SuspiciousLxmlImport, Path::new("S410.py"))]
#[test_case(Rule::SuspiciousXmlrpclibImport, Path::new("S411.py"))]
#[test_case(Rule::SuspiciousPyghmiImport, Path::new("S415.py"))]
#[test_case(Rule::TryExceptContinue, Path::new("S112.py"))]
#[test_case(Rule::TryExceptPass, Path::new("S110.py"))]
#[test_case(Rule::UnixCommandWildcardInjection, Path::new("S609.py"))]
Expand Down
100 changes: 87 additions & 13 deletions crates/ruff_linter/src/rules/flake8_bandit/rules/suspicious_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
//! See: <https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html>
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{self as ast, Expr, ExprCall, Stmt};
use ruff_text_size::Ranged;
use ruff_python_ast::{self as ast, Stmt};
use ruff_text_size::{Ranged, TextRange};

use crate::checkers::ast::Checker;
use crate::codes::Rule::SuspiciousFTPLibUsage;
use crate::registry::AsRule;

// TODO: Docs
Expand Down Expand Up @@ -157,25 +156,100 @@ impl Violation for SuspiciousPyghmiImport {
/// S401, S402, S403, S404, S405, S406, S407, S408, S409, S410, S411, S412, S413
pub(crate) fn suspicious_imports(checker: &mut Checker, stmt: &Stmt) {
match stmt {
Stmt::Import(ast::StmtImport { names, ..}) => {
Stmt::Import(ast::StmtImport { names, .. }) => {
for name in names {
match name.name.as_str() {
"telnetlib" => {
checker.diagnostics.push(Diagnostic::new(SuspiciousTelnetlibImport, name.range))
},
"telnetlib" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousTelnetlibImport),
name.range,
),
"ftplib" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousFtplibImport),
name.range,
),
"pickle" | "cPickle" | "dill" | "shelve" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousPickleImport),
name.range,
),
"subprocess" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousSubprocessImport),
name.range,
),
"lxml" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousLxmlImport),
name.range,
),
"xmlrpc" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousXmlrpclibImport),
name.range,
),
"pyghmi" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousPyghmiImport),
name.range,
),
_ => {}
}
}
},
}
Stmt::ImportFrom(ast::StmtImportFrom { module, .. }) => {
let Some(identifier) = module else { return };
match identifier.as_str() {
"telnetlib" => {
checker.diagnostics.push(Diagnostic::new(SuspiciousTelnetlibImport, identifier.range()))
},
"telnetlib" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousTelnetlibImport),
identifier.range(),
),
"ftplib" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousFtplibImport),
identifier.range(),
),
"pickle" | "cPickle" | "dill" | "shelve" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousPickleImport),
identifier.range(),
),
"subprocess" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousSubprocessImport),
identifier.range(),
),
"lxml" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousLxmlImport),
identifier.range(),
),
"xmlrpc" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousXmlrpclibImport),
identifier.range(),
),
"pyghmi" => check_and_push_diagnostic(
checker,
DiagnosticKind::from(SuspiciousPyghmiImport),
identifier.range(),
),
_ => {}
}
},
}
_ => panic!("Expected Stmt::Import | Stmt::ImportFrom"),
};
}
}

fn check_and_push_diagnostic(
checker: &mut Checker,
diagnostic_kind: DiagnosticKind,
range: TextRange,
) {
let diagnostic = Diagnostic::new::<DiagnosticKind>(diagnostic_kind, range);
if checker.enabled(diagnostic.kind.rule()) {
checker.diagnostics.push(diagnostic);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S401.py:1:8: S401 `telnetlib` and related modules are considered insecure. Use SSH or some other encrypted protocol
|
1 | import telnetlib # S401
| ^^^^^^^^^ S401
2 | from telnetlib import Telnet # S401
|

S401.py:2:6: S401 `telnetlib` and related modules are considered insecure. Use SSH or some other encrypted protocol
|
1 | import telnetlib # S401
2 | from telnetlib import Telnet # S401
| ^^^^^^^^^ S401
|


Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S402.py:1:8: S402 `ftplib` and related modules are considered insecure. Use SSH/SFTP/SCP or some other encrypted protocol
|
1 | import ftplib # S402
| ^^^^^^ S402
2 | from ftplib import FTP # S402
|

S402.py:2:6: S402 `ftplib` and related modules are considered insecure. Use SSH/SFTP/SCP or some other encrypted protocol
|
1 | import ftplib # S402
2 | from ftplib import FTP # S402
| ^^^^^^ S402
|


Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S403.py:1:8: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
1 | import dill # S403
| ^^^^ S403
2 | from dill import objects # S403
3 | import shelve
|

S403.py:2:6: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
1 | import dill # S403
2 | from dill import objects # S403
| ^^^^ S403
3 | import shelve
4 | from shelve import open
|

S403.py:3:8: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
1 | import dill # S403
2 | from dill import objects # S403
3 | import shelve
| ^^^^^^ S403
4 | from shelve import open
5 | import cPickle
|

S403.py:4:6: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
2 | from dill import objects # S403
3 | import shelve
4 | from shelve import open
| ^^^^^^ S403
5 | import cPickle
6 | from cPickle import load
|

S403.py:5:8: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
3 | import shelve
4 | from shelve import open
5 | import cPickle
| ^^^^^^^ S403
6 | from cPickle import load
7 | import pickle
|

S403.py:6:6: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
4 | from shelve import open
5 | import cPickle
6 | from cPickle import load
| ^^^^^^^ S403
7 | import pickle
8 | from pickle import load
|

S403.py:7:8: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
5 | import cPickle
6 | from cPickle import load
7 | import pickle
| ^^^^^^ S403
8 | from pickle import load
|

S403.py:8:6: S403 `pickle`, `cPickle`, `dill` and `shelve` modules are possibly insecure
|
6 | from cPickle import load
7 | import pickle
8 | from pickle import load
| ^^^^^^ S403
|


Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S404.py:1:8: S404 `subprocess` module is possibly insecure
|
1 | import subprocess # S404
| ^^^^^^^^^^ S404
2 | from subprocess import Popen # S404
3 | from subprocess import Popen as pop # S404
|

S404.py:2:6: S404 `subprocess` module is possibly insecure
|
1 | import subprocess # S404
2 | from subprocess import Popen # S404
| ^^^^^^^^^^ S404
3 | from subprocess import Popen as pop # S404
|

S404.py:3:6: S404 `subprocess` module is possibly insecure
|
1 | import subprocess # S404
2 | from subprocess import Popen # S404
3 | from subprocess import Popen as pop # S404
| ^^^^^^^^^^ S404
|


Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S410.py:1:8: S410 `lxml` is vulnerable to XML attacks
|
1 | import lxml # S410
| ^^^^ S410
2 | from lxml import etree # S410
|

S410.py:2:6: S410 `lxml` is vulnerable to XML attacks
|
1 | import lxml # S410
2 | from lxml import etree # S410
| ^^^^ S410
|


Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S411.py:1:8: S411 XMLRPC is particularly dangerous as it is also concerned with communicating data over a network
|
1 | import xmlrpc # S411
| ^^^^^^ S411
2 | from xmlrpc import server # S411
|

S411.py:2:6: S411 XMLRPC is particularly dangerous as it is also concerned with communicating data over a network
|
1 | import xmlrpc # S411
2 | from xmlrpc import server # S411
| ^^^^^^ S411
|


Loading

0 comments on commit 6641d4f

Please sign in to comment.