Skip to main content

Non-upgradable dependencies

Need

Dependency management and explicit declaration of dependencies

Context

  • Usage of TypeScript for statically typed JavaScript development
  • Usage of Express for building web applications and APIs
  • Usage of body-parser for parsing request bodies in Express
  • Usage of MySQL for database connectivity and querying

Description

Non compliant code

import express from 'express';
import bodyParser from 'body-parser';
import mysql from 'mysql';

const app = express();
const port = 3000;

// Middleware
app.use(bodyParser.json());

// Database connection
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydatabase'
});

// Routes
app.get('/users', (req, res) => {
connection.query('SELECT * FROM users', (error, results) => {
if (error) {
console.error('Error retrieving users:', error);
res.status(500).json({ error: 'Internal Server Error' });
} else {
res.json(results);
}
});
});

// Start the server
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});

The vulnerability in this code is related to non-upgradable dependencies. The code imports three dependencies: express, bodyParser, and mysql. However, the code does not explicitly declare the versions of these dependencies.

By not declaring the dependencies with their specific versions, the code is relying on the dependencies being copied directly into the repositories. This can lead to several issues:

  1. Loss of maintainability: Without explicitly declaring the dependencies and their versions, it becomes difficult to track and manage them. If a newer version of a dependency is released with bug fixes or security patches, it may not be updated in the project.

  2. Late update of vulnerable units: If a vulnerability is reported for one of the dependencies, it may take longer to update the vulnerable unit in the codebase. This delay in updating the dependencies can leave the application exposed to potential security risks.

To mitigate this vulnerability, it is recommended to declare all dependencies and reference them using a dependency manager such as npm, pip, or maven. This allows for standardization of the project's construction and packaging, making it easier to manage and update dependencies when needed.

Steps

  • Declare the dependencies in the package.json file
  • Install the declared dependencies using a dependency manager like npm
  • Import the dependencies in the source code using the specified package names

Compliant code

import express from 'express';
import bodyParser from 'body-parser';
import mysql from 'mysql';

const app = express();
const port = 3000;

// Middleware
app.use(bodyParser.json());

// Database connection
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydatabase'
});

// Routes
app.get('/users', (req, res) => {
connection.query('SELECT * FROM users', (error, results) => {
if (error) {
console.error('Error retrieving users:', error);
res.status(500).json({ error: 'Internal Server Error' });
} else {
res.json(results);
}
});
});

// Start the server
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});

The fixed code addresses the vulnerability by explicitly declaring and managing the dependencies using a dependency manager. In this case, the code uses the npm package manager to manage the dependencies.

The code starts by importing the necessary modules using the import statement. The express, body-parser, and mysql modules are imported to be used in the code.

The app variable is then initialized as an instance of the express module. This will be used to create the server and handle the routes.

The port variable is set to 3000, indicating that the server will listen on port 3000.

The body-parser module is used as middleware to parse the incoming request bodies as JSON.

The mysql module is used to create a connection to the database. The connection details such as host, user, password, and database name are provided in the createConnection method.

The routes are defined using the app.get method. In this case, there is a single route /users which retrieves all users from the database. The query is executed using the connection.query method, and the results are returned as a JSON response.

The server is started by calling the app.listen method, passing in the port variable and a callback function to log that the server is running.

By explicitly declaring and managing the dependencies using a dependency manager like npm, the code ensures that the dependencies are maintained and can be easily updated when new versions or security patches are released. This improves the maintainability of the codebase and reduces the risk of using outdated or vulnerable dependencies.

References