This documentation is not maintained. Please refer to doc.castsoftware.com/technologies to find the latest updates.


Summary: This document provides basic information about the extension providing Node.js + Express support for Web applications.

What's New

  • Added Node.js Express Controller to have better Model-View-Controller transactions
  • Support Express Router system to better manage URL calls.
  • Issue fixed when NoSQL calls are made from Javascript methods

Description

This extension provides support for Node.jsNode.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. 

In what situation should you install this extension?

Regarding Front-End to Back-End connections, we do support the following cross-technology stacks:

iOS Front-End connected to Node.js/PostgreSQL Back-endiOS Front-End connected to Node.js/MSSQL Back-endAngularJS Front-End connected to Node.js/MongoDB Back-end

 

If your Web application contains Node.js source code and you want to view these object types and their links with other objects, then you should install this extension:

  • creates a Node.js application object when an instance has been found
  • creates Node.js operations which represent entry-points of web services
  • These declarations will create a Node.js Get Operation:

app.get('/login', function (req, res) {
    "use strict";
    console.log('login ' + req.url);
    console.log('login ' + req.query.pseudo);
    var currentSession = getSessionId(req, res);
    datab.userExists(currentSession, req.query.pseudo, res, cbLogin);
});

and this one will create a NodeJS Service Operation

var admin = express();

app.use('/admin', admin);

Supported Node.js versions

VersionSupportComment
v0.x(error)No longer supported
v4.x(tick)LTS
v5.x(tick)Based on Javascript ES6
v6.x(tick)Based on Javascript ES6

v7.x

(tick)Based on Javascript ES6
v8.x(error) 

Function Point, Quality and Sizing support

This extension provides the following support:

  • Function Points (transactions): a green tick indicates that OMG Function Point counting and Transaction Risk Index are supported
  • Quality and Sizing: a green tick indicates that CAST can measure size and that a minimum set of Quality Rules exist
Function Points
(transactions)
Quality and SizingSecurity
(tick)(tick)(tick)

Comparison with existing support for JavaScript in CAST AIP

CAST AIP has provided support for analyzing JavaScript via its JEE and .NET analyzers (provided out of box in CAST AIP) for some time now. The HTML5/JavaScript extension (on which the Node.js extension depends) also provides support for JavaScript but with a focus on web applications. CAST highly recommends that you use this extension if your Application contains JavaScript and more specifically if you want to analyze a web application, however you should take note of the following:

  • You should ensure that you configure the extension to NOT analyze the back end web client part of a .NET or JEE application.
  • You should ensure that you configure the extension to ONLY analyze the front end web application built with the HTML5/JavaScript that communicates with the back end web client part of a .NET or JEE application.
  • If the back end web client part of a .NET or JEE application is analyzed with the Node.js extension and with the native .NET/JEE analyzers, then your results will reflect this - there will be duplicate objects and links (i.e. from the analyzer and from the extension) therefore impacting results and creating erroneous Function Point data.

Note that in CAST AIP 8.3.x support for analyzing JavaScript has been withdrawn from the JEE and .NET analyzers.

CAST AIP compatibility

This extension is compatible with:

CAST AIP release
Supported
8.3.x(tick)
8.2.x(tick)
8.1.x(tick)
8.0.x(tick)
7.3.4 and all higher 7.3.x releases(tick)

Supported DBMS servers

This extension is compatible with the following DBMS servers:

CAST AIP releaseCSS2OracleMicrosoft
All supported releases(tick)(tick)(error)

Prerequisites

(tick)An installation of any compatible release of CAST AIP (see table above)

Dependencies with other extensions

Some CAST extensions require the presence of other CAST extensions in order to function correctly. The Node.js extension requires that the following other CAST extensions are also installed:

Note that when using the CAST Extension Downloader to download the extension and the Manage Extensions interface in CAST Server Manager to install the extension, any dependent extensions are automatically downloaded and installed for you. You do not need to do anything.

Download and installation instructions

Please see:

The latest release status of this extension can be seen when downloading it from the CAST Extend server.

Packaging, delivering and analyzing your source code

Once the extension is downloaded and installed, you can nowpackage your source code and run an analysis. The process of packaging, delivering and analyzing your source code is described below:

Click here to expand...

Packaging and delivery

Note that the jQuery extension does not contain any CAST Delivery Manager Tool discoverers or extractors, therefore, no "jQuery" projects will be detected. However, the Web Files Discoverer extension will be automatically installed (it is a "shipped" extension which means it is delivered with AIP Core) and will automatically detect projects as HTML5 if specific files are delivered, therefore ensuring that Analysis Units are created for your source code.

Using CAST Console

Using CAST Management Studio

Click here to expand...
  • create a new Version
  • create a new Package for your Node.js source code using the Files on your file system option:

  • Define the root folder of your Application source code:

  • Run the Package action
  • Before delivering the source code, check the packaging results:
Without the Web Files Discover

If you are not using the Web Files Discoverer, the following will occur:

  • the CAST Delivery Manager Tool will not find any "projects" related to the Node.js application source code - this is the expected behaviour. However, if your Node.js related source code is part of a larger application (for example a JEE application), then other projects may be found during the package action (click to enlarge):

With the Web Files Discoverer

If you are using the Web Files Discoverer, the following will occur:

  • the CAST Delivery Manager Tool will automatically detect "HTML5 file projects" (see Web Files Discoverer for more technical information about how the discoverer works) related to the Node.js application source code. In addition, if your Node.js related source code is part of a larger application (for example a JEE application), then other projects may also be found during the package action (click to enlarge):

  • Deliver the Version

Analyzing

Using CAST Console

AIP Console exposes the technology configuration options once a version has been accepted/imported, or an analysis has been run. Click Universal Technology (3) in the Config (1) > Analysis (2) tab to display the available options for your Node.js source code:

Then choose the relevant Analysis Unit (1) to view the configuration:

Using the CAST Management Studio

Click here to expand...


  • Accept and deploy the Version in the CAST Management Studio.
Without the Web Files Discover

If you are not using the Web Files Discoverer, the following will occur:

  • No Analysis Units will be created automatically relating to the Node.js source code - this is the expected behaviour. However, if your Node.js related source code is part of a larger application (for example a JEE application), then other Analysis Units may be created automatically:

  • In the Current Version tab, add a new Analysis Unit specifically for your Node.js source code, selecting the Add new Universal Analysis Unit option:

  • Edit the new Analysis Unit and configure in the Source Settings tab:
    • a name for the Analysis Unit
    • ensure you tick the HTML5/JavaScript option (the Node.js extension depends on the HTML5 and JavaScript extension - and therefore the Universal Analyzer language for the AngularJS extension is set as HTML5/JavaScript)
    • define the location of the deployed Node.js source code (the CAST Management Studio will locate this automatically in the Deployment folder):

  • Run a test analysis on the Analysis Unit before you generate a new snapshot.
With the Web Files Discoverer

If you are using the Web Files Discoverer, the following will occur:

  • "HTML5" Analysis Units will be created automatically (see Web Files Discoverer for more technical information about how the discoverer works) related to the Node.js application source code. In addition, if your Node.js related source code is part of a larger application (for example a JEE application), then other Analysis Units may also be created:

  • There is nothing further to do, you can now run a test analysis on the Analysis Unit before you generate a new snapshot.

Analysis warning and error messages

Click here to expand...

Message ID
Message Type

Logged during

Impact
Remediation
Action
NODEJS-001WarningAnalysisAn internal issue occured when parsing a statement in a file. A part of a file was badly analyzed.

 

Contact CAST Technical Support

What results can you expect?

Once the analysis/snapshot generation has completed, you can view the results in the normal manner (for example via CAST Enlighten):

Node.js application with MongoDB data storage exposing web services

Objects

The following specific objects are displayed in CAST Enlighten:

IconDescription

Node.js Application

Node.js Port

Node.js Delete Operation Service
Node.js Get Operation Service
Node.js Post Operation Service
Node.js Put Operation Service

Node.js Service

Node.js Express Use

Node.js Express Controller

Node.js Get Http Request Service

Node.js Post Http Request Service

Node.js Put Http Request Service

Node.js Delete Http Request Service

Node.js Unknown Database
Node.js MongoDB Connection
Node.js MongoDB Collection

Node.js Mongoose Connection

Node.js Marklogic Database

Node.js Marklogic Collection

Node.js CouchDB database

External link behaviour

Behaviour is different depending on the version of CAST AIP you are using the extension with:

  • From 7.3.6, SQL queries are sent to the external links exactly like standard CAST AIP analyzers.
  • From 7.3.4 and before 7.3.6, a degraded mode takes place: The Node.js extension analyzes the FROM clause to retrieve table names, then sends the table names only to external links.
  • For all versions, if no links are found via external links, unresolved objects are created (with type CAST_NodeJS_Unknown_Database_Table).



Connector per RDBMS Vendor

Oracle "oracledb" connector

Connector "oracledb"
var oracledb = require('oracledb');
connection = oracledb.getConnection(
  {
    user          : "hr",
    password      : "welcome",
    connectString : "localhost/XE"
  }
);
connection.execute(
      "SELECT department_id, department_name FROM departments WHERE department_id < 70",
      function(err, result)
      {
        if (err) { console.error(err); return; }
        console.log(result.rows);
      }
  );

MS SQL "node-sqlserver" and "mssql" connectors

Connector "node-sqlserver"
var sql = require('node-sqlserver');
//
var connStr = "Driver={SQL Server Native Client 11.0};Server=myySqlDb,1433;Database=DB;UID=Henry;PWD=cat;";
var query = "SELECT * FROM GAData WHERE TestID = 17";
sql.open(connStr, function(err,conn){
    if(err){
        return console.error("Could not connect to sql: ", err);
    }
    conn.queryRaw("SELECT TOP 10 FirstName, LastName FROM authors", function (err, results) {
        if (err) {
            console.log("Error running query!");
            return;
        }
        for (var i = 0; i < results.rows.length; i++) {
            console.log("FirstName: " + results.rows[i][0] + " LastName: " + results.rows[i][1]);
        }
    });
});
var match = "%crombie%";
sql.query(conn_str, "SELECT FirstName, LastName FROM titles WHERE LastName LIKE ?", [match], function (err, results) { 
    for (var i = 0; i < results.length; i++) {
        console.log("FirstName: " + results[i].FirstName + " LastName: " + results[i].LastName);
    }
});
Connector "mssql"
var sql = require('mssql');
var config = {
    user: '...',
    password: '...',
    server: 'localhost', // You can use 'localhost\\instance' to connect to named instance 
    database: '...',
     
    options: {
        encrypt: true // Use this if you're on Windows Azure 
    }
}
  
var connection = new sql.Connection(config, function(err) {
    // ... error checks 
     
    // Query 
     
    var request = new sql.Request(connection); // or: var request = connection.request(); 
    request.query('select * from authors', function(err, recordset) {
        // ... error checks 
         
        console.dir(recordset);
    });
     
    // Stored Procedure 
     
    var request = new sql.Request(connection);
    request.input('input_parameter', sql.Int, 10);
    request.output('output_parameter', sql.VarChar(50));
    request.execute('procedure_name', function(err, recordsets, returnValue) {
        // ... error checks 
         
        console.dir(recordsets);
    });
     
});


PostgreSQL "pg" connector

Connector "pg"
var pg = require("pg");
var conString = "pg://operator:CastAIP@localhost:2280/postgres";
var client = new pg.Client(conString);
client.connect();
var querySchemas = client.query("select nspname from pg_catalog.pg_namespace");
querySchemas.on("row", function (row, result) {
    "use strict";
    result.addRow(row);
});
querySchemas.on("end", function (result) {
    "use strict";
    console.log(result.rows);
    client.end();
});

 

MySQL "my_connection" connector

Connector "my_connection"
var connection = require("my_connection");
connection.query('my_url', 
			function result_getCatLogDetails(getCatLogDetails_err, getCatLogDetails_rows, 
			getCatLogDetails_fields) {
		
				if (getCatLogDetails_err) {
			        logContent += '|ERROR'+";";
					logContent += getCatLogDetails_err.message+";";
					utils.logAppDetails(logContent);
			        deferred.reject(new Error(getCatLogDetails_err));
			    } else {
			        deferred.resolve(getCatLogDetails_rows);
			    }
			});

Connector per NoSQL Vendor

Even if we don't have NoSQL server side representation, we will create a client side representation based on the API access. Node.js analyzer will create links from Javascript functions to NoSQL "Database" or "Tables" equivalents

MongoDB "mongoose" connector

This declaration will create a MongoDB connection and model object

Connector "Mongoose"
var mongoose = require('mongoose');
 
mongoose.connect('mongodb://localhost/analyzerlauncher', function(err) {
   if (err) { throw err; }
});

// create a Mongoose model
userModel = mongoose.model('users', userSchema);
 

MarkLogic "marklogic" connector

This declaration will create a MarkLogic database and a collection

Connector "marklogic"
var db = marklogic.createDatabaseClient(conn);
 
// create Collection countries
var q = marklogic.queryBuilder;
db.documents.query(
q.where(
q.collection('countries'),
q.value('region', 'Africa'),
q.or(
q.word('background', 'France'),
q.word('Legal system', 'French')
)
)
).result(function(documents) {
documents.forEach(function(document)
{ console.log(JSON.stringify(document)); });
});

This declaration will create a marklogic collection "fake data" and a useDeleteLink to the collection "fake data".

db.documents.removeAll({collection: 'fake data'})
.result()
.then(response => console.log('Removed collection ' + response.collection))
.catch(error => console.log(error));

This declaration will create a marklogic collection "fake data" and a useInsertLink to the collection "fake data".

db.documents.write(
  data.map((item) => {
    return {
      uri: `/${item.guid}.json`,
      contentType: 'application/json',
      collections: ['fake data'],
      content: item
    }
  })
)
.result()
.then(response => console.dir(JSON.stringify(response)))
.catch(error => console.error(error));

 

CouchDB "node-couchdb" connector

This declaration will create a CouchDB database named "myDatabase".

Connector "node-couchdb"
const NodeCouchDb = require('node-couchdb');
 
// node-couchdb instance with default options 
const couch = new NodeCouchDb();
dbName = 'myDatabase';

couch.createDatabase(dbName).then(() => { }, err => {
    // request error occured 
});

This declaration will create a useSelectLink from code to the database "myDatabase".

	couch.get("myDatabase", "some_document_id").then(({data, headers, status}) => {
	    // data is json response 
	    // headers is an object with all response headers 
	    // status is statusCode number 
	}, err => {
	    // either request error occured 
	    // ...or err.code=EDOCMISSING if document is missing 
	    // ...or err.code=EUNKNOWN if statusCode is unexpected 
	});


This declaration will create a useInsertLink from code to the database "myDatabase".

couch.insert("myDatabase", {
    _id: "document_id",
    field: ["sample", "data", true]
}).then(({data, headers, status}) => {
    // data is json response 
    // headers is an object with all response headers 
    // status is statusCode number 
}, err => {
    // either request error occured 
    // ...or err.code=EDOCCONFLICT if document with the same id already exists 
});

This declaration will create a useUpdateLink from code to the database "myDatabase".

couch.update("myDatabase", {
    _id: "document_id",
    _rev: "1-xxx"
    field: "new sample data",
    field2: 1
}).then(({data, headers, status}) => {
    // data is json response 
    // headers is an object with all response headers 
    // status is statusCode number 
}, err => {
    // either request error occured 
    // ...or err.code=EFIELDMISSING if either _id or _rev fields are missing 
});

This declaration will create a useDeleteLink from code to the database "myDatabase".

couch.del("myDatabase", "some_document_id", "document_revision").then(({data, headers, status}) => {
    // data is json response 
    // headers is an object with all response headers 
    // status is statusCode number 
}, err => {
    // either request error occured 
    // ...or err.code=EDOCMISSING if document does not exist 
    // ...or err.code=EUNKNOWN if response status code is unexpected 
});

CouchDB "couchdb" connector

This declaration will create a CouchDB database named "myDatabase".

Connector "couch-db"
var myCouchDB = require('couch-db').CouchDB,
    server = new myCouchDB('http://localhost:5984');
  
server.auth(username, password);
 
server.bind('myDatabase');
var db = server.myDatabase;

These declarations will create a useInsertLink from code to the database "myDatabase".

// new document 
var doc = db.testdb.doc({});
doc.attach([{
    name: 'place.css',
    content_type: 'text/css',
    data: 'body { font-size: 12px; }'
}, {
    name: 'script.js',
    content_type: 'script/javascript',
    data: 'window.onload(function() {})'
}]).create(function(err) {
 
});
Connector "couch-db"
db.destroy(function(err) {
    // create a new database 
    db.create(function(err) {
        // insert a document with id 'jack johns' 
        db.insert({ _id: 'jack johns', name: 'jack' }, function(err, body) {
            if (err) {
                console.log('insertion failed ', err.message);
                return;
            }
            console.log(body);
            // body will like following: 
            //   { ok: true, 
            //     id: 'jack johns', 
            //     rev: '1-610953b93b8bf1bae12427e2de181307' } 
        });
    });
});

This declaration will create a useUpdateLink from code to the database "myDatabase".

var doc = db.testdb.doc({});
// open to get revision or assign revision to the document 
doc.open(function(err) {
    doc.attach('plain.css', 'body { font-size:12pt; }', 'text/css');
    // save the doc 
    doc.save(function(err, rs) {
        var plain = doc.attachment('plain.txt');
        // retrieve attachment 
        plain.get(function(err, body) {
            assert.equal(body, 'body { font-size:12pt; }');
            // update 
            plain.update('body { font-size:14pt; }', 'text/css', function(err) {
                plain.get(function(err, body) {
                    assert.equal(body, 'body { font-size:14pt; }');
                });
            });
        });
    });

Rules

List of rules is available here:

https://technologies.castsoftware.com/rules?rlH=AIP/extensions/com.castsoftware.nodejs/versions/1.7.0-funcrel/quality-rules

Security Coverage

Node.js analyzer is able to analyze OWASP NodeGoat https://github.com/OWASP/NodeGoat and provide the following security checks.

 

Known Limitations

In this section we list the most significant functional limitations that may affect the analysis of applications using Node.js:

  • With regard to external links degraded mode, only statements with a FROM clause are correctly handled.