prscan 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/README.MD +32 -0
  3. package/dist/bot/lark.d.ts +2 -0
  4. package/dist/bot/lark.d.ts.map +1 -0
  5. package/dist/bot/lark.js +156 -0
  6. package/dist/bot/lark.js.map +1 -0
  7. package/dist/cli/cli.d.ts +2 -0
  8. package/dist/cli/cli.d.ts.map +1 -0
  9. package/dist/cli/cli.js +77 -0
  10. package/dist/cli/cli.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +46 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/report/index.d.ts +7 -0
  16. package/dist/report/index.d.ts.map +1 -0
  17. package/dist/report/index.js +45 -0
  18. package/dist/report/index.js.map +1 -0
  19. package/dist/tool/prscan.d.ts +72 -0
  20. package/dist/tool/prscan.d.ts.map +1 -0
  21. package/dist/tool/prscan.js +477 -0
  22. package/dist/tool/prscan.js.map +1 -0
  23. package/dist/util/analyze.d.ts +4 -0
  24. package/dist/util/analyze.d.ts.map +1 -0
  25. package/dist/util/analyze.js +213 -0
  26. package/dist/util/analyze.js.map +1 -0
  27. package/dist/util/archive.d.ts +34 -0
  28. package/dist/util/archive.d.ts.map +1 -0
  29. package/dist/util/archive.js +110 -0
  30. package/dist/util/archive.js.map +1 -0
  31. package/dist/util/memory-archive.d.ts +37 -0
  32. package/dist/util/memory-archive.d.ts.map +1 -0
  33. package/dist/util/memory-archive.js +128 -0
  34. package/dist/util/memory-archive.js.map +1 -0
  35. package/dist/util/npm.d.ts +46 -0
  36. package/dist/util/npm.d.ts.map +1 -0
  37. package/dist/util/npm.js +35 -0
  38. package/dist/util/npm.js.map +1 -0
  39. package/dist/util/parse.d.ts +18 -0
  40. package/dist/util/parse.d.ts.map +1 -0
  41. package/dist/util/parse.js +92 -0
  42. package/dist/util/parse.js.map +1 -0
  43. package/dist/util/proxy.d.ts +45 -0
  44. package/dist/util/proxy.d.ts.map +1 -0
  45. package/dist/util/proxy.js +143 -0
  46. package/dist/util/proxy.js.map +1 -0
  47. package/dist/util/repo.d.ts +103 -0
  48. package/dist/util/repo.d.ts.map +1 -0
  49. package/dist/util/repo.js +170 -0
  50. package/dist/util/repo.js.map +1 -0
  51. package/package.json +35 -0
  52. package/report.png +0 -0
  53. package/src/bot/lark.ts +184 -0
  54. package/src/cli/cli.ts +80 -0
  55. package/src/index.ts +67 -0
  56. package/src/report/index.ts +50 -0
  57. package/src/tool/prscan.ts +634 -0
  58. package/src/util/analyze.ts +248 -0
  59. package/src/util/memory-archive.ts +184 -0
  60. package/src/util/npm.ts +100 -0
  61. package/src/util/parse.ts +103 -0
  62. package/src/util/repo.ts +224 -0
  63. package/tsconfig.json +43 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "configurations": [
3
+ {
4
+ "name": "Launch Program",
5
+ "program": "${workspaceFolder}/dist/cli/cli.js",
6
+ "request": "launch",
7
+ "skipFiles": [
8
+ "<node_internals>/**"
9
+ ],
10
+ "type": "node",
11
+ "args": ["branch", "master", "feat-monad", "-r", "/Users/ru1n/proj/defi-insight-react"]
12
+ }
13
+ ]
14
+ }
package/README.MD ADDED
@@ -0,0 +1,32 @@
1
+ # NPM依赖检查
2
+ ## 检测规则
3
+ ### 使用最新且近期发布的NPM包
4
+ #### 描述
5
+ 如果使用的NPM包是最新版,且发布时间小于1个月,则报异常
6
+ #### 依据
7
+ 攻击者获取NPM包发布权限后,需要发布一个新NPM包以植入恶意代码,但安全社区往往能在一段时间内发现并发布安全通告
8
+
9
+ ### 访问危险的全局变量
10
+ #### 描述
11
+ 使用babel解析js文件,并提取出js文件访问的所有全局变量。对于操作DOM、发起网络请求的全局变量发出告警,需要手工检查这些敏感调用点是否正常
12
+ #### 依据
13
+ 从过往的恶意代码Payload来看,攻击者外带信息都是通过fetch,还没有做什么隐藏手段
14
+
15
+ ### 关键字检查
16
+ #### 描述
17
+ 如果js文件内出现 ethereum 等关键字,则直接告警
18
+ #### 依据
19
+ 非Crypto领域的NPM包不应该出现这类关键字,但从过往的恶意代码Payload看,有时会通过 ethereum 这一全局变量窃取信息
20
+
21
+ ## 使用
22
+ 目前支持PNPM, YARN等包管理工具,不支持处理默认的NPM包管理工具
23
+ ### CLI
24
+ #### 在本地GIT仓库内使用
25
+ 通过对比2个分支的差异,确定NPM依赖变更,并做扫描
26
+ ```shell
27
+ npx prscan branch <基础分支> <变更分支> -o <报告输出文件名, 默认输出到stdout> -r <仓库路径, 默认为当前路径>
28
+ ```
29
+ #### 在远程GitHub仓库使用
30
+ ```shell
31
+ npx prscan github <PR链接> -o <报告输出文件名, 默认输出到stdout> -t <GitHub TOKEN, 公开项目不需要>
32
+ ```
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lark.d.ts","sourceRoot":"","sources":["../../src/bot/lark.ts"],"names":[],"mappings":""}
@@ -0,0 +1,156 @@
1
+ // SDK 使用说明 SDK user guide:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/nodejs-sdk/preparation-before-development
2
+ import http from "http";
3
+ import * as lark from "@larksuiteoapi/node-sdk";
4
+ import { scanPRRisks } from "../tool/prscan.js";
5
+ import { makeReportInMd, md2Img } from "../report/index.js";
6
+ import * as fs from "fs";
7
+ import * as os from "os";
8
+ import * as path from "path";
9
+ const encryptKey = process.env.key;
10
+ const verificationToken = process.env.token;
11
+ const appId = process.env.id;
12
+ const appSecret = process.env.secret;
13
+ const bindPath = process.env.path || "/larkbot/event";
14
+ const port = process.env.port || 12345;
15
+ console.log("Lark Bot starting...");
16
+ console.log("App ID:", appId);
17
+ console.log("App Secret:", appSecret);
18
+ console.log("Encrypt Key:", encryptKey);
19
+ console.log("Verification Token:", verificationToken);
20
+ console.log("Event Path:", bindPath);
21
+ console.log("Listening on Port:", port);
22
+ const client = new lark.Client({
23
+ appId: appId ?? "",
24
+ appSecret: appSecret ?? "",
25
+ });
26
+ // 注册事件 Register event
27
+ const eventDispatcher = new lark.EventDispatcher({
28
+ logger: console,
29
+ loggerLevel: 5,
30
+ encryptKey: encryptKey ?? "",
31
+ verificationToken: verificationToken ?? "",
32
+ }).register({
33
+ "im.message.receive_v1": async (data) => {
34
+ if (data.message.message_type !== "text") {
35
+ client.im.message.reply({
36
+ path: {
37
+ message_id: data.message.message_id,
38
+ },
39
+ data: {
40
+ content: JSON.stringify({
41
+ text: "只支持文本消息,收到消息类型:" +
42
+ data.message.message_type,
43
+ }),
44
+ msg_type: "text",
45
+ },
46
+ });
47
+ return "success";
48
+ }
49
+ const msg = JSON.parse(data.message.content).text;
50
+ // 提取PR链接
51
+ const prRegex = /(https:\/\/github\.com\/[^\s\/]+\/[^\s\/]+\/pull\/\d+)/g;
52
+ const prLinks = msg.match(prRegex);
53
+ if (prLinks == null || prLinks.length === 0) {
54
+ client.im.message.reply({
55
+ path: {
56
+ message_id: data.message.message_id,
57
+ },
58
+ data: {
59
+ content: JSON.stringify({ text: "未提取到PR链接" }),
60
+ msg_type: "text",
61
+ },
62
+ });
63
+ return "success";
64
+ }
65
+ for (const prLink of prLinks) {
66
+ // 提取owner、repo、pr_number
67
+ const match = prLink.match(/https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/pull\/(\d+)/);
68
+ if (match) {
69
+ const owner = match[1];
70
+ const repo = match[2];
71
+ const prNumber = match[3];
72
+ scanPRRisks(owner, repo, prNumber)
73
+ .then((result) => {
74
+ const report = makeReportInMd(result);
75
+ client.im.message.reply({
76
+ path: {
77
+ message_id: data.message.message_id,
78
+ },
79
+ data: {
80
+ content: JSON.stringify({
81
+ zh_cn: {
82
+ title: `PR安全扫描结果 - ${owner}/${repo}#${prNumber}`,
83
+ content: [
84
+ [
85
+ {
86
+ tag: "text",
87
+ text: `摘要: ${report.abstract}\n详细结果见下图:`,
88
+ },
89
+ {
90
+ tag: "md",
91
+ text: report.report,
92
+ },
93
+ ],
94
+ ],
95
+ },
96
+ }),
97
+ msg_type: "post",
98
+ },
99
+ });
100
+ })
101
+ .catch((error) => {
102
+ client.im.message.reply({
103
+ path: {
104
+ message_id: data.message.message_id,
105
+ },
106
+ data: {
107
+ content: JSON.stringify({
108
+ text: `扫描PR ${prLink} 失败: ${error.message}`,
109
+ }),
110
+ msg_type: "text",
111
+ },
112
+ });
113
+ });
114
+ }
115
+ }
116
+ // console.log(data);
117
+ // client.im.message.reply({
118
+ // path: {
119
+ // message_id: data.message.message_id,
120
+ // },
121
+ // data: {
122
+ // content: JSON.stringify({"text": "收到消息:" + data.message.text}),
123
+ // msg_type: "text"
124
+ // }
125
+ // });
126
+ return "success";
127
+ },
128
+ });
129
+ const server = http.createServer();
130
+ // 创建路由处理器 Create route handler
131
+ server.on("request", lark.adaptDefault(bindPath, eventDispatcher, {
132
+ autoChallenge: true,
133
+ }));
134
+ server.listen(port);
135
+ function createReadStreamFromBuffer(buffer, options = {}) {
136
+ // 在系统临时目录创建文件
137
+ const tempDir = os.tmpdir();
138
+ const tempFile = path.join(tempDir, `buffer-stream-${Date.now()}-${Math.random().toString(36).substr(2)}`);
139
+ // 同步写入临时文件
140
+ fs.writeFileSync(tempFile, buffer);
141
+ // 创建 read stream
142
+ const readStream = fs.createReadStream(tempFile, options);
143
+ // 自动清理临时文件
144
+ const cleanup = () => {
145
+ fs.unlink(tempFile, (err) => {
146
+ if (err && err.code !== "ENOENT") {
147
+ console.error("清理临时文件失败:", err);
148
+ }
149
+ });
150
+ };
151
+ readStream.on("close", cleanup);
152
+ readStream.on("error", cleanup);
153
+ readStream.on("end", cleanup);
154
+ return readStream;
155
+ }
156
+ //# sourceMappingURL=lark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lark.js","sourceRoot":"","sources":["../../src/bot/lark.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ import { program } from "commander";
2
+ import { execSync } from "child_process";
3
+ import { scanByFileDiff, scanPRRisks } from "../tool/prscan.js";
4
+ import { writeFileSync } from "fs";
5
+ import { makeReportInMd } from "../report/index.js";
6
+ program
7
+ .command("branch")
8
+ .description("根据分支文件变更分析NPM依赖变更")
9
+ .argument("<base>", "基础分支")
10
+ .argument("<head>", "变更分支")
11
+ .option("-r, --repo <repo>", "仓库路径", ".")
12
+ .option("-o, --output <output>", "输出文件路径,若不指定则输出到控制台", "")
13
+ .action(async (base, head, options) => {
14
+ console.log(`分析 ${options.repo} 仓库从 ${base} 到 ${head} 的变更`);
15
+ const output = execSync(`git diff --name-only ${base} ${head}`, { cwd: options.repo }).toString();
16
+ const files = [];
17
+ for (let line of output.split("\n")) {
18
+ line = line.trim();
19
+ if (line.endsWith("yarn.lock")) {
20
+ console.log(` 发现变更: ${line}`);
21
+ }
22
+ else if (line.endsWith("pnpm-lock.yaml")) {
23
+ console.log(` 发现变更: ${line}`);
24
+ }
25
+ else if (line.endsWith("package-lock.json")) {
26
+ console.error(` 发现变更: ${line} (暂不支持分析package-lock.json)`);
27
+ continue;
28
+ }
29
+ else {
30
+ continue;
31
+ }
32
+ const file1 = execSync(`git show ${base}:${line}`, { cwd: options.repo }).toString();
33
+ const file2 = execSync(`git show ${head}:${line}`, { cwd: options.repo }).toString();
34
+ files.push({
35
+ filename: line,
36
+ oldContent: file1,
37
+ newContent: file2,
38
+ });
39
+ }
40
+ const sr = await scanByFileDiff(files);
41
+ const report = makeReportInMd(sr);
42
+ if (options.output.length > 0) {
43
+ writeFileSync(options.output, report.report, { encoding: "utf-8" });
44
+ console.log(`分析报告已写入 ${options.output}`);
45
+ }
46
+ else {
47
+ console.log(report.report);
48
+ }
49
+ });
50
+ program.command("github").description("根据GitHub Pull Request分析NPM依赖变更")
51
+ .argument("<link>", "Pull Request链接")
52
+ .option("-t, --token <token>", "GitHub访问令牌", "")
53
+ .option("-o, --output <output>", "输出文件路径,若不指定则输出到控制台", "")
54
+ .action(async (link, options) => {
55
+ console.log(`分析 Pull Request: ${link}`);
56
+ const match = link.match(/https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/pull\/(\d+)/);
57
+ if (match) {
58
+ const owner = match[1];
59
+ const repo = match[2];
60
+ const prNumber = match[3];
61
+ const sr = await scanPRRisks(owner, repo, parseInt(prNumber), options.token);
62
+ const report = makeReportInMd(sr);
63
+ if (options.output.length > 0) {
64
+ writeFileSync(options.output, report.report, { encoding: "utf-8" });
65
+ console.log(`分析报告已写入 ${options.output}`);
66
+ }
67
+ else {
68
+ console.log(report.report);
69
+ }
70
+ }
71
+ else {
72
+ console.error("无法解析Pull Request链接");
73
+ return;
74
+ }
75
+ });
76
+ program.parse();
77
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO;KACF,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,mBAAmB,CAAC;KAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1B,MAAM,CAAC,mBAAmB,EAAE,MAAM,EAAE,GAAG,CAAC;KACxC,MAAM,CAAC,uBAAuB,EAAE,oBAAoB,EAAE,EAAE,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,IAAY,EAAE,OAAyC,EAAE,EAAE;IACpF,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,QAAQ,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,wBAAwB,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClG,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,KAAK,CAAC,WAAW,IAAI,4BAA4B,CAAC,CAAC;YAC3D,SAAS;QACb,CAAC;aAAM,CAAC;YACJ,SAAS;QACb,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACrF,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACrF,KAAK,CAAC,IAAI,CAAC;YACP,QAAQ,EAAE,IAAI;YACd,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,KAAK;SACpB,CAAC,CAAC;IACP,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAE5B,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;AACL,CAAC,CAAC,CAAC;AAEP,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,gCAAgC,CAAC;KAClE,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KACpC,MAAM,CAAC,qBAAqB,EAAE,YAAY,EAAE,EAAE,CAAC;KAC/C,MAAM,CAAC,uBAAuB,EAAE,oBAAoB,EAAE,EAAE,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAA0C,EAAE,EAAE;IACvE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAChB,wDAAwD,CAC3D,CAAC;IACF,IAAI,KAAK,EAAE,CAAC;QACR,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAE1B,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,KAAM,EAAE,IAAK,EAAE,QAAQ,CAAC,QAAS,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,cAAc,CAAC,EAAG,CAAC,CAAC;QACnC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;IACL,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO;IACX,CAAC;AACT,CAAC,CAAC,CAAC;AAEP,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ import { Octokit } from "octokit";
2
+ import { GitHubRepo } from "./util/repo.js";
3
+ import { parseSyml } from '@yarnpkg/parsers';
4
+ import { YarnLockParser } from "./util/parse.js";
5
+ import { getNpmPackageInfo, getNpmPackageDownloadStats } from "./util/npm.js";
6
+ import { scanPRRisks } from "./tool/prscan.js";
7
+ import { makeReportInMd, md2Img } from "./report/index.js";
8
+ import { writeFileSync } from "node:fs";
9
+ // https://github.com/DeBankDeFi/defi-insight-react/pull/2323
10
+ const pr = await scanPRRisks("DeBankDeFi", "defi-insight-react", 2323, "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");
11
+ const r = makeReportInMd(pr);
12
+ const img = await md2Img(r.report);
13
+ if (img) {
14
+ writeFileSync("report.png", img);
15
+ }
16
+ console.log(r.abstract, "\n", r.report);
17
+ // 取消注释来测试
18
+ // await testNpmDownloads();
19
+ // const repo = new GitHubRepo("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");
20
+ // const prinfo = await repo.getPRInfo("RabbyHub", "rabby-mobile", 1082);
21
+ // const prfiles = await repo.getPRChangedFiles("RabbyHub", "rabby-mobile", 1082, 100);
22
+ // // console.log(prfiles);
23
+ // for (let i = 0; i < prfiles.length; i++) {
24
+ // const file = prfiles[i]!;
25
+ // if (file.filename !== "yarn.lock") {
26
+ // continue;
27
+ // }
28
+ // if (file.status !== "modified") {
29
+ // continue;
30
+ // }
31
+ // const content = await repo.getTextFileContent(
32
+ // "RabbyHub",
33
+ // "rabby-mobile",
34
+ // file.filename,
35
+ // prinfo.head.sha
36
+ // );
37
+ // if (content === null) {
38
+ // console.log("Failed to fetch file content");
39
+ // continue;
40
+ // }
41
+ // const parser = new YarnLockParser(content);
42
+ // const deps = parser.getDependencies();
43
+ // console.log(YarnLockParser.deps2Set(deps));
44
+ // debugger
45
+ // }
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,6DAA6D;AAE7D,MAAM,EAAE,GAAG,MAAM,WAAW,CACxB,YAAY,EACZ,oBAAoB,EACpB,IAAI,EACJ,+FAA+F,CAAC,CAAA;AAEpG,MAAM,CAAC,GAAG,cAAc,CAAC,EAAG,CAAC,CAAC;AAE9B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACnC,IAAI,GAAG,EAAE,CAAC;IACN,aAAa,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;AACrC,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;AAGxC,UAAU;AACV,4BAA4B;AAG5B,gIAAgI;AAEhI,yEAAyE;AAEzE,uFAAuF;AACvF,2BAA2B;AAE3B,6CAA6C;AAC7C,gCAAgC;AAEhC,2CAA2C;AAC3C,oBAAoB;AACpB,QAAQ;AAER,wCAAwC;AACxC,oBAAoB;AACpB,QAAQ;AAER,qDAAqD;AACrD,sBAAsB;AACtB,0BAA0B;AAC1B,yBAAyB;AACzB,0BAA0B;AAC1B,SAAS;AAET,8BAA8B;AAC9B,uDAAuD;AACvD,oBAAoB;AACpB,QAAQ;AAER,kDAAkD;AAClD,6CAA6C;AAC7C,kDAAkD;AAClD,eAAe;AACf,IAAI"}
@@ -0,0 +1,7 @@
1
+ import { type PRScanResult } from '../tool/prscan.js';
2
+ export declare function makeReportInMd(sr: PRScanResult): {
3
+ report: string;
4
+ abstract: string;
5
+ };
6
+ export declare function md2Img(md: string): Promise<Buffer | null>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,wBAAgB,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB,CAmCA;AAED,wBAAsB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM/D"}
@@ -0,0 +1,45 @@
1
+ import {} from '../tool/prscan.js';
2
+ import got from 'got';
3
+ export function makeReportInMd(sr) {
4
+ const risksCount = sr.changedDeps.reduce((acc, dep) => acc + dep.risks.length, 0);
5
+ let abstract = "共有 " + sr.changedDeps.length + " 个依赖变更, 包含 " + risksCount + " 个风险";
6
+ let md = "# PR扫描结果\n";
7
+ md += `## 依赖变更\n\n`;
8
+ if (sr.changedDeps.length === 0) {
9
+ md += "无依赖变更\n";
10
+ }
11
+ else {
12
+ md += "```\n";
13
+ md += "| 依赖 | 版本 | 风险 | 下载 | 周下载量 | 最新版 |\n";
14
+ md += "|:---- |:---- |:---- |:---- |:---- |:---- |\n";
15
+ const depSorted = sr.changedDeps.sort((a, b) => b.risks.length - a.risks.length);
16
+ for (const dep of depSorted) {
17
+ md += `| ${dep.name} | ${dep.version} | ${dep.risks.length} | ${dep.packageInfo.versions[dep.version].dist.tarball} | ${dep.downloadInfo.downloads} | ${dep.packageInfo["dist-tags"].latest} |\n`;
18
+ }
19
+ md += "\n```\n\n";
20
+ md += "\n## 详细风险信息\n\n";
21
+ for (const dep of depSorted) {
22
+ if (dep.risks.length === 0) {
23
+ continue;
24
+ }
25
+ md += `### ${dep.name} @ ${dep.version}\n\n`;
26
+ for (const risk of dep.risks) {
27
+ md += `- **【${risk.level === "low" ? "低危" : (risk.level === "medium" ? "中危" : "高危")}】** ${risk.desc}:\n\n\`\`\`\n${risk.info}\n\`\`\`\n\n`;
28
+ }
29
+ md += "\n";
30
+ }
31
+ }
32
+ return {
33
+ report: md,
34
+ abstract
35
+ };
36
+ }
37
+ export async function md2Img(md) {
38
+ try {
39
+ return (await got(`https://readpo.com/p/${encodeURIComponent(md)}`)).rawBody;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,MAAM,mBAAmB,CAAC;AACtD,OAAO,GAAG,MAAM,KAAK,CAAC;AAEtB,MAAM,UAAU,cAAc,CAAC,EAAgB;IAI3C,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAClF,IAAI,QAAQ,GAAG,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,GAAG,aAAa,GAAG,UAAU,GAAG,MAAM,CAAC;IAEnF,IAAI,EAAE,GAAG,YAAY,CAAC;IACtB,EAAE,IAAI,aAAa,CAAC;IACpB,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,EAAE,IAAI,SAAS,CAAC;IACpB,CAAC;SAAM,CAAC;QACJ,EAAE,IAAI,OAAO,CAAC;QACd,EAAE,IAAI,sCAAsC,CAAC;QAC7C,EAAE,IAAI,+CAA+C,CAAC;QACtD,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACjF,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC1B,EAAE,IAAI,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,MAAM,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,IAAI,CAAC,OAAO,MAAM,GAAG,CAAC,YAAY,CAAC,SAAS,MAAM,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,MAAM,CAAC;QACvM,CAAC;QACD,EAAE,IAAI,WAAW,CAAC;QAElB,EAAE,IAAI,iBAAiB,CAAC;QACxB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC1B,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,SAAS;YACb,CAAC;YACD,EAAE,IAAI,OAAO,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,MAAM,CAAC;YAC7C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBAC3B,EAAE,IAAI,QAAQ,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,gBAAgB,IAAI,CAAC,IAAI,cAAc,CAAC;YAC/I,CAAC;YACD,EAAE,IAAI,IAAI,CAAC;QACf,CAAC;IACL,CAAC;IAED,OAAO;QACH,MAAM,EAAE,EAAE;QACV,QAAQ;KACX,CAAA;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAAU;IACnC,IAAI,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
@@ -0,0 +1,72 @@
1
+ import { type GlobalUsageMap } from "../util/analyze.js";
2
+ import { type NpmDownloadStats, type NpmPackageInfo } from "../util/npm.js";
3
+ export interface RelatedPackage {
4
+ package: NpmPackageInfo;
5
+ downloadInfo: NpmDownloadStats;
6
+ }
7
+ export declare abstract class BaseRisk {
8
+ abstract desc: string;
9
+ abstract level: "low" | "medium" | "high";
10
+ package: RelatedPackage;
11
+ info: string;
12
+ constructor(pkg: RelatedPackage, info: string);
13
+ }
14
+ export declare class VersionRisk extends BaseRisk {
15
+ desc: string;
16
+ level: "low" | "medium" | "high";
17
+ static build(pkg: RelatedPackage, version: string): VersionRisk | null;
18
+ }
19
+ export declare class NotWidelyUsedRisk extends BaseRisk {
20
+ desc: string;
21
+ level: "low" | "medium" | "high";
22
+ static build(pkg: RelatedPackage): NotWidelyUsedRisk | null;
23
+ }
24
+ type RiskRecord = Record<string, {
25
+ perm: "r" | "rw";
26
+ type: "网络请求" | "操作DOM" | "动态执行代码" | "读取本地储存" | "访问chrome扩展API";
27
+ desc: string;
28
+ }>;
29
+ export declare class RiskyGlobalUsageRisk extends BaseRisk {
30
+ desc: string;
31
+ level: "low" | "medium" | "high";
32
+ globals: RiskRecord;
33
+ constructor(pkg: RelatedPackage, info: string, globals: RiskRecord);
34
+ static build(pkg: RelatedPackage, globals: Record<string, "r" | "rw">): RiskyGlobalUsageRisk | null;
35
+ }
36
+ export declare class ObfuscationRisk extends BaseRisk {
37
+ desc: string;
38
+ level: "low" | "medium" | "high";
39
+ static build(pkg: RelatedPackage, files: Record<string, string>): ObfuscationRisk | null;
40
+ }
41
+ export declare class RuleRisk extends BaseRisk {
42
+ desc: string;
43
+ level: "low" | "medium" | "high";
44
+ static build(pkg: RelatedPackage, files: Record<string, string>): RuleRisk | null;
45
+ }
46
+ export type Risk = VersionRisk | NotWidelyUsedRisk | RiskyGlobalUsageRisk | ObfuscationRisk | RuleRisk;
47
+ export interface PRScanResult {
48
+ changedDeps: Array<{
49
+ name: string;
50
+ version: string;
51
+ packageInfo: NpmPackageInfo;
52
+ downloadInfo: NpmDownloadStats;
53
+ analyze: {
54
+ global: GlobalUsageMap;
55
+ };
56
+ risks: Risk[];
57
+ }>;
58
+ }
59
+ export declare function scanPkgRisks(name: string, version: string): Promise<{
60
+ risks: Risk[];
61
+ package: NpmPackageInfo;
62
+ downloadInfo: NpmDownloadStats;
63
+ globalUsage: GlobalUsageMap;
64
+ }>;
65
+ export declare function scanByFileDiff(files: Array<{
66
+ filename: string;
67
+ oldContent: string;
68
+ newContent: string;
69
+ }>): Promise<PRScanResult>;
70
+ export declare function scanPRRisks(owner: string, repo: string, pull_no: number, auth?: string | undefined): Promise<PRScanResult | null>;
71
+ export {};
72
+ //# sourceMappingURL=prscan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prscan.d.ts","sourceRoot":"","sources":["../../src/tool/prscan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAGH,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACtB,MAAM,gBAAgB,CAAC;AAYxB,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,EAAE,gBAAgB,CAAC;CAClC;AAED,8BAAsB,QAAQ;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;gBAER,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM;CAIhD;AAED,qBAAa,WAAY,SAAQ,QAAQ;IAC9B,IAAI,EAAE,MAAM,CAAmB;IAC/B,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAS;IAEhD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;CAiCzE;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;IACpC,IAAI,EAAE,MAAM,CAAiB;IAC7B,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAY;IAEnD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,iBAAiB,GAAG,IAAI;CAS9D;AAED,KAAK,UAAU,GAAG,MAAM,CACpB,MAAM,EACN;IACI,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB,IAAI,EACE,MAAM,GACN,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CAChB,CACJ,CAAC;AACF,qBAAa,oBAAqB,SAAQ,QAAQ;IAC9C,IAAI,EAAE,MAAM,CAAgB;IAC5B,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAU;IAEnC,OAAO,EAAE,UAAU,CAAC;gBAEf,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IAKlE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC;CAoMxE;AAED,qBAAa,eAAgB,SAAQ,QAAQ;IAClC,IAAI,EAAE,MAAM,CAAY;IACxB,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAY;IAEnD,MAAM,CAAC,KAAK,CACR,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,eAAe,GAAG,IAAI;CAqB5B;AAED,qBAAa,QAAS,SAAQ,QAAQ;IAC3B,IAAI,EAAE,MAAM,CAAa;IACzB,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAS;IAEhD,MAAM,CAAC,KAAK,CACR,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,QAAQ,GAAG,IAAI;CAWrB;AAED,MAAM,MAAM,IAAI,GACV,WAAW,GACX,iBAAiB,GACjB,oBAAoB,GACpB,eAAe,GACf,QAAQ,CAAC;AAEf,MAAM,WAAW,YAAY;IACzB,WAAW,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,cAAc,CAAC;QAC5B,YAAY,EAAE,gBAAgB,CAAC;QAC/B,OAAO,EAAE;YACL,MAAM,EAAE,cAAc,CAAC;SAC1B,CAAC;QACF,KAAK,EAAE,IAAI,EAAE,CAAC;KACjB,CAAC,CAAC;CACN;AAED,wBAAsB,YAAY,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GAChB,OAAO,CAAC;IACP,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,WAAW,EAAE,cAAc,CAAC;CAC/B,CAAC,CAwFD;AAED,wBAAsB,cAAc,CAChC,KAAK,EAAE,KAAK,CAAC;IACT,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACtB,CAAC,yBA6CL;AAED,wBAAsB,WAAW,CAC7B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,GAAG,SAAqB,GACrC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAiG9B"}