# Isn't storing secrets in environment variables not safe?

**URL:** <https://community.sonarsource.com/t/isnt-storing-secrets-in-environment-variables-not-safe/138097>\
**Category:** Rules and Languages\
**Tags:** secrets\
**Created:** [April 1, 2025, 3:06pm UTC](https://community.sonarsource.com/t/isnt-storing-secrets-in-environment-variables-not-safe/138097 "2025-04-01T15:06:01Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Philippe\_Formulain](https://dub1.discourse-cdn.com/sonarsource/user_avatar/community.sonarsource.com/philippe_formulain/32/64599_2.png) [@Philippe\_Formulain](https://community.sonarsource.com/u/Philippe_Formulain)\
**Post date:** [April 1, 2025, 3:06pm UTC](https://community.sonarsource.com/t/isnt-storing-secrets-in-environment-variables-not-safe/138097/1 "2025-04-01T15:06:01Z")

</div>

I’m reading some of the [secret rules descriptions](https://rules.sonarsource.com/secrets/), and something looks strange to me: you seem to officially recommend to store secrets in environment variables.

Typically:

> Code examples
> 
> #### Noncompliant code example
> 
> props.set(“vercel\_api\_access\_token”, “EFvQS4yzzxia31Hg5xmy6uOn”) // Noncompliant
> 
> #### Compliant solution
> 
> props.set(“vercel\_api\_access\_token”, System.getenv(“VERCEL\_API\_ACCESS\_TOKEN”))

By nature, methods like `System.getenv` are available to every single part of the executed application, including imported dependencies. It is not possible to know if one of the dependencies - direct or transitive - tries to access well known environment keys, like `VERCEL_API_ACCESS_TOKEN`.

Isn’t it dangerous to officially recommend to store secrets in environment variables?

Wouldn’t it be more accurate to recommend to pass them as arguments to the executable, and have the `main` method store them in memory, and clean the passed `args`, so that they are not accessible from this point forward?

---

<div class="post-metadata">

**Author:** ![daniel\_teuchert](https://dub1.discourse-cdn.com/sonarsource/user_avatar/community.sonarsource.com/daniel_teuchert/32/49255_2.png) [@daniel\_teuchert](https://community.sonarsource.com/u/daniel_teuchert)\
**Post date:** [April 3, 2025, 9:34am UTC](https://community.sonarsource.com/t/isnt-storing-secrets-in-environment-variables-not-safe/138097/5 "2025-04-03T09:34:22Z")

</div>

Hello Philippe,  
thank you for raising your concern in our community forum.

If I understand correctly, you are concerned that a malicious dependency that can execute arbitrary (Java) code in the context of the application can obtain secrets passed as environment variables more easily than if these secrets would be passed as command line arguments.

While it is true, that `System.getenv` can be used to obtain set environment variables, a malicious dependency could also use `System.getProperty("sun.java.command");` to obtain the passed command line arguments.  
So, given this attacker scenario I do not see any difference.

If you want to go for extra security you can indeed try to use some techniques that limit the time when a secret is stored in memory. However, these techniques are usually not necessary for the most scenarios and therefore we suggest setting secrets via environment variables since this will be sufficient for most users.

You can also read more about secrets management in this cheat sheet by OWASP: [Secrets Management - OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)

I hope my explanation helps,  
Daniel

---

<div class="post-metadata">

**Author:** ![Philippe\_Formulain](https://dub1.discourse-cdn.com/sonarsource/user_avatar/community.sonarsource.com/philippe_formulain/32/64599_2.png) [@Philippe\_Formulain](https://community.sonarsource.com/u/Philippe_Formulain)\
**Post date:** [April 3, 2025, 5:09pm UTC](https://community.sonarsource.com/t/isnt-storing-secrets-in-environment-variables-not-safe/138097/6 "2025-04-03T17:09:21Z")

</div>

> [@daniel\_teuchert](#):
>
> a malicious dependency could also use `System.getProperty("sun.java.command");` to obtain the passed command line arguments

True. But I’m not refering to the JVM only. The rule that I mention, except if I miss something obvious, is _runtime_ agnostic. But the compliant solution is opinionated towards environment variables.

Typically, with Node.js, it is possible to:

> have the `main` method store them in memory, and clean the passed `args`

In my opinion, this should be the proposed compliant solution for every runtime that allows cleaning the received arguments.

In the case of Node.js, even `process.env` can be cleaned, so this is another option.

```js
console.log(process.argv); // ['/usr/local/bin/node', 'index.js']
console.log(process.env); // {...gazillons of things}

process.argv = [];
process.env = {};

console.log(process.argv);// []
console.log(process.env); // {}

```

But, environment variables are available to every single process that runs in a given host. And we can’t do anything against that. Cleaning them in the entry point of one specific application doesn’t make them less accessible to all the others. They are out of control.

Storing sensitive data in environment variables is basically admitting that we put those sensitive data at the disposal of every single process. This is not secure.
