Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best practice for dealing with passwords in git repositories?

People also ask

Is it safe to store passwords in git?

In short, don't store your secrets in Git! This applies to both secrets that are hardcoded into your application (such as putting the database password directly in the source code, which should be avoided at any cost), as well as keeping configuration files with secrets alongside your source code (such as .

Which of the following practices can be followed when we adopt a secure repository?

Add a security policy with a SECURITY.md file. Remove a commit exposing sensitive data in a pull request. Keep sensitive files out of your repository by applying the use of a . gitignore file.

Which type of repository in GitHub helps to make the update in a secure environment?

Secret scanning is enabled for all public repositories and is available for private repositories owned by organizations that are part of an enterprise with a license for GitHub Advanced Security. For more information, see the GitHub Enterprise Cloud documentation.


The typical way to do this is to read the password info from a configuration file. If your configuration file is called foobar.config, then you would commit a file called foobar.config.example to the repository, containing sample data. To run your program, you would create a local (not tracked) file called foobar.config with your real password data.

To filter out your existing password from previous commits, see the GitHub help page on Removing sensitive data.


An approach can be to set password (or API key) using an environment variable. So this password is out of revision control.

With Bash, you can set environment variable using

export your_env_variable='your_password'

This approach can be use with continuous integration services like Travis, your code (without password) being stored in a GitHub repository can be executed by Travis (with your password being set using environment variable).

With Bash, you can get value of an environment variable using:

echo "$your_env_variable"

With Python, you can get value of an environment variable using:

import os
print(os.environ['your_env_variable'])

PS: be aware that it's probably a bit risky (but it's a quite common practice) https://www.bleepingcomputer.com/news/security/javascript-packages-caught-stealing-environment-variables/

PS2: this dev.to article titled "How to securely store API keys" may be interesting to read.


What Greg said but I'd add that it's a good idea to check in a file foobar.config-TEMPLATE.

It should contain example names, passwords or other config info. Then it is very obvious what the real foobar.config should contain, without having to look in all the code for which values must be present in foobar.config and what format they should have.

Often config values can be non obvious, like database connection strings and similar things.


Dealing with passwords in repositories would be handled different ways depending on what your exact problem is.

1. Don't do it.

And ways to avoid doing are covered in some replies - .gitignore, config.example, etc

  • .gitignore: Store on servers etc but not Git (weak solution)
  • Environment variables: https://stackoverflow.com/a/30664318/3070485
  • Config.example: https://stackoverflow.com/a/2397905/3070485
  • Command line parameter: manually enter password on program startup

or 2. Make repository accessible only to authorized people

I.e. people that are allowed to know the password. chmod and user groups comes to mind; also problems like should Github or AWS employees be allowed to see things if you host your repositories or servers externally?

or 3. Encrypt the sensitive data (purpose of this reply)

If you want to store your config files containing sensitive information (like passwords) in a public location then it needs to be encrypted. The files could be decrypted when recovered from the repository, or even used straight from their encrypted form.

An example javascript solution to using encrypted configuration data is shown below.

const fs = require('fs');
const NodeRSA = require('node-rsa');

let privatekey = new NodeRSA();
privatekey.importKey(fs.readFileSync('private.key', 'utf8'));
const config = privatekey.decrypt(fs.readFileSync('config.RSA', 'utf8'), 'json');

console.log('decrypted: ', config);

Decrypted Config File

So you can recover an encrypted config file writing just a few lines of Javascript.

Note that putting a file config.RSA into a git repository would effectively make it a binary file and so it would lose many of the benefits of something like Git, e.g. ability to cherry pick changes to it.

The solution to that might be to encrypt key value pairs or perhaps just values. You could encrypt all values, for example if you have a separate file for sensitive information, or encrypt just the sensitive values if you have all values in one file. (see below)

My example above is a bit useless to anyone wanting to do a test with it, or as an example to start from as it assumes the existence of some RSA keys and an encrypted config file config.RSA.

So here's some extra lines of code added to create RSA keys and a config file to play with.

const fs = require('fs');
const NodeRSA = require('node-rsa');

/////////////////////////////
// Generate some keys for testing
/////////////////////////////

const examplekey = new NodeRSA({b: 2048});

fs.writeFileSync('private.key', examplekey.exportKey('pkcs8-private'));
fs.writeFileSync('public.key', examplekey.exportKey('pkcs8-public'));

/////////////////////////////
// Do this on the Machine creating the config file
/////////////////////////////

const configToStore = {Goodbye: 'Cruel world'};

let publickey = new NodeRSA();
publickey.importKey(fs.readFileSync('public.key', 'utf8'));

fs.writeFileSync('config.RSA', publickey.encrypt(configToStore, 'base64'), 'utf8');

/////////////////////////////
// Do this on the Machine consuming the config file
/////////////////////////////

let privatekey = new NodeRSA();
privatekey.importKey(fs.readFileSync('private.key', 'utf8'));

const config = privatekey.decrypt(fs.readFileSync('config.RSA', 'utf8'), 'json');
console.log('decrypted: ', config);

Encrypting values only

fs.writeFileSync('config.RSA', JSON.stringify(config,null,2), 'utf8');

enter image description here

You can decrypt a config file with encrypted values using something like this.

const savedconfig = JSON.parse(fs.readFileSync('config.RSA', 'utf8'));
let config = {...savedconfig};
Object.keys(savedconfig).forEach(key => {
    config[key] = privatekey.decrypt(savedconfig[key], 'utf8');
});

With each configuration item on a separate line (e.g. Hello and Goodbye above), Git will recognize better what's going on in a file and will store changes to items of information as differences rather than complete files. Git will also be able to manage merges and cherry picks etc better.

However the more you want to version control changes to sensitive information, the more you are moving towards a SAFE REPOSITORY solution (2) and away from an ENCRYPTED INFO (3) solution.