most-box 0.0.1 → 0.0.2

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.
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path'
2
2
  import fs from 'node:fs'
3
+ import crypto from 'node:crypto'
3
4
 
4
5
  import { MAX_FILE_SIZE } from '../config.js'
5
6
 
@@ -8,9 +9,9 @@ const DANGEROUS_PREFIXES = /^[\s.]+|[\s.]+$/
8
9
  const RESERVED_NAMES = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])$/i
9
10
 
10
11
  /**
11
- * Sanitize filename to prevent security issues
12
- * @param {string} filename - Original filename
13
- * @returns {string} - Sanitized filename
12
+ * 清理文件名以防止安全问题
13
+ * @param {string} filename - 原始文件名
14
+ * @returns {string} - 清理后的文件名
14
15
  */
15
16
  export function sanitizeFilename(filename) {
16
17
  if (typeof filename !== 'string') {
@@ -19,25 +20,27 @@ export function sanitizeFilename(filename) {
19
20
 
20
21
  let sanitized = filename
21
22
 
22
- // Normalize backslashes to forward slashes (S3-style folder paths)
23
+ // 将反斜杠规范化为正斜杠(S3 风格路径)
23
24
  sanitized = sanitized.replace(/\\/g, '/')
24
25
 
25
- // Remove dangerous characters but preserve / for folder paths
26
+ // 移除危险字符但保留 / 以支持文件夹路径
26
27
  sanitized = sanitized.replace(/[<>:"|?*\x00-\x1f]/g, '_')
27
28
 
28
- // Remove dangerous prefixes/suffixes
29
+ // 移除危险前缀/后缀
29
30
  sanitized = sanitized.replace(DANGEROUS_PREFIXES, '')
30
31
 
31
- // Prevent path traversal
32
- sanitized = sanitized.replace(/\.\./g, '_')
32
+ // 防止路径遍历
33
+ while (sanitized.includes('..')) {
34
+ sanitized = sanitized.replace(/\.\./g, '_')
35
+ }
33
36
 
34
- // Normalize multiple consecutive slashes
37
+ // 规范多个连续斜杠
35
38
  sanitized = sanitized.replace(/\/{2,}/g, '/')
36
39
 
37
- // Remove leading/trailing slashes
40
+ // 移除首尾斜杠
38
41
  sanitized = sanitized.replace(/^\/+|\/+$/g, '')
39
42
 
40
- // Sanitize each path segment individually
43
+ // 单独清理每个路径段
41
44
  const segments = sanitized.split('/')
42
45
  const safeSegments = segments.map(seg => {
43
46
  let safe = seg.replace(/[<>:"|?*]/g, '_')
@@ -54,10 +57,10 @@ export function sanitizeFilename(filename) {
54
57
  }
55
58
 
56
59
  /**
57
- * Validate and sanitize file path to prevent path traversal attacks
58
- * @param {string} inputPath - User input path
59
- * @param {object} options - Validation options
60
- * @param {string} [options.allowedBase] - Base directory that paths must be within (optional)
60
+ * 验证并清理文件路径以防止路径遍历攻击
61
+ * @param {string} inputPath - 用户输入路径
62
+ * @param {object} options - 验证选项
63
+ * @param {string} [options.allowedBase] - 路径必须在的基础目录(可选)
61
64
  * @returns {{ cleanPath: string, error?: string }}
62
65
  */
63
66
  export function validateAndSanitizePath(inputPath, options = {}) {
@@ -81,7 +84,7 @@ export function validateAndSanitizePath(inputPath, options = {}) {
81
84
  if (options.allowedBase) {
82
85
  const resolvedPath = path.resolve(cleanPath)
83
86
  const allowedBase = path.resolve(options.allowedBase)
84
- if (!resolvedPath.startsWith(allowedBase)) {
87
+ if (resolvedPath !== allowedBase && !resolvedPath.startsWith(allowedBase + path.sep)) {
85
88
  return { cleanPath: '', error: 'Path must be within allowed directory' }
86
89
  }
87
90
  }
@@ -90,9 +93,9 @@ export function validateAndSanitizePath(inputPath, options = {}) {
90
93
  }
91
94
 
92
95
  /**
93
- * Check if file size is within limits
94
- * @param {string} filePath - Path to file
95
- * @param {number} [maxSize] - Maximum allowed size in bytes (default: 100GB)
96
+ * 检查文件大小是否在限制内
97
+ * @param {string} filePath - 文件路径
98
+ * @param {number} [maxSize] - 最大允许大小(字节,默认 100GB
96
99
  * @returns {{ valid: boolean, size?: number, error?: string }}
97
100
  */
98
101
  export async function validateFileSize(filePath, maxSize = MAX_FILE_SIZE) {
@@ -123,8 +126,8 @@ export async function validateFileSize(filePath, maxSize = MAX_FILE_SIZE) {
123
126
  }
124
127
 
125
128
  /**
126
- * Check if directory is writable
127
- * @param {string} dirPath - Directory path to check
129
+ * 检查目录是否可写
130
+ * @param {string} dirPath - 要检查的目录路径
128
131
  * @returns {{ writable: boolean, error?: string }}
129
132
  */
130
133
  export async function checkDirectoryWritable(dirPath) {
@@ -133,7 +136,7 @@ export async function checkDirectoryWritable(dirPath) {
133
136
  fs.mkdirSync(dirPath, { recursive: true })
134
137
  }
135
138
 
136
- const testFile = path.join(dirPath, '.write-test-' + Date.now())
139
+ const testFile = path.join(dirPath, `.write-test-${crypto.randomUUID()}`)
137
140
  await fs.promises.writeFile(testFile, 'test')
138
141
  await fs.promises.unlink(testFile)
139
142
 
@@ -147,8 +150,8 @@ export async function checkDirectoryWritable(dirPath) {
147
150
  }
148
151
 
149
152
  /**
150
- * Get human-readable file size string
151
- * @param {number} bytes - Size in bytes
153
+ * 获取人类可读的文件大小字符串
154
+ * @param {number} bytes - 字节大小
152
155
  * @returns {string}
153
156
  */
154
157
  export function formatFileSize(bytes) {