Alexander Williams is a full stack developer and technical writer, with a background working as an independent IT consultant and helping new business owners set up their websites.
Read more from Alexander T. Williams
JavaScript has once again retained its title as the top programming language in Stack Overflow’s annual developer survey (overall, not just for web development), fending off rivals like Rust, but that doesn’t mean it’s airtight and invulnerable.
On the contrary — JS is validated client-side, which means hackers are continuously developing new ways to exploit vulnerabilities and stay one step ahead of devs and security experts.
So, in this article, we’ll tackle the vulnerabilities and attack vectors causing the most headaches for JavaScript developers. And by the looks of it, these issues will stay hot topics well into 2025 and possibly beyond.
In 2023, a particularly nasty JavaScript malware was unleashed on 40 banks and 50,000 users across the world. It was delivered via phishing and generated fake login pages, equipped with malicious JS code designed to snatch OTPs (one-time passwords) and other login data.
This case, and many others similar to it, highlights the fact that even something as ubiquitous as JS can be prone to exploits.
First comes reputational loss, of course. But if a threat actor exploits a JS vulnerability and manages to access user data, especially if it’s kept in the form of MS 365 backups or on a Google Drive that is poorly protected, the consequences could be calamitous.
The exploited website may be culpable for any financial loss if such an incident occurs. Not to mention, relevant authorities will take a closer look at the site and check for any other violations.
To make things even worse, there are thousands of third-party JS libraries, each with various known vulnerabilities that threat actors can exploit with varying degrees of difficulty. These risks can be amplified if web owners fail to implement relevant security policies such as CSP and SRI, since JavaScript environments don’t have built-in security permissions as standard.
The point is: if you don’t care about shoring up your JS code for security purposes, the costs will be dizzying!
Threat actors are turning to new and more advanced techniques to bypass existing security protocols and turn JS into their golden goose. At the same, some old threats are still looming in the background.
An XSS attack involves a hacker injecting malicious scripts into a website and can be achieved in several ways. Once injected, the script typically executes malware that infects the website or the user’s machine when they access the website or application.
The goal is to steal sensitive information or modify the website to conduct malicious activity. This attack often targets banks, financial institutions, and websites that handle financial transactions.
It can be a sneaky way for cybercriminals to read bank statements, record the entry of financial details (sniffing), and find vulnerabilities to attack either the end-user or the financial institution itself.
Cross-Site Request Forgery (CSRF) forces authenticated end users to execute unintended actions. It’s often delivered via social engineering techniques such as sending a link in an email, web chat, or SMS text, tricking users into transferring funds or entering financial details.
This technique can be even more disastrous if it compromises a user who has a high level of access, potentially compromising the entire application and all its users. To make things even worse, AI-generated attacks muddy the waters by making it harder to discern fake pages from real ones.
Thus, the most effective method for preventing CSRF attacks, other than educating web users on the risk of social engineering, is to include CSRF tokens within relevant requests. These tokens enforce strict criteria that are uniquely tied to each user session, preventing malicious actors from striking.
Server-side code injection vulnerabilities are present in web applications that integrate user-controllable data in a string that is dynamically validated by a code interpreter.
If the data is not validated correctly, threat actors can modify the input and inject arbitrary code that is then executed on the server. If successful, this type of attack can compromise an entire application in terms of both data and functionality — and even use the webserver to launch additional attacks on other systems.
To prevent SSJI attacks, user-controllable data should not be incorporated in dynamically evaluated code. If this isn’t possible then all code needs to be strictly validated, preferably using a whitelist that only accepts specific values.
An old threat, formjacking can still result in data theft with relative ease. All that’s needed is a shoddy codebase, and the following happens:
Formjacking is a growing concern, particularly for e-commerce websites or any web applications that handle sensitive user information through forms. The only way to combat this well-known risk is to run regular integrity checks and offer users one-time payment options for e-commerce.
Prototype pollution is a JS vulnerability that allows threat actors to add arbitrary properties to global object prototypes, which user-defined objects can also inherit. These prototypes can then be used to allow or override object behaviors.
To initiate the attack, threat actors must identify JS functions or DOM elements that enable arbitrary code execution.
After exploiting these global objects, hackers can control properties in a web application that would otherwise have been unattainable, allowing them to launch attacks from within.
In a scenario where the client-side JavaScript has been exploited, the hacker will likely attempt a DOM XSS. Meanwhile, server-side, prototype pollution is generally used to conduct remote code execution.
Insecure direct object references (IDOR) mainly affect web applications that rely on user-supplied input to access objects and database records.
This incorrect access control implementation can result in these controls being redirected, granting unauthorized access to the threat actor. Think of a Node.js-built app accessing user IDs from a database and things only spiraling from there.
How to combat IDOR attacks? Well, developers should avoid using direct object references when building a JS application, and instead implement user input validation, globally unique identifiers (GUIDs), and random identifiers to prevent IDOR vulnerabilities.
Supply chain attacks target third-party tools and services used to provide web functionality. An example of this is third-party libraries that contain pre-written scripts to make developing websites and applications easier.
As a result, indirect attacks target the dependencies that connect a third-party tool to an application, such as those that power AI chatbots or allow a website to accept payments.
A threat actor will usually target a specific vendor, adding malicious code to their software which is then rolled out to clients when they install an update. Because the client trusts the source, these attacks can successfully infiltrate in huge numbers.
The June 2024 attack using the Polyfill.io JS library is perhaps the most recent example of this type of attack occurring. While the obvious solution is to focus on well-known open source libraries, this also stifles innovation by slowing down the adoption of newer, more efficient JS libraries.
The benefits of JavaScript when building websites and web applications are evident, but the programming language’s widespread popularity also brings risks. As JavaScript is validated client-side, the process of securing apps becomes more difficult.
Many of these vulnerabilities are created when the application is developed, with mistakes such as incorrect input validation and the use of user-controllable data being two of the most common errors.
However, some attacks require more advanced mitigation techniques such as the use of security tokens. Stay safe out there.