Repository: astral-sh/ruff
File: crates/ruff_linter/src/rules/flake8_bandit/rules/suspicious_function_call.rs (Rust)

Code before:
                        // If the `url` argument is a `urllib.request.Request` object, allow `http` and `https` schemes.
                        Some(Expr::Call(ExprCall {
                            func, arguments, ..
                        })) => {
                            if checker
                                .semantic()
                                .resolve_qualified_name(func.as_ref())
                                .is_some_and(|name| {
                                    name.segments() == ["urllib", "request", "Request"]
                                })
                            {
                                if arguments
                                    .find_argument_value("url", 0)
                                    .and_then(leading_chars)
                                    .is_some_and(has_http_prefix)
                                {
                                    return;
                                }
                            }
                        }

                        // If the `url` argument is a string literal (including resolved bindings), allow `http` and `https` schemes.
                        Some(expr) => {
                            // First try to resolve bindings to string literals
                            if let Some(str_lit) =
                                resolve_to_string_literal(expr, checker.semantic())
                            {
                                if has_http_prefix(str_lit.value.chars()) {
                                    return;
                                }
                            }
                            // Fall back to checking direct string literals, f-strings, and concatenation
                            if leading_chars(expr).is_some_and(has_http_prefix) {
                                return;
                            }
                        }

                        _ => {}
                    }
                }
            }
            checker.report_diagnostic_if_enabled(SuspiciousURLOpenUsage, range)
        }

        // URLOpen (`URLopener`, `FancyURLopener`)
        ["urllib", "request", "URLopener" | "FancyURLopener"]
        | [
            "six",
            "moves",
            "urllib",
            "request",

Review comment (suggestion):
This version of `resolve_to_string_literal` actually seems too restrictive in this case since `leading_chars` just takes any `Expr`. I guess we should just resolve an `Expr::Name` to whatever its binding is and pass that directly to `leading_chars`. Something like:

```rust
                        Some(expr) => {
                            let expr = resolve_name(expr);

                            if leading_chars(expr).is_some_and(has_http_prefix) {
                                return;
                            }
                        }
```

Then we could add tests showing that we handle resolved f-strings and concatenated string literals.

Code after:
                        Some(Expr::Call(ExprCall {
                            func, arguments, ..
                        })) => {
                            if checker
                                .semantic()
                                .resolve_qualified_name(func.as_ref())
                                .is_some_and(|name| {
                                    name.segments() == ["urllib", "request", "Request"]
                                })
                            {
                                if let Some(url_expr) = arguments.find_argument_value("url", 0)
                                    && expression_starts_with_http_prefix(
                                        url_expr,
                                        checker.semantic(),
                                        checker.settings(),
                                    )
                                {
                                    return;
                                }
                            }
                        }

                        // If the `url` argument is a string literal (including resolved bindings), allow `http` and `https` schemes.
                        Some(expr) => {
                            if expression_starts_with_http_prefix(
                                expr,
                                checker.semantic(),
                                checker.settings(),
                            ) {
                                return;
                            }
                        }

                        _ => {}
                    }
                }
            }
            checker.report_diagnostic_if_enabled(SuspiciousURLOpenUsage, range)
        }

        // URLOpen (`URLopener`, `FancyURLopener`)
        ["urllib", "request", "URLopener" | "FancyURLopener"]
        | [
            "six",
            "moves",
            "urllib",
            "request",
            "URLopener" | "FancyURLopener",
        ] => checker.report_diagnostic_if_enabled(SuspiciousURLOpenUsage, range),

        // NonCryptographicRandom