前言

由于很久没有更新博客了,最近闲来无事发现主题更新了,顺便更新了一下博客主题,无意中想到应该修修BUG了,就跑了一遍npm audit,不跑不知道,一跑吓一跳。

29个漏洞让我强迫症瞬间发作。于是开始了修Bug之旅。

仔细观察所有信息之后,发现有24个漏洞都是源于年久失修的ga-analytics导致的。细细一看好家伙上次更新十年前。打开github 发现好多pull requests也没有被处理,看来项目基本属于报废状态。
奈何本人学硬件的,IT功底实在捉襟见肘,所以直接借助ChatGPT修了一波,在此记录一下。

删除文件

主要需要修改的文件结构如下:

1
2
3
4
5
6
7
8
9
10

Blog
├── package-lock.json
└── node_modules
└── ga-analytics
├── package-lock.json
├── package.json
├── module.js
└── node_modules

首先我们先删除一些中间文件和需要修改的内容。

  • 我们需要将Blog/package-lock.json删掉,不删除无法使用npm audit更新查看是否修复。
  • 接着我们需要将Blog/node_modules/ga-analytics/package-lock.json删掉, 防止重新安装依赖时无法更新。
  • 最后我们需要删除所有Blog/node_modules/ga-analytics/node_modules路径下载文件。我们会在修复完之后重新安装所有依赖。

查找并修改依赖版本

打开Blog/node_modules/ga-analytics/package.json之后,我们会发现如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

{
"name": "ga-analytics",
"version": "0.0.7",
"description": "Access Google Analytics reports via the command-line or node module",
"main": "module.js",
"bin": {
"ga-analytics": "bin/ga-analytics"
},
"repository": {
"type": "git",
"url": "https://github.com/sfarthin/ga-analytics.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Google Analytics",
"google",
"analytics",
"commandline"
],
"author": {
"name": "Steve Farthing",
"email": "me@stevefar.com",
"url": "https://stevefar.com"
},
"license": "MIT",
"dependencies": {
"cli-table": "^0.3.1",
"commander": "^2.5.0",
"googleapis": "^1.0.21",
"lodash": "^2.4.1",
"moment": "^2.8.4"
}
}

我们逐一打开检索依赖项发现版本都已经很久没有更新了。

cli-table

链接:cli-table
旧版本:0.3.1
新版本:0.3.11

commander

链接:commander
旧版本:2.5.0
新版本:12.1.0

googleapis

链接:googleapis
旧版本:1.0.21
新版本:140.0.1

lodash

链接:lodash
旧版本:2.4.1
新版本:4.17.21

moment

链接:moment
旧版本:2.8.4
新版本:2.30.1

修改后的文件效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

{
"name": "ga-analytics",
"version": "0.0.7",
"description": "Access Google Analytics reports via the command-line or node module",
"main": "module.js",
"bin": {
"ga-analytics": "bin/ga-analytics"
},
"repository": {
"type": "git",
"url": "https://github.com/sfarthin/ga-analytics.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Google Analytics",
"google",
"analytics",
"commandline"
],
"author": {
"name": "Steve Farthing",
"email": "me@stevefar.com",
"url": "https://stevefar.com"
},
"license": "MIT",
"dependencies": {
"cli-table": "^0.3.11",
"commander": "^12.1.0",
"googleapis": "^140.0.1",
"lodash": "^4.17.21",
"moment": "^2.30.1"
}
}

修改js代码

修改完依赖之后,js代码会直接报错,因为ga-analytics的代码太老了,很多新版本依赖的函数已经做出了很大的修改,所以我们要将 Blog/node_modules/ga-analytics/module.js文件中的代码做较大的修改。
整个过程就是在Terminal切换到 Blog/node_modules/ga-analytics/目录下,然后运行 npm install查看报错信息,复制粘贴给 CharGPT修改,以此往复。

最终文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

const { google } = require('googleapis');
const OAuth2 = google.auth.OAuth2;
const fs = require("fs");
const _ = require("lodash");
const moment = require("moment");

_.mixin({
compactObject: function (o) {
var clone = _.clone(o);
_.each(clone, function (v, k) {
if (!v) {
delete clone[k];
}
});
return clone;
},
});

module.exports = function (settings, final_callback) {
try {
var GOOGLEAPI_CLIENTID = settings.clientId ? settings.clientId : process.env.GOOGLEAPI_CLIENTID,
GOOGLEAPI_EMAIL = settings.serviceEmail ? settings.serviceEmail : process.env.GOOGLEAPI_EMAIL,
GOOGLEAPI_KEY = settings.key ? settings.key : process.env.GOOGLEAPI_KEY,
GOOGLEAPI_ANALYTICS_TABLE = settings.ids ? settings.ids : process.env.GOOGLEAPI_ANALYTICS_TABLE;

var sessionFile = process.env.TMPDIR + "ga-analytics-" + GOOGLEAPI_EMAIL.replace(/[^a-zA-Z\-]/gi, "_");

if (!GOOGLEAPI_CLIENTID || !GOOGLEAPI_EMAIL || !GOOGLEAPI_KEY || !GOOGLEAPI_ANALYTICS_TABLE) throw "Missing";
} catch (e) {
var error =
"\n A valid client id, service email, key, and table are required" +
"\n\n OAuth Client id: " + settings.clientId +
"\n Service Email: " + settings.serviceEmail +
"\n Path to Private Key: " + settings.key +
"\n Google Analytics view: " + GOOGLEAPI_ANALYTICS_TABLE;

final_callback(new Error(error));
return;
}

if (!settings.startDate)
settings.startDate = moment().subtract(moment.duration(1, "M")).format("YYYY-MM-DD");

if (!settings.endDate)
settings.endDate = moment(settings.startDate).add(moment.duration(1, "M")).format("YYYY-MM-DD");

// Create OAuth2 and JWT clients
const oauth2Client = new OAuth2(GOOGLEAPI_CLIENTID, null, "postmessage");
const jwt = new google.auth.JWT(GOOGLEAPI_EMAIL, GOOGLEAPI_KEY, null, [
"https://www.googleapis.com/auth/analytics.readonly",
]);

// Authorize with the JWT client
const authorize = function (callback) {
fs.exists(sessionFile, function (exists) {
if (exists) {
fs.readFile(sessionFile, function (err, res) {
if (err) {
jwt.authorize(callback);
return;
}

try {
var json = JSON.parse(res);
} catch (e) {
jwt.authorize(callback);
return;
}

if (new Date(json.expiry_date) > Date.now()) {
callback(null, json);
} else {
jwt.authorize(callback);
}
});
} else {
jwt.authorize(callback);
}
});
};

authorize(function (err, result) {
if (err) {
final_callback(err);
return;
}

fs.writeFile(sessionFile, JSON.stringify(result), function (err) {
final_callback(err);
});

oauth2Client.setCredentials({
access_token: result.access_token,
refresh_token: result.refresh_token,
});

// Fetch data from Google Analytics API
google.analytics("v3").data.ga.get(
_.compactObject({
ids: GOOGLEAPI_ANALYTICS_TABLE,
"start-date": settings.startDate,
"end-date": settings.endDate,
metrics: settings.metrics,
filters: settings.filter,
dimensions: settings.dimensions,
"max-results": settings.max,
sort: settings.sort,
auth: oauth2Client,
}),
function (err, r) {
if (err) {
final_callback(err);
return;
}

final_callback(null, r);
}
);
});
};

修改完成之后,在 Blog/node_modules/ga-analytics/ 目录下运行 npm install 完成依赖的修改和安装。
之后再运行npx patch-package ga-analytics来本地保存应用修改。

返回到博客根目录之后运行一遍 npm audit查看是否修复漏洞。在此过程中应该会提示重建Lock文件。按照命令npm i --package-lock-only运行一下之后再次输入npm audit即可发现漏洞已经被修复了。

结束

之后就是编译博客产看是否生效。到此为止更新年久失修的ga-analytics已经更新完毕。