mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 07:04:53 +00:00
[flake8-bandit
] Implement mako-templates
(S702
) (#8533)
See: https://github.com/astral-sh/ruff/issues/1646.
This commit is contained in:
parent
ce549e75bc
commit
fce9f63418
8 changed files with 102 additions and 0 deletions
9
crates/ruff_linter/resources/test/fixtures/flake8_bandit/S702.py
vendored
Normal file
9
crates/ruff_linter/resources/test/fixtures/flake8_bandit/S702.py
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
from mako.template import Template
|
||||||
|
from mako import template
|
||||||
|
import mako
|
||||||
|
|
||||||
|
|
||||||
|
Template("hello")
|
||||||
|
|
||||||
|
mako.template.Template("hern")
|
||||||
|
template.Template("hern")
|
|
@ -571,6 +571,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||||
if checker.enabled(Rule::Jinja2AutoescapeFalse) {
|
if checker.enabled(Rule::Jinja2AutoescapeFalse) {
|
||||||
flake8_bandit::rules::jinja2_autoescape_false(checker, call);
|
flake8_bandit::rules::jinja2_autoescape_false(checker, call);
|
||||||
}
|
}
|
||||||
|
if checker.enabled(Rule::MakoTemplates) {
|
||||||
|
flake8_bandit::rules::mako_templates(checker, call);
|
||||||
|
}
|
||||||
if checker.enabled(Rule::HardcodedPasswordFuncArg) {
|
if checker.enabled(Rule::HardcodedPasswordFuncArg) {
|
||||||
flake8_bandit::rules::hardcoded_password_func_arg(checker, keywords);
|
flake8_bandit::rules::hardcoded_password_func_arg(checker, keywords);
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,6 +629,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||||
(Flake8Bandit, "609") => (RuleGroup::Stable, rules::flake8_bandit::rules::UnixCommandWildcardInjection),
|
(Flake8Bandit, "609") => (RuleGroup::Stable, rules::flake8_bandit::rules::UnixCommandWildcardInjection),
|
||||||
(Flake8Bandit, "612") => (RuleGroup::Stable, rules::flake8_bandit::rules::LoggingConfigInsecureListen),
|
(Flake8Bandit, "612") => (RuleGroup::Stable, rules::flake8_bandit::rules::LoggingConfigInsecureListen),
|
||||||
(Flake8Bandit, "701") => (RuleGroup::Stable, rules::flake8_bandit::rules::Jinja2AutoescapeFalse),
|
(Flake8Bandit, "701") => (RuleGroup::Stable, rules::flake8_bandit::rules::Jinja2AutoescapeFalse),
|
||||||
|
(Flake8Bandit, "702") => (RuleGroup::Preview, rules::flake8_bandit::rules::MakoTemplates),
|
||||||
|
|
||||||
// flake8-boolean-trap
|
// flake8-boolean-trap
|
||||||
(Flake8BooleanTrap, "001") => (RuleGroup::Stable, rules::flake8_boolean_trap::rules::BooleanTypeHintPositionalArgument),
|
(Flake8BooleanTrap, "001") => (RuleGroup::Stable, rules::flake8_boolean_trap::rules::BooleanTypeHintPositionalArgument),
|
||||||
|
|
|
@ -28,6 +28,7 @@ mod tests {
|
||||||
#[test_case(Rule::HardcodedTempFile, Path::new("S108.py"))]
|
#[test_case(Rule::HardcodedTempFile, Path::new("S108.py"))]
|
||||||
#[test_case(Rule::HashlibInsecureHashFunction, Path::new("S324.py"))]
|
#[test_case(Rule::HashlibInsecureHashFunction, Path::new("S324.py"))]
|
||||||
#[test_case(Rule::Jinja2AutoescapeFalse, Path::new("S701.py"))]
|
#[test_case(Rule::Jinja2AutoescapeFalse, Path::new("S701.py"))]
|
||||||
|
#[test_case(Rule::MakoTemplates, Path::new("S702.py"))]
|
||||||
#[test_case(Rule::LoggingConfigInsecureListen, Path::new("S612.py"))]
|
#[test_case(Rule::LoggingConfigInsecureListen, Path::new("S612.py"))]
|
||||||
#[test_case(Rule::ParamikoCall, Path::new("S601.py"))]
|
#[test_case(Rule::ParamikoCall, Path::new("S601.py"))]
|
||||||
#[test_case(Rule::RequestWithNoCertValidation, Path::new("S501.py"))]
|
#[test_case(Rule::RequestWithNoCertValidation, Path::new("S501.py"))]
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
use ruff_python_ast::{self as ast};
|
||||||
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
|
/// ## What it does
|
||||||
|
/// Checks for uses of the `mako` templates.
|
||||||
|
///
|
||||||
|
/// ## Why is this bad?
|
||||||
|
/// Mako templates allow HTML and JavaScript rendering by default, and are
|
||||||
|
/// inherently open to XSS attacks. Ensure variables in all templates are
|
||||||
|
/// properly sanitized via the `n`, `h` or `x` flags (depending on context).
|
||||||
|
/// For example, to HTML escape the variable `data`, use `${ data |h }`.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```python
|
||||||
|
/// from mako.template import Template
|
||||||
|
///
|
||||||
|
/// Template("hello")
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```python
|
||||||
|
/// from mako.template import Template
|
||||||
|
///
|
||||||
|
/// Template("hello |h")
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## References
|
||||||
|
/// - [Mako documentation](https://www.makotemplates.org/)
|
||||||
|
/// - [OpenStack security: Cross site scripting XSS](https://security.openstack.org/guidelines/dg_cross-site-scripting-xss.html)
|
||||||
|
/// - [Common Weakness Enumeration: CWE-80](https://cwe.mitre.org/data/definitions/80.html)
|
||||||
|
#[violation]
|
||||||
|
pub struct MakoTemplates;
|
||||||
|
|
||||||
|
impl Violation for MakoTemplates {
|
||||||
|
#[derive_message_formats]
|
||||||
|
fn message(&self) -> String {
|
||||||
|
format!(
|
||||||
|
"Mako templates allow HTML and JavaScript rendering by default and are inherently open to XSS attacks"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// S702
|
||||||
|
pub(crate) fn mako_templates(checker: &mut Checker, call: &ast::ExprCall) {
|
||||||
|
if checker
|
||||||
|
.semantic()
|
||||||
|
.resolve_call_path(&call.func)
|
||||||
|
.is_some_and(|call_path| matches!(call_path.as_slice(), ["mako", "template", "Template"]))
|
||||||
|
{
|
||||||
|
checker
|
||||||
|
.diagnostics
|
||||||
|
.push(Diagnostic::new(MakoTemplates, call.func.range()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ pub(crate) use hardcoded_tmp_directory::*;
|
||||||
pub(crate) use hashlib_insecure_hash_functions::*;
|
pub(crate) use hashlib_insecure_hash_functions::*;
|
||||||
pub(crate) use jinja2_autoescape_false::*;
|
pub(crate) use jinja2_autoescape_false::*;
|
||||||
pub(crate) use logging_config_insecure_listen::*;
|
pub(crate) use logging_config_insecure_listen::*;
|
||||||
|
pub(crate) use mako_templates::*;
|
||||||
pub(crate) use paramiko_calls::*;
|
pub(crate) use paramiko_calls::*;
|
||||||
pub(crate) use request_with_no_cert_validation::*;
|
pub(crate) use request_with_no_cert_validation::*;
|
||||||
pub(crate) use request_without_timeout::*;
|
pub(crate) use request_without_timeout::*;
|
||||||
|
@ -37,6 +38,7 @@ mod hardcoded_tmp_directory;
|
||||||
mod hashlib_insecure_hash_functions;
|
mod hashlib_insecure_hash_functions;
|
||||||
mod jinja2_autoescape_false;
|
mod jinja2_autoescape_false;
|
||||||
mod logging_config_insecure_listen;
|
mod logging_config_insecure_listen;
|
||||||
|
mod mako_templates;
|
||||||
mod paramiko_calls;
|
mod paramiko_calls;
|
||||||
mod request_with_no_cert_validation;
|
mod request_with_no_cert_validation;
|
||||||
mod request_without_timeout;
|
mod request_without_timeout;
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/flake8_bandit/mod.rs
|
||||||
|
---
|
||||||
|
S702.py:6:1: S702 Mako templates allow HTML and JavaScript rendering by default and are inherently open to XSS attacks
|
||||||
|
|
|
||||||
|
6 | Template("hello")
|
||||||
|
| ^^^^^^^^ S702
|
||||||
|
7 |
|
||||||
|
8 | mako.template.Template("hern")
|
||||||
|
|
|
||||||
|
|
||||||
|
S702.py:8:1: S702 Mako templates allow HTML and JavaScript rendering by default and are inherently open to XSS attacks
|
||||||
|
|
|
||||||
|
6 | Template("hello")
|
||||||
|
7 |
|
||||||
|
8 | mako.template.Template("hern")
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ S702
|
||||||
|
9 | template.Template("hern")
|
||||||
|
|
|
||||||
|
|
||||||
|
S702.py:9:1: S702 Mako templates allow HTML and JavaScript rendering by default and are inherently open to XSS attacks
|
||||||
|
|
|
||||||
|
8 | mako.template.Template("hern")
|
||||||
|
9 | template.Template("hern")
|
||||||
|
| ^^^^^^^^^^^^^^^^^ S702
|
||||||
|
|
|
||||||
|
|
||||||
|
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -3386,6 +3386,7 @@
|
||||||
"S7",
|
"S7",
|
||||||
"S70",
|
"S70",
|
||||||
"S701",
|
"S701",
|
||||||
|
"S702",
|
||||||
"SIM",
|
"SIM",
|
||||||
"SIM1",
|
"SIM1",
|
||||||
"SIM10",
|
"SIM10",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue