Skip to content
This repository was archived by the owner on Mar 31, 2025. It is now read-only.

Commit 18a1c0b

Browse files
fix(*): remove shelljs dependency
Using `shelljs.exec()` has been flagged as a security issue, so this commit removes it as a dependency and uses `child_process.spanSync()` instead.
1 parent 16ceb9c commit 18a1c0b

File tree

7 files changed

+49
-51
lines changed

7 files changed

+49
-51
lines changed

git/mocks/mocks.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ var mockGitDescribe = {
5757
stdout: 'v0.10.15'
5858
};
5959

60-
var mockShellDefault = {
60+
var mockDefaultFail = {
6161
code: 1,
6262
stdout: "default"
6363
};
@@ -84,5 +84,5 @@ module.exports = {
8484
mockGitDescribe: mockGitDescribe,
8585
mockGitLsRemoteTags: mockGitLsRemoteTags,
8686
mockGitRevParse: mockGitRevParse,
87-
mockShellDefault: mockShellDefault
87+
mockDefaultFail: mockDefaultFail
8888
};

git/services/getPreviousVersions.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var shell = require('shelljs');
3+
var child = require('child_process');
44
var _ = require('lodash');
55
var semver = require('semver');
66

@@ -15,9 +15,8 @@ module.exports = function getPreviousVersions(decorateVersion, packageInfo) {
1515
// not contain all commits when cloned with git clone --depth=...
1616
// Needed e.g. for Travis
1717
var repo_url = packageInfo.repository.url;
18-
var tagResults = shell.exec('git ls-remote --tags ' + repo_url,
19-
{silent: true});
20-
if (tagResults.code === 0) {
18+
var tagResults = child.spawnSync('git', ['ls-remote', '--tags', repo_url], {encoding: 'utf8'});
19+
if (tagResults.status === 0) {
2120
return _(tagResults.stdout.match(/v[0-9].*[0-9]$/mg))
2221
.map(function(tag) {
2322
var version = semver.parse(tag);

git/services/getPreviousVersions.spec.js

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ var mocks = require('../mocks/mocks.js');
77
var mockPackageFactory = require('../mocks/mockPackage');
88

99
describe("getPreviousVersions", function() {
10-
var getPreviousVersions, shell;
10+
var getPreviousVersions, child;
1111

1212
beforeEach(function() {
13-
shell = getPreviousVersionsFactory.__get__('shell');
13+
child = getPreviousVersionsFactory.__get__('child');
1414

1515
var mockPackage = mockPackageFactory()
1616
.factory(getPreviousVersionsFactory);
@@ -22,59 +22,59 @@ describe("getPreviousVersions", function() {
2222
});
2323

2424
it("should have called exec", function() {
25-
spyOn(shell, 'exec').and.returnValue({});
25+
spyOn(child, 'spawnSync').and.returnValue({});
2626
getPreviousVersions();
27-
expect(shell.exec).toHaveBeenCalled();
27+
expect(child.spawnSync).toHaveBeenCalled();
2828
});
2929

3030
it("should return an empty list for no tags", function() {
31-
spyOn(shell, 'exec').and.returnValue({});
31+
spyOn(child, 'spawnSync').and.returnValue({});
3232
expect(getPreviousVersions()).toEqual([]);
3333
});
3434

3535
it("should return an array of semvers matching tags", function() {
36-
spyOn(shell, 'exec').and.returnValue({
37-
code: 0,
36+
spyOn(child, 'spawnSync').and.returnValue({
37+
status: 0,
3838
stdout: 'v0.1.1'
3939
});
4040
expect(getPreviousVersions()).toEqual([semver('v0.1.1')]);
4141
});
4242

4343
it("should match v0.1.1-rc1", function() {
44-
spyOn(shell, 'exec').and.returnValue({
45-
code: 0,
44+
spyOn(child, 'spawnSync').and.returnValue({
45+
status: 0,
4646
stdout: 'v0.1.1-rc1'
4747
});
4848
expect(getPreviousVersions()).toEqual([semver('v0.1.1-rc1')]);
4949
});
5050

5151
it("should not match v1.1.1.1", function() {
52-
spyOn(shell, 'exec').and.returnValue({
53-
code: 0,
52+
spyOn(child, 'spawnSync').and.returnValue({
53+
status: 0,
5454
stdout: 'v1.1.1.1'
5555
});
5656
expect(getPreviousVersions()).toEqual([]);
5757
});
5858

5959
it("should not match v1.1.1-rc", function() {
60-
spyOn(shell, 'exec').and.returnValue({
61-
code: 0,
60+
spyOn(child, 'spawnSync').and.returnValue({
61+
status: 0,
6262
stdout: 'v1.1.1-rc'
6363
});
6464
expect(getPreviousVersions()).toEqual([]);
6565
});
6666

6767
it("should match multiple semvers", function() {
68-
spyOn(shell, 'exec').and.returnValue({
69-
code: 0,
68+
spyOn(child, 'spawnSync').and.returnValue({
69+
status: 0,
7070
stdout: 'v0.1.1\nv0.1.2'
7171
});
7272
expect(getPreviousVersions()).toEqual([semver('v0.1.1'), semver('v0.1.2')]);
7373
});
7474

7575
it("should sort multiple semvers", function() {
76-
spyOn(shell, 'exec').and.returnValue({
77-
code: 0,
76+
spyOn(child, 'spawnSync').and.returnValue({
77+
status: 0,
7878
stdout: 'v0.1.1\nv0.1.1-rc1'
7979
});
8080
expect(getPreviousVersions()).toEqual([semver('v0.1.1-rc1'), semver('v0.1.1')]);
@@ -84,8 +84,8 @@ describe("getPreviousVersions", function() {
8484
it("should decorate all versions", function() {
8585
mocks.decorateVersion.calls.reset();
8686

87-
spyOn(shell, 'exec').and.returnValue({
88-
code: 0,
87+
spyOn(child, 'spawnSync').and.returnValue({
88+
status: 0,
8989
stdout: 'v0.1.1\nv0.1.2'
9090
});
9191
var versions = getPreviousVersions();

git/services/versionInfo.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var shell = require('shelljs');
3+
var child = require('child_process');
44
var semver = require('semver');
55
var _ = require('lodash');
66

@@ -27,7 +27,7 @@ var satisfiesVersion = function(version) {
2727
* @return {String} The codename if found, otherwise null/undefined
2828
*/
2929
var getCodeName = function(tagName) {
30-
var gitCatOutput = shell.exec('git cat-file -p ' + tagName, {silent:true}).stdout;
30+
var gitCatOutput = child.spawnSync('git', ['cat-file', '-p ' + tagName], {encoding:'utf8'}).stdout;
3131
var match = gitCatOutput.match(/^.*codename.*$/mg);
3232
var tagMessage = match && match[0];
3333
return tagMessage && tagMessage.match(/codename\((.*)\)/)[1];
@@ -38,15 +38,15 @@ var getCodeName = function(tagName) {
3838
* @return {String} The commit SHA
3939
*/
4040
function getCommitSHA() {
41-
return shell.exec('git rev-parse HEAD', {silent: true}).stdout.replace('\n', '');
41+
return child.spawnSync('git', ['rev-parse', 'HEAD'], {encoding:'utf8'}).stdout.replace('\n', '');
4242
}
4343

4444
/**
4545
* Compute a build segment for the version, from the Jenkins build number and current commit SHA
4646
* @return {String} The build segment of the version
4747
*/
4848
function getBuild() {
49-
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).stdout.replace('\n', '');
49+
var hash = child.spawnSync('git', ['rev-parse', '--short', 'HEAD'], {encoding:'utf8'}).stdout.replace('\n', '');
5050
return 'sha.' + hash;
5151
}
5252

@@ -56,7 +56,7 @@ function getBuild() {
5656
* @return {SemVer} The version or null
5757
*/
5858
var getTaggedVersion = function() {
59-
var gitTagResult = shell.exec('git describe --exact-match', {silent:true});
59+
var gitTagResult = child.spawnSync('git', ['describe', '--exact-match'], {encoding:'utf8'});
6060

6161
if (gitTagResult.code === 0) {
6262
var tag = gitTagResult.stdout.trim();
@@ -107,7 +107,7 @@ var getSnapshotVersion = function() {
107107
// last release was a non beta release. Increment the patch level to
108108
// indicate the next release that we will be doing.
109109
// E.g. last release was 1.3.0, then the snapshot will be
110-
// 1.3.1-build.1, which is lesser than 1.3.1 accorind the semver!
110+
// 1.3.1-build.1, which is lesser than 1.3.1 according to semver!
111111

112112
// If the last release was a beta release we don't update the
113113
// beta number by purpose, as otherwise the semver comparison

git/services/versionInfo.spec.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,28 @@ var versionInfoFactory = rewire('./versionInfo.js');
99

1010

1111
describe("versionInfo", function() {
12-
var versionInfo, mockPackage, shellMocks, ciBuild;
12+
var versionInfo, mockPackage, gitMocks, ciBuild;
1313

1414
beforeEach(function() {
1515
mocks.getPreviousVersions.calls.reset();
1616

17-
var shell = versionInfoFactory.__get__('shell');
17+
var child = versionInfoFactory.__get__('child');
1818

19-
shellMocks = {
19+
gitMocks = {
2020
rev: mocks.mockGitRevParse,
21-
describe: mocks.mockShellDefault,
22-
cat: mocks.mockShellDefault
21+
describe: mocks.mockDefaultFail,
22+
cat: mocks.mockDefaultFail
2323
};
2424

25-
spyOn(shell, 'exec').and.callFake(function (input) {
26-
if (input.indexOf('git rev-parse') == 0) {
27-
return shellMocks.rev;
28-
} else if (input.indexOf('git describe --exact-match') == 0) {
29-
return shellMocks.describe;
30-
} else if (input.indexOf('git cat-file') == 0) {
31-
return shellMocks.cat;
25+
spyOn(child, 'spawnSync').and.callFake(function (command, args) {
26+
if (args[0] === 'rev-parse') {
27+
return gitMocks.rev;
28+
} else if (args[0] === 'describe') {
29+
return gitMocks.describe;
30+
} else if (args[0] === 'cat-file') {
31+
return gitMocks.cat;
3232
} else {
33-
return mocks.mockShellDefault;
33+
return mocks.mockDefaultFail;
3434
}
3535
});
3636

@@ -138,8 +138,8 @@ describe("versionInfo", function() {
138138
describe("currentVersion with annotated tag", function() {
139139

140140
beforeEach(function() {
141-
shellMocks.cat = mocks.mockGitCatFile;
142-
shellMocks.describe = mocks.mockGitDescribe;
141+
gitMocks.cat = mocks.mockGitCatFile;
142+
gitMocks.describe = mocks.mockGitDescribe;
143143

144144
versionInfo = versionInfoFactory(
145145
function() {},
@@ -148,7 +148,7 @@ describe("versionInfo", function() {
148148
});
149149

150150
it("should have a version matching the tag", function() {
151-
var tag = shellMocks.describe.stdout.trim();
151+
var tag = gitMocks.describe.stdout.trim();
152152
var version = semver.parse(tag);
153153
expect(versionInfo.currentVersion.version).toBe(version.version);
154154
});
@@ -158,7 +158,7 @@ describe("versionInfo", function() {
158158
});
159159

160160
it("should set codeName to null if it doesn't have a codename specified", function() {
161-
shellMocks.cat = mocks.mockGitCatFileNoCodeName;
161+
gitMocks.cat = mocks.mockGitCatFileNoCodeName;
162162

163163
var dgeni = new Dgeni([mockPackage]);
164164
var injector = dgeni.configureInjector();
@@ -167,7 +167,7 @@ describe("versionInfo", function() {
167167
});
168168

169169
it("should set codeName to falsy if it has a badly formatted codename", function() {
170-
shellMocks.cat = mocks.mockGitCatFileBadFormat;
170+
gitMocks.cat = mocks.mockGitCatFileBadFormat;
171171

172172
var dgeni = new Dgeni([mockPackage]);
173173
var injector = dgeni.configureInjector();

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
"nunjucks": "^3.1.6",
5656
"rehype": "^8.0.0",
5757
"semver": "^5.2.0",
58-
"shelljs": "^0.7.0",
5958
"source-map-support": "^0.4.15",
6059
"spdx-license-list": "^2.1.0",
6160
"stringmap": "^0.2.2",

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1924,7 +1924,7 @@ set-value@^2.0.0:
19241924
is-plain-object "^2.0.3"
19251925
split-string "^3.0.1"
19261926

1927-
shelljs@^0.7.0, shelljs@^0.7.4:
1927+
shelljs@^0.7.4:
19281928
version "0.7.8"
19291929
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
19301930
integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM=

0 commit comments

Comments
 (0)