Skip to content

Commit

Permalink
SONARPY-1434 Rule S5122: Add support for flask_cors 2 (#1638)
Browse files Browse the repository at this point in the history
  • Loading branch information
joke1196 authored Nov 8, 2023
1 parent bded873 commit e6751e0
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ public class CorsCheck extends PythonSubscriptionCheck {
".+$",
"^.*",
"^.+",
STAR
);
STAR);

private static final String ALLOW_ORIGIN = "Access-Control-Allow-Origin";
private static final String ORIGINS = "origins";
Expand All @@ -94,8 +93,7 @@ public class CorsCheck extends PythonSubscriptionCheck {
"django.http.HttpResponse",
"django.http.response.HttpResponse",
"werkzeug.datastructures.Headers",
"werkzeug.datastructures.headers.Headers"
);
"werkzeug.datastructures.headers.Headers");

private static final List<String> REQUEST_SET_HEADER_QUALIFIER = Arrays.asList("headers", "add");

Expand Down Expand Up @@ -241,7 +239,8 @@ private static void checkFlaskDecorator(SubscriptionContext ctx) {
expression = ((CallExpression) expression).callee();
}
TreeUtils.getSymbolFromTree(expression).ifPresent(symbol -> {
if (isSymbol(symbol, "flask_cors.decorator.cross_origin")) {
if (isSymbol(symbol, "flask_cors.decorator.cross_origin") ||
isSymbol(symbol, "flask.ext.cors.cross_origin")) {
ArgList arguments = decorator.arguments();
if (arguments == null) {
ctx.addIssue(decorator, MESSAGE);
Expand Down Expand Up @@ -306,7 +305,8 @@ private static <T extends Tree> void reportOnHeader(SubscriptionContext ctx, T e
private static void checkFlaskCorsCall(SubscriptionContext ctx) {
CallExpression callExpression = (CallExpression) ctx.syntaxNode();
Symbol calleeSymbol = callExpression.calleeSymbol();
if (!isSymbol(calleeSymbol, "flask_cors.extension.CORS")) {
if (!isSymbol(calleeSymbol, "flask_cors.extension.CORS") &&
!isSymbol(calleeSymbol, "flask.ext.cors.CORS")) {
return;
}

Expand Down
38 changes: 38 additions & 0 deletions python-checks/src/test/resources/checks/hotspots/cors/cors.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,41 @@ def flask_app_response_headers_set():
non_call_response = app.NonResponse("Foo bar baz")
non_call_response.headers['Access-Control-Allow-Origin'] = '*'
return resp

def flask_cross_origin_decorator_version2():
from flask.ext.cors import cross_origin
@cross_origin() # Noncompliant
# ^^^^^^^^^^^^^^^
@cross_origin # Noncompliant
# ^^^^^^^^^^^^^
@cross_origin(origins="*") # Noncompliant
# ^^^^^^^^^^^^^^^^^^^^^^^^^^
@cross_origin(origins=r".*") # Noncompliant
@cross_origin(origins=r".+") # Noncompliant
@cross_origin(origins=["*"]) # Noncompliant
@cross_origin(origins="trustedwebsite.com") # Compliant
@cross_origin(origins=["trustedwebsite.com"]) # Compliant
@foo.cross_origin() # compliant
@foo_cross_origin() # compliant
def foo():
pass

def flask_cors_version2():
from flask.ext.cors import CORS
app = flask.Flask(__name__)
CORS(app) # Noncompliant
CORS(app, origins="*") # Noncompliant
CORS(app, origins=r".*") # Noncompliant
CORS(app, origins=["*"]) # Noncompliant
CORS(app, origins="trustedwebsite.com") # Compliant
CORS(app, origins=0) # Compliant
CORS(app, origins=["trustedwebsite.com"]) # Compliant
CORS(app, resources=r"/api/*") # Noncompliant
CORS(app, resources=r"/api/*", origins="trustedwebsite.com") # OK
CORS(app, resources=0) # OK
CORS(app, resources={r"/api/1": {"origins": "*"}, r"/api/2": {"origins": "*"}}) # Noncompliant
CORS(app, resources={r"/api/*": {"origins": r".*"}}) # Noncompliant
CORS(app, resources={r"/api/*": {"origins": ["*"]}}) # Noncompliant
CORS(app, resources={r"/api/*": {"foo": ["*"]}}) # OK
CORS(app, resources={r"/api/*": {"origins": "trustedwebsite.com"}, **unpack}) # Compliant
CORS(app, resources={r"/api/*": {"origins": ["trustedwebsite.com"]}}) # Compliant

0 comments on commit e6751e0

Please sign in to comment.