Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Architect is a simple plugin system useful for writing large node.js applications.
Some key features are:
With this system, plugin authors can focus on doing one thing and doing it well. The sysadmin can focus on the architecture of the system through the app config. And Architect will handle connecting everything together automatically.
The best way to explain plugins is to provide an example. We'll start out with a simple HTTP plugin that provides an http
service. It will have a service API that can be used to register HTTP route handlers.
var http = require('http');
// This is the standard plugin interface signature
module.exports = function startup(options, imports, register) {
var port = options.port || 8080;
var host = options.host || "0.0.0.0";
// Store our internal route table.
var routes = {};
// A very minimal request router
function onRequest(req, res) {
if (routes.hasOwnProperty(req.url)) {
return routes[req.url](req, res);
}
res.statusCode = 404;
res.end();
}
// Start the http server.
http.createServer(onRequest).listen(port, host, onListening);
function onListening() {
// Register our service and tell architect this plugin is ready
register(null, {
// Other plugins can use the the http.setRoute service
http: {
setRoute: function (url, handler, callback) {
routes[url] = handler;
callback();
}
}
});
}
};
Notice that we didn't use the imports
parameter. That's for plugins that consume services.
Every plugin needs a package.json to declare it's plugin properties. This can be the same package.json you use for npm if this plugin is to be published on npm.
{
"name": "http-server",
"version": "0.0.1",
"main": "http.js",
"private": true,
"plugin": {
"provides": ["http"]
}
}
Notice that the API function setRoute
has a callback at the end. This is so that the plugin consuming this API can know that setRoute finished. Remember that the client isn't always in the same process so these calls can be async.
Now we'll write a simple plugin that registers a route.
var fs = require('fs');
module.exports = function startup(options, imports, register) {
// This is a simple http handler that serves the static file.
function onIndex(req, res) {
var data = fs.createReadStream("index.html");
res.writeHead(200, {
"Content-Type": "text/html"
});
data.pipe(res);
}
// Register the route using the http service.
imports.http.setRoute("/", onIndex, register);
};
Here we used the imports
parameter to get at the http
service provided by the first plugin. All plugins need to call register
when they are done even if they don't provide any services. Here we simply chained the callback from setRoute
. Once the route is setup we're done!
The json file would look like:
{
"name": "index-page",
"version": "0.0.1",
"main": "index.js",
"private": true,
"plugin": {
"consumes": ["http"]
}
}
This lets architect know that when the index-page
plugin is loaded, it first needs to start the plugin that provides the http service.
If you're worried about service names conflicting, there is a feature where you can alias the service names in the app config.
Ok, now you're asking how architect knew to load the http plugin first so that the index plugin could use it right? Well the core of an architect app is the config file. Actually an app is nothing more than a set of plugins and one or more plugin config files. The plugin config file specifies what plugins to use and what options to send them.
Going with our previous example, let's create a simple config that only has one process and two plugins, http-server
and index-page
.
The config file can be JSON or JS (or even coffeescript if you have it), it will be loaded by node's require
, so same rules as that.
module.exports = {
containers: {
master: {
plugins: [
{ packagePath: "./plugins/http-server", port: 8080 },
"./plugins/index-page"
]
}
}
};
If the plugin has any config options, put the require path to the plugin as packagePath and other properties to be sent to the plugin. For the index-page
plugin we don't have any parameters so we can just use the string shortcut.
Note that these paths are relative to the config file as if the config file did the require. This follows normal node require paths otherwise. You can install plugins via npm, put them manually in a node_modules
folder, or use relative paths like I did here.
Now that we have two plugins and a plugin config we can create a real app using the architect system. Assuming you installed architect with npm, the following could work:
var architect = require("architect");
architect.createApp("simple-config.js", function (err, app) {
if (err) throw err;
console.log("Started the App!");
});
Our tree would look like:
.
├── app.js
├── plugins
│ ├── http-server
│ │ ├── http.js
│ │ └── package.json
│ └── index-page
│ ├── index.js
│ └── package.json
└── simple-config.js
And we would start the server with:
node app.js
Clearly you would never use this system for such a simple application. For a slightly more advanced example, see the everything example in the demos folder. It contains two configs default and simple. One simple that puts everything in the same process, and a more advanced one that shards the plugins manually across several processes. The plugins work the same on both!
Asynchronous register
If you have a plugin that needs to hold up the registration process for more than 5 seconds use an asynchronous register. Make sure you eventually return or architect will hang!
register(function(register) {
// Take more than 5 seconds.
register(err, null);
});
FAQs
A Simple yet powerful plugin system for node applications
The npm package architect receives a total of 924 weekly downloads. As such, architect popularity was classified as not popular.
We found that architect demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.