Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dockerfilelint

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dockerfilelint - npm Package Compare versions

Comparing version 0.0.4 to 0.0.5

lib/messages.js

28

lib/checks.js

@@ -1,3 +0,1 @@

var commands = module.exports = {

@@ -9,3 +7,3 @@ expose_container_port_only: function(args) {

if (port.split(':').length > 1) {
result.push({name: 'expose_host_port', message: 'EXPOSE should only specify a container port, not a host port'});
result.push('expose_host_port');
}

@@ -26,3 +24,3 @@ });

if (label.split('=').length !== 2) {
result.push({name: 'label_invalid', message: 'LABEL command should contain one or more key=value pairs'});
result.push('label_invalid');
}

@@ -47,5 +45,5 @@ });

if (baseImage.length === 1) {
result.push({name: 'missing_tag', message: 'Base images should have a declared tag'});
result.push('missing_tag');
} else if (baseImage[1] === 'latest') {
result.push({name: 'latest_tag', message: 'Base images should use a pinned tag, not latest'});
result.push('latest_tag');
}

@@ -59,3 +57,3 @@

if (args.trim().match(/\S+/g).length != 1) {
result.push({name: 'extra_args', message: 'USER command should only include a single username'});
result.push('extra_args');
}

@@ -70,5 +68,5 @@

if (emails.length === 0) {
result.push({name: 'missing_args', message: 'MAINTAINER should include an email address'});
result.push('missing_args');
} else if (emails.length > 1) {
result.push({name: 'extra_args', message: 'MAINTAINER command should only include a single author'});
result.push('extra_args');
}

@@ -90,3 +88,3 @@

if (!commands.param_count_min(args, 2)) {
result.push({name: 'missing_args', message: 'ADD command found with less than 2 arguments.'});
result.push('missing_args');
}

@@ -102,3 +100,3 @@

if (!commands.is_dir_in_context(source)) {
result.push({name: 'add_src_invalid', message: 'ADD source locations must be local to the Docker build context.'});
result.push('add_src_invalid');
}

@@ -110,3 +108,3 @@ });

if (args.slice(-1)[0] !== '/') {
result.push({name: 'add_dest_invalid', message: 'When ADD source includes wildcards or multiple locations, dest must be a directory'});
result.push('add_dest_invalid');
}

@@ -127,3 +125,3 @@ }

if (args.match(/\S+/g).length > 1) {
result.push({name: 'invalid_workdir', message: 'WORKDIR cannot include spaces unless wrapped in quotes.'});
result.push('invalid_workdir');
}

@@ -157,6 +155,6 @@

if (!v.includes('=')) {
result.push({name: 'invalid_format', message: 'ENV should contain key=value'});
result.push('invalid_format');
}
if (v.match(/\S+/g).length > 1) {
result.push({name: 'invalid_format', message: 'Unquoted ENV should not contain whitespace'});
result.push('invalid_format');
}

@@ -163,0 +161,0 @@ });

@@ -5,2 +5,3 @@ 'use strict';

var run_checks = require('./run_checks');
var messages = require('./messages');

@@ -50,3 +51,3 @@ module.exports.run = function(content) {

cmdFound: false,
messages: []
items: []
}

@@ -56,3 +57,3 @@

var result = runLine(state, instructions, idx);
state.messages = state.messages.concat(result.messages);
state.items = state.items.concat(result.items);

@@ -68,8 +69,9 @@ // We care about only having 1 cmd instruction

return state.messages;
return state.items;
}
function runLine(state, instructions, idx) {
// return messages in an object with the line number as key, value is array of messages for this line
var messages = [];
// return items in an object with the line number as key, value is array of items for this line
var items = [];
var line = parseInt(idx) + 1;

@@ -79,3 +81,3 @@ // All Dockerfile commands require parameters, this is an error if not

if (instruction.trim().match(/\S+/g).length === 1) {
messages.push({line: parseInt(idx)+1, name: 'required_params', message: 'Command \'' + instruction + '\' without parameters'});
items.push(messages.build('required_params', line));
}

@@ -88,3 +90,3 @@

if (instruction.trim().match(/\S+/g)[0] !== cmd.toUpperCase()) {
messages.push({line: parseInt(idx)+1, name: 'uppercase_commands', message: 'Command \'' + instruction.trim().match(/\S+/g)[0] + '\' should be upper case'});
items.push(messages.build('uppercase_commands', line));
}

@@ -95,3 +97,3 @@

if ((state.instructionsProcessed === 0 && cmd !== 'from') || (state.instructionsProcessed !== 0 && cmd === 'from')) {
messages.push({line: parseInt(idx)+1, name: 'from_first', message: 'FROM command should be the first line in a Dockerfile.'});
items.push(messages.build('from_first', line));
}

@@ -103,3 +105,3 @@

if (!args) {
messages.push({line: parseInt(idx)+1, name: 'invalid_line', message: 'Line is invalid'});
items.push(messages.build('invalid_line', line));
}

@@ -111,3 +113,3 @@

if (arg.trim().toLowerCase() === 'sudo') {
messages.push({line: parseInt(idx)+1, name: 'sudo_usage', message: 'sudo usage is not allowed. Commands will run as sudo.'});
items.push(messages.build('sudo_usage', line));
}

@@ -119,9 +121,9 @@ }.bind(this));

case 'from':
checks.base_image_tag(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.base_image_tag(args).forEach(function(item) {
items.push(messages.build(item, line));
});
break;
case 'maintainer':
checks.valid_maintainer(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.valid_maintainer(args).forEach(function(item) {
items.push(messages.build(item, line));
});

@@ -136,3 +138,3 @@ break;

if (!run_checks.aptget_hasyes(aptget_command)) {
messages.push({line: parseInt(idx)+1, name: 'apt-get_missing_param', message: 'apt-get commands should include a -y flag'});
items.push(messages.build('apt-get_missing_param', line));
}

@@ -143,16 +145,16 @@ }

if (!run_checks.aptget_hasnorecommends(aptget_command)) {
messages.push({line: parseInt(idx)+1, name: 'apt-get_recommends', message: 'apt-get install commands should include a --no-install-recommends flag'});
items.push(messages.build('apt-get_recommends', line));
}
} else if (subcommand === 'update') {
if (!run_checks.includes_rmaptlists(args)) {
messages.push({line: parseInt(idx)+1, name: 'apt-get_missing_rm', message: 'apt-get update should include a matching /var/lib/apt/lists/*'})
items.push(messages.build('apt-get_missing_rm', line));
}
} else if (subcommand === 'upgrade') {
messages.push({line: parseInt(idx)+1, name: 'apt-get-upgrade', message: 'apt-get upgrade is not allowed'});
items.push(messages.build('apt-get-upgrade', line));
} else if (subcommand === 'dist-upgrade') {
messages.push({line: parseInt(idx)+1, name: 'apt-get-dist-upgrade', message: 'apt-get dist-upgrade is not allowed'});
items.push(messages.build('apt-get-dist-upgrade', line));
}
});
if ((subcommands.indexOf('update') > -1) && (subcommands.indexOf('install') === -1)) {
messages.push({line: parseInt(idx)+1, name: 'apt-get-update_require_install', message: 'apt-get update commands must be paired with apt-get install commands'});
items.push(messages.build('apt-get-update_require_install', line));
}

@@ -163,9 +165,9 @@ break;

case 'label':
checks.label_format(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.label_format(args).forEach(function(item) {
items.push(messages.build(item, line));
});
break;
case 'expose':
checks.expose_container_port_only(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.expose_container_port_only(args).forEach(function(item) {
items.push(messages.build(item, line));
});

@@ -175,3 +177,3 @@ args.match(/\S+/g).forEach(function(port) {

if (!port.includes(':')) { // Just eliminate a double message here
messages.push({line: parseInt(idx)+1, name: 'invalid_port', message: 'EXPOSE should be a valid port number'});
items,push(messages.build('invalid_port', line));
}

@@ -182,9 +184,9 @@ }

case 'env':
checks.is_valid_env(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.is_valid_env(args).forEach(function(item) {
items.push(messages.build(item, line));
});
break;
case 'add':
checks.is_valid_add(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.is_valid_add(args).forEach(function(item) {
items.push(messages.build(item, line));
});

@@ -199,9 +201,9 @@ break;

case 'user':
checks.valid_user(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.valid_user(args).forEach(function(item) {
items.push(messages.build(item, line));
});
break;
case 'workdir':
checks.is_valid_workdir(args).forEach(function(message) {
messages.push({line: parseInt(idx)+1, name: message.name, message: message.message});
checks.is_valid_workdir(args).forEach(function(item) {
items.push(messages.build(item, line));
});

@@ -216,3 +218,3 @@ break;

default:
messages.push({line: parseInt(idx)+1, name: 'invalid_command', message: 'Only supported Dockerfile commands are allowed'});
items.push(messages.build('invalid_command', line));
break;

@@ -224,4 +226,4 @@ }

command: cmd,
messages: messages
items: items
};
}
{
"name": "dockerfilelint",
"version": "0.0.4",
"version": "0.0.5",
"description": "A linter for Dockerfiles to find bugs and encourage best practices",

@@ -5,0 +5,0 @@ "main": "./lib/index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc