Credential Leakage Risks Hiding in Frontend Code

The Big Threat to Credentials in Cyber Security

How much do you know about the importance of credentials? Credentials are the privileges that give you access to an application or system, such as API keys, database access information, session tokens, and more. What happens if these credentials are exposed to the outside world?

It's a scary thing to think about. For starters, if an attacker gets hold of your credentials, they'll be able to take control of some of your services. It's not uncommon for them to crash your site, trick users into taking over their accounts, or even worse, compromise your customers' information. Services today store a lot of valuable data, including personal information. What happens when an attacker steals this data? Individuals could suffer identity theft or financial harm, and organizations could face legal sanctions and huge losses in trust. It's a devastating blow that can threaten a company's very existence.

In other words, credentials are like the keys to a safe. You don't want to hand over the keys to your organization's most valuable assets - your data - to the wrong hands. So, just like keys, credentials need to be locked away and access to them tightly controlled, especially when they're embedded in front-end code. Front-end code that runs in the open space of the browser can be easily snooped on by anyone, so sensitive credentials should never be left on the front-end for any reason.

Credential Breaches Are Becoming More Common

That's exactly what happened to Resend. Their front-end code left hard-coded database access information exposed. Hackers were able to learn environment variables from client source code and access customer databases at will. As a result, the company suffered a serious security breach.

Unfortunately, this story is not unique. We used Probe to validate the front-end code of some of South Korea's most popular websites and found that 14 out of 70 sites had exposed credentials. In short, they're making similar mistakes to Resend.

Credential Leak Example

The most common issue was the exposure of OAuth's Client Secret, which is a sensitive value used for OAuth authentication that, if compromised, can put the entire service at risk. The next most common issue was third-party access tokens with all permissions open. These tokens are used as authentication when calling external APIs, and if the permissions are not set correctly, an attacker can exploit the token to manipulate the core functionality of the service.

AWS Key Leaked

We've also seen critical credentials, such as AWS IAM secret keys, embedded directly into the code - hard-coded. This may seem like a small mistake at first glance, but it poses a huge security risk.

OIDC Token Leaked

On some sites, the OIDC access token used by the build server was left as an environment variable, which was left in the front-end build files, or the credentials were left in a configuration file that was accidentally committed to the repository.

These examples suggest that many organizations overlook the importance of front-end security, perhaps out of a vague sense of complacency that the front-end is less risky than the back-end, but it's important to recognize that the security risks inherent in the front-end are not to be taken lightly.

So why do so many developers neglect front-end security? The truth is, in haste, they often hardcode credentials instead of setting cumbersome environment variables. But more importantly, this has become increasingly common in recent years because today's front-end code doesn't just draw on the screen, it often deals directly with sensitive data.

Let's take a look at an example of how this mistake can be made during development. First, let's take a look at the next.config.js file, which is responsible for configuring the Next.js application.

next js secret

The above code is a good example of a common security issue that can arise in the pursuit of ease of development. The publicRuntimeConfig option is a feature provided by Next.js that allows you to set client-side accessible environment variables. This is useful for things like public API keys or settings needed for business logic. However, in the codeabove, we're assigning process.env in its entirety using the spread syntax. This means that we're exposing all of the server's environment variables to the client without exception.

What if process.envcontains sensitive credentials, such as database access information, secret keys for third-party services, and so on? It's just bundled into the client-side bundle, making it accessible to everyone. If you open your browser's developer tools, you'll see code like process.env.DB_PASSWORD in plain text, which is obviously a development convenience, but it's a pretty risky code from a security perspective.

next js ssr security issue

The code above shows a case where Next.js's page router includes a hardcoded credential key during server-side rendering (SSR). Typically, Next.js doesn't bundle server-side code with the client, so many developers hardcode the secret key as a convenience, thinking it's relatively safe compared to the API route. But there's a pitfall. It's the source map.

For example, you might upload a source map to introduce an error monitoring solution like Sentry. This is because they need the source map to map the obfuscated stack traces to the original code.

The problem is that these source maps can also contain server-side code. This means that not only the API routes are exposed, but also any code written to get Server Side Props (SSP). This is a very dangerous situation, as it shows that Sentry is a very useful tool, but it can also be an attack vector.

Sentry Security issue

Recently, the Next.js and React ecosystems have been undergoing a revolutionary transformation. The introduction of the React Server Component (RSC) in Next.js 13 revolutionized the development paradigm by blurring the lines between server-side and client-side rendering, and Next.js 14 added a new feature called Server Actions.

These technologies have greatly improved development productivity and user experience. But they also introduce new security risks. The blurring of the lines between server and client code has increased the potential for credential exposure. Let's take a look at this risk in the code below.

The above code is a simple form component using RSC. The logic is to get an environment variable called SECRET_TOKENvia the getEnv function, pass it to the run function, and run it on the server.

Here, the run function has the "use server " directive added to it. This indicates that the function will only be executed on the server and will not be sent to the client. So at first glance, it looks like the SECRET_TOKENwill never be exposed to the client, and it’s being used securely on the server only.

However, there’s a significant pitfall to watch out for. By default, Next.js encrypts Server Components before sending them to the client. But if you bind a value, as shown in the code above, the encryption is automatically bypassed when using a Server Action. This means the value of SECRET_TOKEN is exposed and embedded in the client-side code. You can confirm this by inspecting your browser’s developer tools.

next js frontend leaked


What Should We Do Next?

As such, securing front-end applications requires a systematic approach throughout the development process. The simplest and most important one is to never include sensitive information in front-end code. Credentials like API keys or secret tokens should never be included in JS bundles, no matter how convenient.

To achieve this, it's important that your entire development team understands and practices secure coding principles. Regular training and workshops will help build secure coding habits, and a culture of code review within the team will help proactively identify vulnerabilities. Creating checklists to review all code changes from a security perspective is also effective.

However, even the best processes and design can't completely eliminate human error, especially with newer technologies like Next.js' Server Action and React Server Component blurring the lines between server and client, making it easier for developers to accidentally expose credentials. It's wise to enlist the help of an automated scanning tool. Probe by Cremit not only detects hard-coded credentials in source code, but also finds and alerts you to wrongfully shared API keys, passwords, and more scattered across collaboration tools like Notion, Slack, and Jira.

When it comes to front-end development, security is no longer an option, it's a necessity. And not just from a technical standpoint, but also from a business sustainability standpoint. You must prioritize protecting your customers’ trust while enhancing brand value.

What happened to Resend should be a wake-up call, it's time to realize the importance of front-end security and get proactive. Let Probe be your vigilant guardian - the more secure your code is, the better the internet will be for everyone. Contact us today to get started.

Cremit Makes The Cyber World Safer

In addition to the numbers in this post, we also found other highly sensitive leaks (plain text exposure of credentials in Alibaba Cloud, administrator credentials in AWS Cloud, among other authentication tokens).

Most of the vulnerable sites still did not read the notifications we sent (about 20%) or did not respond (about 35%), but Cremit's continuous contact with the AWS Account Management team helped us remediate most of the threats.

Want to have a technical discussion with Cremit? Sign up for a meeting and demo.