Skip to content

Conversation

@Linish2020
Copy link

This is for testing

return render(request, 'mitre/mitre_lab_17.html')

def command_out(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Found 'subprocess' function 'Popen' with 'shell=True'. This is dangerous because this call will spawn the command using a shell process. Doing so propagates current shell settings and variables, which makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead.

To resolve this comment:

💡 Follow autofix suggestion

Suggested change
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by subprocess-shell-true.

You can view more details about this finding in the Semgrep AppSec Platform.

'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=300),
'iat': datetime.datetime.utcnow()
}
cookie = jwt.encode(payload, 'csrf_vulneribility', algorithm='HS256')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Hardcoded JWT secret or private key is used. This is a Insufficiently Protected Credentials weakness: https://cwe.mitre.org/data/definitions/522.html Consider using an appropriate security mechanism to protect the credentials (e.g. keeping secrets in environment variables)

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by jwt-python-hardcoded-secret.

You can view more details about this finding in the Semgrep AppSec Platform.

def csrf_transfer_monei_api(request,recipent,amount):
if request.method == "GET":
cookie = request.COOKIES['auth_cookiee']
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
A secret is hard-coded in the application. Secrets stored in source code, such as credentials, identifiers, and other types of sensitive data, can be leaked and used by internal or external malicious actors. Use environment variables to securely provide credentials and other secrets or retrieve them from a secure vault or Hardware Security Module (HSM).

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])
import os
payload = jwt.decode(cookie, os.environ.get('JWT_SECRET'), algorithms=['HS256'])
View step-by-step instructions
  1. Remove the hardcoded JWT secret 'csrf_vulneribility' from all jwt.encode and jwt.decode calls.
  2. Store your secret key outside of your source code, such as in an environment variable. For example, add JWT_SECRET to your server's environment configuration.
  3. In your code, import the os module if it's not already present: import os
  4. Retrieve the secret using os.environ.get('JWT_SECRET') in both jwt.encode and jwt.decode:
    • Replace jwt.encode(payload, 'csrf_vulneribility', algorithm='HS256') with jwt.encode(payload, os.environ.get('JWT_SECRET'), algorithm='HS256')
    • Replace jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256']) with jwt.decode(cookie, os.environ.get('JWT_SECRET'), algorithms=['HS256'])
  5. Make sure the JWT_SECRET environment variable is set in your deployment (e.g., in your .env file or deployment config).

Using environment variables helps prevent accidental leaks of sensitive keys in source code repositories.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by python-pyjwt-hardcoded-secret.

You can view more details about this finding in the Semgrep AppSec Platform.

if request.method == 'GET':
try:
cookie = request.COOKIES['auth_cookiee']
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
A secret is hard-coded in the application. Secrets stored in source code, such as credentials, identifiers, and other types of sensitive data, can be leaked and used by internal or external malicious actors. Use environment variables to securely provide credentials and other secrets or retrieve them from a secure vault or Hardware Security Module (HSM).

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])
import os
JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY')
payload = jwt.decode(cookie, JWT_SECRET_KEY, algorithms=['HS256'])
View step-by-step instructions
  1. Remove the hardcoded secret 'csrf_vulneribility' from all jwt.encode and jwt.decode calls.
  2. Store the secret securely in an environment variable, for example, JWT_SECRET_KEY.
  3. At the top of your file, import os if it isn't already imported: import os
  4. Retrieve the secret from the environment by adding JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY').
  5. Replace all usages of the hardcoded string 'csrf_vulneribility' with JWT_SECRET_KEY in both jwt.encode and jwt.decode calls:
    Example: jwt.decode(cookie, JWT_SECRET_KEY, algorithms=['HS256'])
  6. Set the environment variable JWT_SECRET_KEY securely in your deployment environment, not in the source code.

This approach keeps sensitive secrets out of your codebase and helps prevent accidental leaks.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by python-pyjwt-hardcoded-secret.

You can view more details about this finding in the Semgrep AppSec Platform.

'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=300),
'iat': datetime.datetime.utcnow()
}
cookie = jwt.encode(payload, 'csrf_vulneribility', algorithm='HS256')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
A secret is hard-coded in the application. Secrets stored in source code, such as credentials, identifiers, and other types of sensitive data, can be leaked and used by internal or external malicious actors. Use environment variables to securely provide credentials and other secrets or retrieve them from a secure vault or Hardware Security Module (HSM).

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
cookie = jwt.encode(payload, 'csrf_vulneribility', algorithm='HS256')
import os # Make sure this is at the top of your file
cookie = jwt.encode(payload, os.environ["JWT_SECRET_KEY"], algorithm='HS256')
View step-by-step instructions
  1. Remove the hardcoded secret key 'csrf_vulneribility' from all uses of jwt.encode and jwt.decode.
  2. Store your JWT secret key in an environment variable. For example, add JWT_SECRET_KEY to your system or .env file.
  3. At the top of your file, import the os module if it is not already imported: import os
  4. Replace 'csrf_vulneribility' in both jwt.encode(...) and jwt.decode(...) with os.environ["JWT_SECRET_KEY"]:
    • Example: cookie = jwt.encode(payload, os.environ["JWT_SECRET_KEY"], algorithm='HS256')
    • And: payload = jwt.decode(cookie, os.environ["JWT_SECRET_KEY"], algorithms=['HS256'])
  5. Ensure your deployment environment sets the JWT_SECRET_KEY environment variable with a strong, random value.

Storing secrets in environment variables instead of source code reduces the risk of credential leaks.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by python-pyjwt-hardcoded-secret.

You can view more details about this finding in the Semgrep AppSec Platform.

Comment on lines +237 to +247
@csrf_exempt
def mitre_lab_17_api(request):
if request.method == "POST":
ip = request.POST.get('ip')
command = "nmap " + ip
res, err = command_out(command)
res = res.decode()
err = err.decode()
pattern = "STATE SERVICE.*\\n\\n"
ports = re.findall(pattern, res,re.DOTALL)[0][14:-2].split('\n')
return JsonResponse({'raw_res': str(res), 'raw_err': str(err), 'ports': ports})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Detected usage of @csrf_exempt, which indicates that there is no CSRF token set for this route. This could lead to an attacker manipulating the user's account and exfiltration of private data. Instead, create a function without this decorator.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
@csrf_exempt
def mitre_lab_17_api(request):
if request.method == "POST":
ip = request.POST.get('ip')
command = "nmap " + ip
res, err = command_out(command)
res = res.decode()
err = err.decode()
pattern = "STATE SERVICE.*\\n\\n"
ports = re.findall(pattern, res,re.DOTALL)[0][14:-2].split('\n')
return JsonResponse({'raw_res': str(res), 'raw_err': str(err), 'ports': ports})
def mitre_lab_17_api(request):
if request.method == "POST":
ip = request.POST.get('ip')
command = "nmap " + ip
res, err = command_out(command)
res = res.decode()
err = err.decode()
pattern = "STATE SERVICE.*\\n\\n"
ports = re.findall(pattern, res,re.DOTALL)[0][14:-2].split('\n')
return JsonResponse({'raw_res': str(res), 'raw_err': str(err), 'ports': ports})
View step-by-step instructions
  1. Remove the @csrf_exempt decorator from the mitre_lab_17_api function.
  2. If you need to exempt some views from CSRF checks for valid reasons (such as for APIs intended for third-party access), make sure you use appropriate authentication and add CSRF protection elsewhere or use tokens like JWT.
  3. If the route is intended for use within your own web application (e.g., called via AJAX from templates you control), rely on Django's default CSRF protection. Ensure that your frontend sends the CSRF token with AJAX requests by including the token in your request headers.
  4. Test submitting a POST request to this endpoint from your frontend to make sure the CSRF token is being sent and the request succeeds as expected.

Django provides CSRF protection by default to help prevent cross-site request forgery attacks, so only remove these decorators unless you absolutely require it for legitimate API design purposes.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by no-csrf-exempt.

You can view more details about this finding in the Semgrep AppSec Platform.

return render(request, 'mitre/mitre_lab_17.html')

def command_out(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Detected subprocess function 'mitre_lab_17_api' with user controlled data. A malicious actor could leverage this to perform command injection. You may consider using 'shlex.escape()'.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>mitre1.py</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L240 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 240] request.POST.get(&apos;ip&apos;)</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L240 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 240] ip</a>"]

            v3["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L241 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 241] command</a>"]

            v4["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L242 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 242] command_out</a>"]

            v5["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L232 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 232] command</a>"]
        end
            v2 --> v3
            v3 --> v4
            v4 --> v5
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L233 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 233] command</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by dangerous-subprocess-use.

You can view more details about this finding in the Semgrep AppSec Platform.

return render(request, 'mitre/mitre_lab_17.html')

def command_out(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Detected user input entering a subprocess call unsafely. This could result in a command injection vulnerability. An attacker could use this vulnerability to execute arbitrary commands on the host, which allows them to download malware, scan sensitive data, or run any command they wish on the server. Do not let users choose the command to run. In general, prefer to use Python API versions of system commands. If you must use subprocess, use a dictionary to allowlist a set of commands.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>mitre1.py</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L238 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 238] request</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L238 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 238] request</a>"]

            v3["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L240 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 240] ip</a>"]

            v4["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L241 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 241] command</a>"]

            v5["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L242 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 242] command_out</a>"]

            v6["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L232 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 232] command</a>"]
        end
            v2 --> v3
            v3 --> v4
            v4 --> v5
            v5 --> v6
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L233 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 233] subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by subprocess-injection.

You can view more details about this finding in the Semgrep AppSec Platform.

Comment on lines +176 to +189
@authentication_decorator
@csrf_exempt
def csrf_transfer_monei(request):
if request.method == 'GET':
try:
cookie = request.COOKIES['auth_cookiee']
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])
username = payload['username']
User = CSRF_user_tbl.objects.filter(username=username)
if not User:
redirect('/mitre/9/lab/login')
return render(request, 'mitre/csrf_dashboard.html', {'balance': User[0].balance})
except:
return redirect('/mitre/9/lab/login')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Detected usage of @csrf_exempt, which indicates that there is no CSRF token set for this route. This could lead to an attacker manipulating the user's account and exfiltration of private data. Instead, create a function without this decorator.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
@authentication_decorator
@csrf_exempt
def csrf_transfer_monei(request):
if request.method == 'GET':
try:
cookie = request.COOKIES['auth_cookiee']
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])
username = payload['username']
User = CSRF_user_tbl.objects.filter(username=username)
if not User:
redirect('/mitre/9/lab/login')
return render(request, 'mitre/csrf_dashboard.html', {'balance': User[0].balance})
except:
return redirect('/mitre/9/lab/login')
@authentication_decorator
def csrf_transfer_monei(request):
if request.method == 'GET':
try:
cookie = request.COOKIES['auth_cookiee']
payload = jwt.decode(cookie, 'csrf_vulneribility', algorithms=['HS256'])
username = payload['username']
User = CSRF_user_tbl.objects.filter(username=username)
if not User:
redirect('/mitre/9/lab/login')
return render(request, 'mitre/csrf_dashboard.html', {'balance': User[0].balance})
except:
return redirect('/mitre/9/lab/login')
View step-by-step instructions
  1. Remove the @csrf_exempt decorator from the csrf_transfer_monei function definition.
  2. Make sure that your frontend forms which POST to this route include the CSRF token, typically by using Django’s {% csrf_token %} template tag within forms.
  3. Confirm that any AJAX requests to this endpoint include the CSRF token in the request headers, as per Django's CSRF protection guidelines.

Removing @csrf_exempt ensures that Django's default CSRF protection is enabled for this route, reducing the risk of cross-site request forgery attacks.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by no-csrf-exempt.

You can view more details about this finding in the Semgrep AppSec Platform.

elif request.method == 'POST':
password = request.POST.get('password')
username = request.POST.get('username')
password = md5(password.encode()).hexdigest()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
It looks like MD5 is used as a password hash. MD5 is not considered a secure password hash because it can be cracked by an attacker in a short amount of time. Use a suitable password hashing function such as scrypt. You can use hashlib.scrypt.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>mitre1.py</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L161 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 161] md5</a>"]
        end
        %% Intermediate

        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/ArmorCode-Public-Test/pygoat/blob/74b51fb13244b885e9cc6ce142fea8f875eaf939/mitre1.py#L161 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 161] md5(password.encode()).hexdigest()</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    File0:::invis

    %% Connections

    Source --> Sink


Loading

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
password = md5(password.encode()).hexdigest()
import os
import hashlib
# To use scrypt securely, you must store each user's salt alongside their password hash.
# Here we use a static salt for illustration, but in production generate/store per-user salts.
STATIC_SALT = b'some_static_salt' # Replace with per-user salt in production
# If you have access to user's salt from the database, retrieve it here.
# Example: user_obj = CSRF_user_tbl.objects.filter(username=username).first()
# salt = user_obj.salt if user_obj else STATIC_SALT
salt = STATIC_SALT # Replace this line to get the actual per-user salt as above.
password = hashlib.scrypt(password.encode(), salt=salt, n=16384, r=8, p=1).hex()
View step-by-step instructions
  1. Replace the usage of md5 for password hashing with a secure password hash function, such as hashlib.scrypt.
  2. Change the line password = md5(password.encode()).hexdigest() to use scrypt as follows:
    password = hashlib.scrypt(password.encode(), salt=b'some_unique_salt', n=16384, r=8, p=1).hex()
    Replace b'some_unique_salt' with a unique, securely generated salt for each user if possible.
  3. If you store password hashes in the database, make sure to store both the salt and the hashed password.
  4. Update the login and user creation logic to use the same password hashing method so passwords can be verified correctly.

Using scrypt instead of md5 makes it much harder for attackers to crack user passwords, since scrypt is designed to be slow and computationally expensive.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by md5-used-as-password.

You can view more details about this finding in the Semgrep AppSec Platform.

def mitre_lab_25_api(request):
if request.method == "POST":
expression = request.POST.get('expression')
result = eval(expression)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Detected the use of eval(). eval() can be dangerous if used to evaluate dynamic content. If this content can be input from outside the program, this may be a code injection vulnerability. Ensure evaluated content is not definable by external sources.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
result = eval(expression)
import ast
# ... [previous code unchanged] ...
@csrf_exempt
def mitre_lab_25_api(request):
if request.method == "POST":
expression = request.POST.get('expression')
try:
# Safely evaluate only Python literals (numbers, strings, tuples, lists, dicts, booleans, and None)
result = ast.literal_eval(expression)
except (ValueError, SyntaxError):
result = "Invalid input"
return JsonResponse({'result': result})
else:
return redirect('/mitre/25/lab/')
# ... [following code unchanged] ...
View step-by-step instructions
  1. Remove the line that calls eval(expression).
  2. Replace it with code that safely handles only the operations you need. If the allowed expressions are limited (e.g., only math calculations), use the ast.literal_eval function: import ast then result = ast.literal_eval(expression).
  3. If that’s still too permissive, validate and parse the input more strictly—such as using regular expressions to allow only digits and operators you want to support.
  4. Raise an error or return an error message if the input does not match expected safe patterns.

For simple math, this would look like:

import re
expression = request.POST.get('expression')
if re.fullmatch(r"[0-9+\-*/ ().]+", expression):
    result = eval(expression)
else:
    result = "Invalid input"

Replace eval(expression) with the safer ast.literal_eval(expression) if only literals (numbers, tuples, lists, etc.) must be supported.

This avoids security risks because eval will execute any code it receives, which can allow attackers to run arbitrary Python commands if input is unchecked.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by eval-detected.

You can view more details about this finding in the Semgrep AppSec Platform.

}
cookie = jwt.encode(payload, 'csrf_vulneribility', algorithm='HS256')
response = redirect("/mitre/9/lab/transaction")
response.set_cookie('auth_cookiee', cookie)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Django cookies should be handled securely by setting secure=True, httponly=True, and samesite='Lax' in response.set_cookie(...). If your situation calls for different settings, explicitly disable the setting. If you want to send the cookie over http, set secure=False. If you want to let client-side JavaScript read the cookie, set httponly=False. If you want to attach cookies to requests for external sites, set samesite=None.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
response.set_cookie('auth_cookiee', cookie)
response.set_cookie('auth_cookiee', cookie, secure=True, httponly=True, samesite='Lax')
View step-by-step instructions
  1. Add these arguments to the response.set_cookie call: secure=True, httponly=True, samesite='Lax'.
  2. The full line should look like:
    response.set_cookie('auth_cookiee', cookie, secure=True, httponly=True, samesite='Lax')
  3. If you intentionally need different settings (for example, if cookies must be read by JavaScript or sent cross-site), explicitly set httponly=False or samesite=None as needed.

This change ensures the cookie is only sent over HTTPS, cannot be accessed by JavaScript, and is not sent with cross-site requests, making it less likely to be exposed to attackers.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by django-secure-set-cookie.

You can view more details about this finding in the Semgrep AppSec Platform.

Comment on lines +214 to +221
@csrf_exempt
def mitre_lab_25_api(request):
if request.method == "POST":
expression = request.POST.get('expression')
result = eval(expression)
return JsonResponse({'result': result})
else:
return redirect('/mitre/25/lab/')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Detected usage of @csrf_exempt, which indicates that there is no CSRF token set for this route. This could lead to an attacker manipulating the user's account and exfiltration of private data. Instead, create a function without this decorator.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
@csrf_exempt
def mitre_lab_25_api(request):
if request.method == "POST":
expression = request.POST.get('expression')
result = eval(expression)
return JsonResponse({'result': result})
else:
return redirect('/mitre/25/lab/')
def mitre_lab_25_api(request):
if request.method == "POST":
expression = request.POST.get('expression')
result = eval(expression)
return JsonResponse({'result': result})
else:
return redirect('/mitre/25/lab/')
View step-by-step instructions
  1. Remove the @csrf_exempt decorator from the mitre_lab_25_api function.
  2. Make sure that your frontend sends the CSRF token in POST requests to this view, typically by including the X-CSRFToken header.
  3. If you are using Django's default template system, ensure that your form includes {% csrf_token %} inside the <form> tag.

This will ensure that Django's CSRF protection is enforced for this view and reduce the risk of cross-site request forgery.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by no-csrf-exempt.

You can view more details about this finding in the Semgrep AppSec Platform.

Comment on lines +217 to +218
expression = request.POST.get('expression')
result = eval(expression)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:
Found user data in a call to 'eval'. This is extremely dangerous because it can enable an attacker to execute arbitrary remote code on the system. Instead, refactor your code to not use 'eval' and instead use a safe library for the specific functionality you need.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
expression = request.POST.get('expression')
result = eval(expression)
expression = request.POST.get('expression')
# Use simpleeval to safely evaluate mathematical expressions
from simpleeval import simple_eval
try:
result = simple_eval(expression)
except Exception as e:
# If the expression is invalid, return an error message
result = f"Invalid expression: {str(e)}"
View step-by-step instructions
  1. Remove the line that uses eval(expression). Do not directly evaluate user input with eval.
  2. If you need to allow users to perform mathematical calculations, use the ast.literal_eval function from Python's standard library, which only safely evaluates Python literals (like numbers, strings, lists, etc.), or use a math expression parser like simpleeval or sympy.
    For example, replace eval(expression) with:
    • import ast
    • result = ast.literal_eval(expression)
  3. Alternatively, if you need to support full calculator-style math expressions (e.g. 2+2, 3*5), install and use a library like simpleeval:
    • $ pip install simpleeval
    • from simpleeval import simple_eval
    • result = simple_eval(expression)
  4. Validate or sanitize the input as much as possible to prevent unsafe expressions from being processed.

The eval function can execute arbitrary code, which lets attackers take control of your server. Libraries like ast.literal_eval or simpleeval only allow safe expressions and are designed for this use case.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by user-eval.

You can view more details about this finding in the Semgrep AppSec Platform.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Nov 3, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
4 Security Hotspots
99.2% Duplication on New Code (required ≤ 3%)
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants