Skip to content

Commit

Permalink
fix(rules): improve S507 detection (#7661)
Browse files Browse the repository at this point in the history
## Summary

Follow-up on #7528 that improves
detections of mis-usages of policy in `paramiko`.

First commit applies the same fix as in `bandit`
(PyCQA/bandit#1064), as `paramiko` supports
passing both a class and a class instance for the policy in
`set_missing_host_key_policy`
(https://github.com/paramiko/paramiko/blob/8e389c77660c5cdae3069b478665427d23012853/paramiko/client.py#L171-L191).

Second commit improve the detection of `paramiko` import paths that
trigger a violation, as `AutoAddPolicy`, `WarningPolicy` and `SSHClient`
are not only exposed in `paramiko.client`, but also in `paramiko`
(https://github.com/paramiko/paramiko/blob/66117732de6de03914308f9a21b05b50a781d13c/paramiko/__init__.py#L121-L164).

## Test Plan

Snapshot tests.
  • Loading branch information
mkniewallner committed Sep 28, 2023
1 parent 5e75467 commit cfbebcf
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import paramiko
from paramiko import client
from paramiko.client import AutoAddPolicy, WarningPolicy

ssh_client = client.SSHClient()
ssh_client_from_paramiko = paramiko.SSHClient()

# OK
ssh_client.set_missing_host_key_policy(policy=foo)
Expand All @@ -12,10 +14,12 @@
# Errors
ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
ssh_client.set_missing_host_key_policy(client.WarningPolicy)
ssh_client.set_missing_host_key_policy(client.AutoAddPolicy())
ssh_client.set_missing_host_key_policy(AutoAddPolicy)
ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
ssh_client_from_paramiko.set_missing_host_key_policy(paramiko.AutoAddPolicy)

# Unrelated
set_missing_host_key_policy(client.AutoAddPolicy)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::map_callable;
use ruff_python_ast::{Expr, ExprAttribute, ExprCall};
use ruff_python_semantic::analyze::typing;
use ruff_text_size::Ranged;
Expand Down Expand Up @@ -56,21 +57,26 @@ pub(crate) fn ssh_no_host_key_verification(checker: &mut Checker, call: &ExprCal
return;
};

// Detect either, e.g., `paramiko.client.AutoAddPolicy` or `paramiko.client.AutoAddPolicy()`.
if !checker
.semantic()
.resolve_call_path(policy_argument)
.resolve_call_path(map_callable(policy_argument))
.is_some_and(|call_path| {
matches!(
call_path.as_slice(),
["paramiko", "client", "AutoAddPolicy" | "WarningPolicy"]
| ["paramiko", "AutoAddPolicy" | "WarningPolicy"]
)
})
{
return;
}

if typing::resolve_assignment(value, checker.semantic()).is_some_and(|call_path| {
matches!(call_path.as_slice(), ["paramiko", "client", "SSHClient"])
matches!(
call_path.as_slice(),
["paramiko", "client", "SSHClient"] | ["paramiko", "SSHClient"]
)
}) {
checker.diagnostics.push(Diagnostic::new(
SSHNoHostKeyVerification,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,62 +1,82 @@
---
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
---
S507.py:13:40: S507 Paramiko call with policy set to automatically trust the unknown host key
S507.py:15:40: S507 Paramiko call with policy set to automatically trust the unknown host key
|
12 | # Errors
13 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
14 | # Errors
15 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
| ^^^^^^^^^^^^^^^^^^^^ S507
14 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
15 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
17 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy())
|

S507.py:14:40: S507 Paramiko call with policy set to automatically trust the unknown host key
S507.py:16:40: S507 Paramiko call with policy set to automatically trust the unknown host key
|
12 | # Errors
13 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
14 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
14 | # Errors
15 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
| ^^^^^^^^^^^^^^^^^^^^ S507
15 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
17 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy())
18 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
|

S507.py:15:40: S507 Paramiko call with policy set to automatically trust the unknown host key
S507.py:17:40: S507 Paramiko call with policy set to automatically trust the unknown host key
|
15 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
17 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy())
| ^^^^^^^^^^^^^^^^^^^^^^ S507
18 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
19 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
|

S507.py:18:40: S507 Paramiko call with policy set to automatically trust the unknown host key
|
13 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy)
14 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
15 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
17 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy())
18 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
| ^^^^^^^^^^^^^ S507
16 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
17 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
19 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
20 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
|

S507.py:16:47: S507 Paramiko call with policy set to automatically trust the unknown host key
S507.py:19:47: S507 Paramiko call with policy set to automatically trust the unknown host key
|
14 | ssh_client.set_missing_host_key_policy(client.WarningPolicy)
15 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
17 | ssh_client.set_missing_host_key_policy(client.AutoAddPolicy())
18 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
19 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
| ^^^^^^^^^^^^^^^^^^^^ S507
17 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
18 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
20 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
21 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
|

S507.py:17:47: S507 Paramiko call with policy set to automatically trust the unknown host key
S507.py:20:47: S507 Paramiko call with policy set to automatically trust the unknown host key
|
15 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
16 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
17 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
18 | ssh_client.set_missing_host_key_policy(AutoAddPolicy)
19 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
20 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
| ^^^^^^^^^^^^^^^^^^^^ S507
18 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
21 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
22 | ssh_client_from_paramiko.set_missing_host_key_policy(paramiko.AutoAddPolicy)
|

S507.py:18:47: S507 Paramiko call with policy set to automatically trust the unknown host key
S507.py:21:47: S507 Paramiko call with policy set to automatically trust the unknown host key
|
16 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
17 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
18 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
19 | ssh_client.set_missing_host_key_policy(policy=client.AutoAddPolicy)
20 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
21 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
| ^^^^^^^^^^^^^ S507
19 |
20 | # Unrelated
22 | ssh_client_from_paramiko.set_missing_host_key_policy(paramiko.AutoAddPolicy)
|

S507.py:22:54: S507 Paramiko call with policy set to automatically trust the unknown host key
|
20 | ssh_client.set_missing_host_key_policy(policy=client.WarningPolicy)
21 | ssh_client.set_missing_host_key_policy(policy=WarningPolicy)
22 | ssh_client_from_paramiko.set_missing_host_key_policy(paramiko.AutoAddPolicy)
| ^^^^^^^^^^^^^^^^^^^^^^ S507
23 |
24 | # Unrelated
|


0 comments on commit cfbebcf

Please sign in to comment.