The way I handle sensitive information in my projects such as API keys is to create a file with a class that holds sensitive information in private fields. I then put that file name in my .gitignore file so I don’t accidentally push that file to my repository. Doing this I can create methods in that class that can access that data when necessary while keeping the data from being retrievable.
I am noticing however when I look up how to do things such as send an email from a web form for example that people in these examples tend to use environment variables and environment variable files for this. Is this a safer practice than what I have been doing and if so why?
What I have been doing so far seems to work to my liking however I would like to know whether or not I am using best practices.
3
Answers
It’s good that you’re not comitting this file to version control, although this solution probably won’t hold up in a production environment. How do you plan to continuously deploy new environment variables to an environment like DigitalOcean or AWS? These platforms make changing environment variables very simple, whereas delivering source code outside of a standard build pipeline seems like a lot of unneccesary work.
It is a little difficult to say with confidence as you don’t state if this is in-browser or on a Node server (or a mix such as Next.js).
The established norm is to use a package such as https://www.npmjs.com/package/dotenv to load these values from a local file
.env
which is as you have done in your solution excluded from version control. This then allows you to substitute the local file for environment variables in production which can be set securely at runtime often handled by your hosting provider. A good example of this is in Github actions where you can set secrets which are environment variables that are redacted if logged and can be used by others without them needing to read them.In the other scenario where this is purely in the browser then your class is a good way of ensuring proper access to the information but not securing it. Once in the browser pretty much all information is readable in some way or another. If something should not be read then it needs to be moved out of the browser onto the server where you can better control access.
Hope this helps, it sounds like you have a strong data access flow which is great.
Yes, probably. Really it doesn’t matter really from a security perspective which serialisation format you chose to store the sensitive data – it could be CSV files, environment variable files, JSON files, javascript files, ini files, whatever. You must not publish the file, and it must be secured from unauthorised access.
Putting the file (whatever its content and file extension are) in your
.gitignore
is good practice to prevent it from being committed to your repository.However, your solution has one major drawback when compared to environment variable files: nobody expects code to be sensitive data. Application code should be public, especially JavaScript code which typically sent to the client anyway, everything else would be security by obscurity amirite? This makes your solution much more susceptible to such accidents. Someone might refactor the code, rename the file, move or copy the code around elsewhere…
In contrast, environment variable files or ini files are established as configuration. They are versatile, they work everywhere, their use is a best practice. People immediately understand that they are not part of the application, not application data, but rather used for deployment secrets and other configuration values.
That’s not a security measure. Private fields (just like local variables) are useful for encapsulation and code organisation, but they don’t prevent an attacker from accessing the sensitive information – in particular when there are methods in your class to access them. And if there are no methods that would expose them, only methods that use them internally, then that would be application logic; code which you really would want to commit to your repository.
And I hope you’re not running untrusted code as part of your application, to which you would pass objects with private fields in the hope of their values being inaccessible? What you still need to protect would be access to the code of those classes, which is not particularly well protected – especially if any code could just read that file.