@whyour/qinglong 2.20.1-0 → 2.20.2-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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@whyour/qinglong",
3
3
  "packageManager": "pnpm@8.3.1",
4
- "version": "2.20.1-0",
4
+ "version": "2.20.2-0",
5
5
  "description": "Timed task management platform supporting Python3, JavaScript, Shell, Typescript",
6
6
  "repository": {
7
7
  "type": "git",
@@ -17,8 +17,25 @@ const store_1 = require("../shared/store");
17
17
  const auth_1 = require("../shared/auth");
18
18
  const path_1 = __importDefault(require("path"));
19
19
  exports.default = ({ app }) => {
20
+ // Security: Enable strict routing to prevent case-insensitive path bypass
21
+ app.set('case sensitive routing', true);
22
+ app.set('strict routing', true);
20
23
  app.set('trust proxy', 'loopback');
21
24
  app.use((0, cors_1.default)());
25
+ // Security: Path normalization middleware to prevent case variation attacks
26
+ app.use((req, res, next) => {
27
+ const originalPath = req.path;
28
+ const normalizedPath = originalPath.toLowerCase();
29
+ // Block requests with case variations on protected paths
30
+ if (originalPath !== normalizedPath &&
31
+ (normalizedPath.startsWith('/api/') || normalizedPath.startsWith('/open/'))) {
32
+ return res.status(400).json({
33
+ code: 400,
34
+ message: 'Invalid path format'
35
+ });
36
+ }
37
+ next();
38
+ });
22
39
  // Rewrite URLs to strip baseUrl prefix if configured
23
40
  // This allows the rest of the app to work without baseUrl awareness
24
41
  if (config_1.default.baseUrl) {
@@ -34,7 +51,7 @@ exports.default = ({ app }) => {
34
51
  secret: config_1.default.jwt.secret,
35
52
  algorithms: ['HS384'],
36
53
  }).unless({
37
- path: [...config_1.default.apiWhiteList, /^\/(?!api\/).*/],
54
+ path: [...config_1.default.apiWhiteList, /^(\/(?!api\/).*)$/i],
38
55
  }));
39
56
  app.use((req, res, next) => {
40
57
  if (!req.headers) {
@@ -48,16 +65,17 @@ exports.default = ({ app }) => {
48
65
  });
49
66
  app.use(async (req, res, next) => {
50
67
  var _a;
51
- if (!['/open/', '/api/'].some((x) => req.path.startsWith(x))) {
68
+ const pathLower = req.path.toLowerCase();
69
+ if (!['/open/', '/api/'].some((x) => pathLower.startsWith(x))) {
52
70
  return next();
53
71
  }
54
72
  const headerToken = (0, util_1.getToken)(req);
55
- if (req.path.startsWith('/open/')) {
73
+ if (pathLower.startsWith('/open/')) {
56
74
  const apps = await store_1.shareStore.getApps();
57
75
  const doc = (_a = apps === null || apps === void 0 ? void 0 : apps.filter((x) => { var _a; return (_a = x.tokens) === null || _a === void 0 ? void 0 : _a.find((y) => y.value === headerToken); })) === null || _a === void 0 ? void 0 : _a[0];
58
76
  if (doc && doc.tokens && doc.tokens.length > 0) {
59
77
  const currentToken = doc.tokens.find((x) => x.value === headerToken);
60
- const keyMatch = req.path.match(/\/open\/([a-z]+)\/*/);
78
+ const keyMatch = pathLower.match(/\/open\/([a-z]+)\/*/);
61
79
  const key = keyMatch && keyMatch[1];
62
80
  if (doc.scopes.includes(key) &&
63
81
  currentToken &&
@@ -84,7 +102,13 @@ exports.default = ({ app }) => {
84
102
  next(err);
85
103
  });
86
104
  app.use(async (req, res, next) => {
87
- if (!['/api/user/init', '/api/user/notification/init'].includes(req.path)) {
105
+ const pathLower = req.path.toLowerCase();
106
+ if (![
107
+ '/api/user/init',
108
+ '/api/user/notification/init',
109
+ '/open/user/init',
110
+ '/open/user/notification/init',
111
+ ].includes(req.path)) {
88
112
  return next();
89
113
  }
90
114
  const authInfo = (await store_1.shareStore.getAuthInfo()) || {};
package/version.yaml CHANGED
@@ -1,11 +1,6 @@
1
- version: 2.20.1
2
- changeLogLink: https://t.me/jiao_long/433
3
- publishTime: 2025-12-26 22:00
1
+ version: 2.20.2
2
+ changeLogLink: https://t.me/jiao_long/434
3
+ publishTime: 2026-03-01 1800
4
4
  changeLog: |
5
- 1. 修复获取依赖管理列表
6
- 2. notify.js 修复 TG_PROXY_AUTH 参数拼接
7
- 3. QLAPI.notify larkSecret 参数
8
- 4. 修复 cron parser 定时规则校验
9
- 5. 修复设置 baseUrl 后无法访问
10
- 6. 修复环境变量排序
11
- 7. 修复定时任务无法停止
5
+ 1. 修复 path 安全漏洞(重要)
6
+