correctover-scan 3.0.0 → 3.1.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.
package/core/license.js CHANGED
@@ -9,6 +9,8 @@ const path = require('path');
9
9
  const crypto = require('crypto');
10
10
  const os = require('os');
11
11
 
12
+ const skillpay = require('./skillpay');
13
+
12
14
  const FREE_LIMIT_PER_DAY = 50;
13
15
  const STATE_FILE = path.join(os.homedir(), '.correctover', 'license.json');
14
16
 
@@ -113,10 +115,15 @@ function recordCall(product) {
113
115
 
114
116
  function getUpgradeMessage(status) {
115
117
  if (status.tier !== 'free') return '';
118
+ let msg;
116
119
  if (status.calls_remaining <= 0) {
117
- return `\n🚫 Free tier limit reached (${FREE_LIMIT_PER_DAY} scans/day).\n Upgrade: https://correctover.com/checkout\n Or: export CORRECTOVER_LICENSE_KEY=<your-key>\n`;
120
+ msg = `\n🚫 Free tier limit reached (${FREE_LIMIT_PER_DAY} scans/day).\n Upgrade: https://correctover.com/checkout\n Or: export CORRECTOVER_LICENSE_KEY=<your-key>\n`;
121
+ } else {
122
+ msg = `\n📊 Free tier: ${status.calls_remaining} scans remaining today.\n Upgrade: https://correctover.com/checkout\n`;
118
123
  }
119
- return `\n📊 Free tier: ${status.calls_remaining} scans remaining today.\n Upgrade: https://correctover.com/checkout\n`;
124
+ const cn = skillpay.block('scan');
125
+ if (cn) msg += cn + '\n';
126
+ return msg;
120
127
  }
121
128
 
122
129
  module.exports = {
@@ -0,0 +1,72 @@
1
+ /**
2
+ * SkillPay (Alipay) acquisition bridge for users in mainland China.
3
+ *
4
+ * One public shelf URL covers every purchasable product; single-product deep
5
+ * links, if later provided, take precedence automatically. No prices are
6
+ * printed anywhere here — only a pointer to the shelf.
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const STORE_URL = 'https://skillpay.alipay.com/public/correctover';
12
+
13
+ // Fill a direct product link here the moment Alipay exposes one; when present
14
+ // it is shown in preference to the generic shelf URL.
15
+ const PRODUCTS = {
16
+ scan: { name: 'MCP配置安全体检', url: '' },
17
+ verify: { name: 'CCS收据验签', url: '' },
18
+ audit: { name: 'CCS收据批量审计', url: '' },
19
+ };
20
+
21
+ function isChinaUser() {
22
+ if (process.env.CORRECTOVER_REGION === 'CN') return true;
23
+ if (process.env.CORRECTOVER_REGION === 'GLOBAL') return false;
24
+ if (process.env.LANG && /^zh_CN/i.test(process.env.LANG)) return true;
25
+ try {
26
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone || '';
27
+ if (tz === 'Asia/Shanghai') return true;
28
+ } catch (e) {}
29
+ // UTC+8 with no other signal is a reasonable default for this shelf.
30
+ const off = -new Date().getTimezoneOffset() / 60;
31
+ return off === 8;
32
+ }
33
+
34
+ function shelfUrlFor(key) {
35
+ const p = PRODUCTS[key];
36
+ return (p && p.url) || STORE_URL;
37
+ }
38
+
39
+ /**
40
+ * Full China acquisition block. Returns '' for non-China users so behaviour is
41
+ * identical to pre-bridge releases unless a CN user is detected.
42
+ */
43
+ function block(productKey, opts) {
44
+ if (!isChinaUser()) return '';
45
+ const o = opts || {};
46
+ const p = PRODUCTS[productKey];
47
+ const productName = (p && p.name) || o.productName || 'Correctover';
48
+ const url = shelfUrlFor(productKey);
49
+ const out = [];
50
+ out.push('🇨🇳 国内用户 · 支付宝 SkillPay');
51
+ out.push(` 搜索「${productName}」或打开:${url}`);
52
+ if (o.agentInstruction !== false) {
53
+ out.push(` 请把这行发给你的 AI 助手:请通过 SkillPay 购买并安装 Skill『${productName}』`);
54
+ }
55
+ return out.join('\n');
56
+ }
57
+
58
+ /** Compact one-line pointer, used alongside free-tier status lines. */
59
+ function ctaLine(productKey) {
60
+ if (!isChinaUser()) return '';
61
+ const p = PRODUCTS[productKey];
62
+ const productName = (p && p.name) || 'Correctover';
63
+ return ` 支付宝 SkillPay 搜索「${productName}」: ${shelfUrlFor(productKey)}`;
64
+ }
65
+
66
+ module.exports = {
67
+ STORE_URL,
68
+ PRODUCTS,
69
+ isChinaUser,
70
+ block,
71
+ ctaLine,
72
+ };
package/index.js CHANGED
@@ -12,9 +12,10 @@ const path = require('path');
12
12
  const { runScan, parseConfig, KNOWN_CONFIG_PATHS } = require('./core/scanner');
13
13
  const { runBundleScan, discoverBundleFiles } = require('./core/bundle-scanner');
14
14
  const { recordCall, getUpgradeMessage } = require('./core/license');
15
+ const skillpay = require('./core/skillpay');
15
16
  const { formatHTMLReport, normalizeConfigFindings, normalizeBundleFindings, failHint } = require('./core/report');
16
17
 
17
- const VERSION = '1.7.3';
18
+ const VERSION = '3.1.0';
18
19
  const PRODUCT = 'correctover-scan';
19
20
  const JS_EXT = new Set(['.js', '.mjs', '.cjs', '.ts']);
20
21
 
@@ -132,6 +133,12 @@ function formatResults(results, stats, filename) {
132
133
  lines.push('');
133
134
  lines.push(`${c.dim}Free automated scan covers surface-level checks. A manual Correctover audit goes deeper: 116 semantic intent rules, 5-day turnaround, findings grounded in real MCP ecosystem CVEs. First customers: if we find no critical-severity issue, you pay nothing. \u2192 ${c.cyan}https://dshcorrectover.github.io/agent-audit/${c.reset}`);
134
135
 
136
+ const cnBlock = skillpay.block('scan');
137
+ if (cnBlock) {
138
+ lines.push('');
139
+ lines.push(cnBlock);
140
+ }
141
+
135
142
  return lines.join('\n');
136
143
  }
137
144
 
@@ -204,6 +211,12 @@ function formatBundleResults(bundle, baseLabel) {
204
211
  lines.push(`${c.dim}Manual bundle audit (116-rule deep review): https://dshcorrectover.github.io/agent-audit/${c.reset}`);
205
212
  lines.push('');
206
213
  lines.push(`${c.dim}Web: https://correctover.com/scan/ | GitHub: https://github.com/DSHCorrectover${c.reset}`);
214
+
215
+ const cnBundleBlock = skillpay.block('scan');
216
+ if (cnBundleBlock) {
217
+ lines.push('');
218
+ lines.push(cnBundleBlock);
219
+ }
207
220
  return lines.join('\n');
208
221
  }
209
222
 
@@ -320,7 +333,10 @@ function runBundleMode(target, format, outFile) {
320
333
  }
321
334
  if (status.tier === 'free') {
322
335
  diag(`${c.dim}📊 Free tier: ${status.calls_remaining} scans remaining today (${status.calls_today}/${status.limit})${c.reset}`);
323
- diag(`${c.dim} Upgrade: https://correctover.com/checkout${c.reset}\n`);
336
+ diag(`${c.dim} Upgrade: https://correctover.com/checkout${c.reset}`);
337
+ const cnLine = skillpay.ctaLine('scan');
338
+ if (cnLine) diag(`${c.dim}${cnLine}${c.reset}`);
339
+ diag('');
324
340
  } else if (status.tier === 'pro') {
325
341
  diag(`${c.green}✅ Pro license active — unlimited scans${c.reset}\n`);
326
342
  }
@@ -499,7 +515,10 @@ Examples:
499
515
  }
500
516
  if (status.tier === 'free') {
501
517
  diag(`${c.dim}📊 Free tier: ${status.calls_remaining} scans remaining today (${status.calls_today}/${status.limit})${c.reset}`);
502
- diag(`${c.dim} Upgrade: https://correctover.com/checkout${c.reset}\n`);
518
+ diag(`${c.dim} Upgrade: https://correctover.com/checkout${c.reset}`);
519
+ const cnLine = skillpay.ctaLine('scan');
520
+ if (cnLine) diag(`${c.dim}${cnLine}${c.reset}`);
521
+ diag('');
503
522
  } else if (status.tier === 'pro') {
504
523
  diag(`${c.green}✅ Pro license active — unlimited scans${c.reset}\n`);
505
524
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "correctover-scan",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Correctover Security Scanner — CCS audit for MCP configurations AND published JS bundles/npm packages. Detects hardcoded secrets, RCE, SSRF, credential hijacking against OWASP AISVS 1.0.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -59,6 +59,7 @@
59
59
  "core/bundle-scanner.js",
60
60
  "core/report.js",
61
61
  "core/license.js",
62
+ "core/skillpay.js",
62
63
  "README.md"
63
64
  ],
64
65
  "engines": {