Post

OWASP Top 10 2025: How to Secure Your Code Part 1

OWASP Top 10 2025: How to Secure Your Code Part 1

In this series I’m going to go through the OWASP Top 10:2025 list with a snippet of vulnerable code relating to the vulnerability and show you how to secure it using Python.

Vulnerable Code

Below is a piece of vulnerable code which contains a Broken Access Control, Security Misconfiguration, and Software Supply Chain Failure vulnerability as listed on the OWASP Top 10:2025.

vuln code

Note

The original vulnerable code was generated by AI, but it contained some bugs so I’ve updated it and made adjustments using the original code. The secure code changes and comments listed throughout the article and linked below were done by me.

Broken Access Control

Broken Access Control is the result of not enforcing rules on who can view data or perform actions on a given website or application. For example, if I login to a webpage and the url is https://www.mywebsite.com/user?id=1 if I were to change the id=1 to id=2 and get another user’s landing page, then that is Broken Access Control, more specifically it is called an IDOR (Insecure Direct Object Reference). In this case, as a normal user I should not be able to view other user’s landing pages or have access to them, only an admin should have these privileges. This is just one example of Broken Access Control and more specifically an IDOR.

Looking at the vulnerable code above, can you spot the IDOR? If you didn’t know FastAPI appends function arguments to the URL. So looking at our code we have user_id, plugin_url, and debug_mode which means if we set values to user_id=1, plugin_url=https://www.myurl.com/plugin.py, debug_mode=true our url will look like https://www.mywebsite.com/api/user-profile?user_id=1&plugin_url=https://www.myurl.com/plugin.py&debug_mode=true. That means we can change the user_id value in our URL and it will load the appropriate user we request because our query to the database doesn’t check if we are the querying user or an admin. Here is the vulnerability in action.

idor vuln 1

idor vuln 2

One way to secure this is to get the current user using a JWT token. A JWT Token is a Json Web Token that allows for a stateless authentication and authorization between a client and a server. We encode a payload with a secret key and then decode it when the user logs in. When we decode the payload we can compare the values of the payload against the values used in the query of the database and if it’s not an admin or the appropriate user querying their own info then we deny the request. Here is an example of the secure code and of it working. To do this we call FastAPI’s authenication login form to login as Alice and the token gets encoded after we successfully login. Then when we query the database using the user-profile endpoint which depends on a function called get_user to decode our payload and get the required information to check against our database query.

idor fix login

idor fix allow

idor fix deny

There is a second case of broken access control here and it is how we present the data from the database to the user. We don’t want to show the user the password or whether it is an admin or not, so what we can do is define what we send to the user. We create a new dictionary with just the id and the username and send that back to the user when we successfully query our profile. Here’s an example with the code following:

info fix

BAC fix1

BAC fix2

BAC fix3

Security Misconfiguration

A security misconfiguration is when an application, server, or cloud service is setup with insecure default settings, open permissions, missing system hardening, or information disclosure. Imagine you get a new router and the credentials needed to login to the router portal are admin admin and you don’t change them. Any bad actor with access to your router can get in as most default credentials for routers, servers, etc are well known and documented. Another example is let’s say you’re working on a website but leave debugging turned on. So when a user gets an error it returns information about the host. These, and more, all fall under security misconfigurations and can lead to bad actors initiating an attack. Can you see the security misconfiguration in the code above?

There are 2 that I will be pointing out, but only 1 that we care about for this section. The first one is our database which is missing system hardening due to the hardcoded credentials. This is one we’re not going to fix for the sake of this example, at least not yet, as it also falls under another category of the OWASP Top 10. The second one, which we will be addressing here, is allowing debug_mode on by default and exposing sensitive information about our system and internal frameworks, more specifically it’s exposing my environment variables and the service we’re using.

debug on

The fix for this particular issue is quite simple, we remove the option of allowing debug_mode to be set in our URL and remove the exception that is exposing our sensitive information to any potential attackers. We then replace the message that was leaking our internal information to a more specific error message.

debug off

BAC fix3

Software Supply Chain Failure

OWASP says software supply chain failures are “…breakdowns or other compromises in the process of building, distributing, or updating software”. The cause of this could be third-party libraries or code that the service or system relies on or some other dependency. This vulnerability occurs when using components that are out-of-date or unsupported, you don’t scan for vulnerabilities regularly or don’t subscribe to security bulletins on the components you use. Can you spot the vulnerability in our code?

The vulnerability is in the block of code where we are loading a python script. We should NEVER allow users to upload or use their own scripts as they can be malicious. Allowing a user to upload a malicious script can lead to a Remote Code Execution (RCE) vulnerability and give an attack FULL access to your system. For this code specifically there is no reason to allow users to upload their own scripts so we’re going to completely remove that option.

This one is fairly straight-forward to fix and there’s not much to it, but here is an article from ibm on the Log4j issue that plagued businesses in 2021. This should give you a better understanding of how software supply chain failures occur in production and how to prevent them.

BAC fix3

This concludes the first part of the article on securing OWASP Top10:2025 security vulnerabilities. You can find the vulnerable and secure code versions on my github here.

This post is licensed under CC BY 4.0 by the author.