Skip to main content

Sensitive information in source code

Need

Protection of sensitive information in source code

Context

  • Usage of Dart for building cross-platform mobile, web, and desktop applications
  • Usage of Shelf for managing and organizing data in Node.js applications
  • Usage of shelf_io for managing and interacting with data storage in Node.js

Description

Non compliant code

import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);

io.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
// Sensitive information in source code
var username = 'admin';
var password = '123456';
var email = '[email protected]';
var ip = '192.168.1.1';
var aws_secret_key = 'test';

return shelf.Response.ok('Request for "${request.url}"');
}

The Dart code above is an example of a backend application using the Shelf framework. The function _echoRequest contains sensitive information in the source code.

The variables username, password, email, ip, and aws_secret_key are hardcoded into the code, which is a serious security vulnerability. This information should never be stored directly in the source code, especially not without any form of encryption.

If this code were to be committed to a public repository, anyone who has access to that repository would be able to see this sensitive information. This could potentially lead to unauthorized access of any systems that use these credentials.

Additionally, this code reveals a bad practice of storing sensitive information in the repository with no encryption. Even if these are placeholder values, they can be replaced with real sensitive values, which can lead to serious security risks.

The recommended practice is to store sensitive information in environment variables or in a secure and encrypted database, and to use secure methods to access this information. This way, the sensitive information is not exposed in the source code and is kept secure.

Steps

  • Remove the hard-coded sensitive information from the source code.
  • Use environment variables to store sensitive information. This way, the sensitive data is not exposed in the code.
  • If the sensitive information is required for the application to function, consider using a secure method to retrieve it, such as a secure API call.
  • Encrypt sensitive data if it must be stored in the code. This way, even if someone gains access to the code, they cannot read the sensitive data.
  • Implement a secure method for handling user authentication, such as OAuth or JWT, instead of hard-coding usernames and passwords.
  • Regularly rotate sensitive keys and credentials to limit the potential damage if they are compromised.
  • Consider using a secrets management tool or service for handling sensitive data.

Compliant code

import 'dart:io';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;

void main() {
var handler = const shelf.Pipeline().addMiddleware(shelf.logRequests())
.addHandler(_echoRequest);

io.serve(handler, 'localhost', 8080);
}

shelf.Response _echoRequest(shelf.Request request) {
// Sensitive information retrieved from environment variables
var username = Platform.environment['USERNAME'];
var password = Platform.environment['PASSWORD'];
var email = Platform.environment['EMAIL'];
var ip = Platform.environment['IP'];
var aws_secret_key = Platform.environment['AWS_SECRET_KEY'];

return shelf.Response.ok('Request for "${request.url}"');
}

The updated code no longer contains hard-coded sensitive information. Instead, it retrieves this information from environment variables. This is a more secure practice as it ensures that sensitive data is not exposed in the code.

The Platform.environment method is used to retrieve the values of the environment variables. These variables should be set in the environment where the application is running.

For example, in a Unix-based system, you can set these variables in the terminal before running the application:

export USERNAME=admin
export PASSWORD=123456
export [email protected]
export IP=192.168.1.1
export AWS_SECRET_KEY=test

Then, you can run your application, and it will have access to these environment variables.

Remember, this is just a basic example. In a real-world scenario, you should never expose sensitive information even in your environment variables. Always use secure methods to handle sensitive data, such as secrets management tools or services, and encrypt data whenever possible.

Also, consider implementing secure methods for handling user authentication, such as OAuth or JWT, instead of using usernames and passwords directly. Regularly rotate sensitive keys and credentials to limit the potential damage if they are compromised.

References