exarch-rs 0.1.0 → 0.1.1
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/Cargo.toml +1 -0
- package/README.md +1 -1
- package/biome.json +47 -0
- package/exarch-rs.darwin-arm64.node +0 -0
- package/index.d.ts +551 -181
- package/index.js +588 -0
- package/package.json +25 -5
- package/src/config.rs +303 -47
- package/src/error.rs +42 -0
- package/src/lib.rs +553 -14
- package/src/report.rs +538 -0
- package/tests/create.test.js +124 -0
- package/tests/creation-config.test.js +97 -0
- package/tests/extract.test.js +118 -0
- package/tests/list-verify.test.js +148 -0
- package/tests/security-config.test.js +187 -0
package/index.d.ts
CHANGED
|
@@ -1,217 +1,377 @@
|
|
|
1
|
+
/* auto-generated by NAPI-RS */
|
|
2
|
+
/* eslint-disable */
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Provides secure archive extraction with built-in protection against:
|
|
5
|
-
* - Path traversal attacks
|
|
6
|
-
* - Symlink escape attacks
|
|
7
|
-
* - Hardlink escape attacks
|
|
8
|
-
* - Zip bomb attacks
|
|
9
|
-
* - Invalid file permissions
|
|
10
|
-
* - Resource quota violations
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Security configuration for archive extraction.
|
|
4
|
+
* Configuration for archive creation operations.
|
|
15
5
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* // Use secure defaults
|
|
21
|
-
* const config = new SecurityConfig();
|
|
6
|
+
* Controls how archives are created from filesystem sources, including
|
|
7
|
+
* security options, compression settings, and file filtering.
|
|
22
8
|
*
|
|
23
|
-
*
|
|
24
|
-
* const config = new SecurityConfig()
|
|
25
|
-
* .maxFileSize(100 * 1024 * 1024)
|
|
26
|
-
* .allowSymlinks(true);
|
|
9
|
+
* # Defaults
|
|
27
10
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
11
|
+
* | Setting | Default Value |
|
|
12
|
+
* |---------|--------------|
|
|
13
|
+
* | `compression_level` | 6 (balanced) |
|
|
14
|
+
* | `preserve_permissions` | true |
|
|
15
|
+
* | `follow_symlinks` | false (secure) |
|
|
16
|
+
* | `include_hidden` | false |
|
|
17
|
+
* | `max_file_size` | None (no limit) |
|
|
18
|
+
* | `exclude_patterns` | `[".git", ".DS_Store", "*.tmp"]` |
|
|
31
19
|
*/
|
|
32
|
-
export class
|
|
20
|
+
export declare class CreationConfig {
|
|
21
|
+
/** Creates a new `CreationConfig` with secure defaults. */
|
|
22
|
+
constructor()
|
|
33
23
|
/**
|
|
34
|
-
* Creates a
|
|
24
|
+
* Creates a `CreationConfig` with secure defaults.
|
|
25
|
+
*
|
|
26
|
+
* This is equivalent to calling `new CreationConfig()`.
|
|
35
27
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
static default(): CreationConfig
|
|
38
29
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
30
|
+
* Sets the compression level (1-9).
|
|
31
|
+
*
|
|
32
|
+
* Higher values provide better compression but slower speed.
|
|
33
|
+
* Default: 6 (balanced).
|
|
34
|
+
*
|
|
35
|
+
* # Errors
|
|
36
|
+
*
|
|
37
|
+
* Returns error if level is not in range 1-9.
|
|
41
38
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
setCompressionLevel(level: number): this
|
|
44
40
|
/**
|
|
45
|
-
*
|
|
41
|
+
* Sets whether to preserve file permissions from source.
|
|
46
42
|
*
|
|
47
|
-
*
|
|
48
|
-
* Use only for archives from trusted sources.
|
|
43
|
+
* Default: true.
|
|
49
44
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Builder pattern methods (chainable)
|
|
53
|
-
|
|
45
|
+
setPreservePermissions(preserve?: boolean | undefined | null): this
|
|
54
46
|
/**
|
|
55
|
-
* Sets
|
|
56
|
-
*
|
|
47
|
+
* Sets whether to follow symlinks when adding files.
|
|
48
|
+
*
|
|
49
|
+
* Default: false (store symlinks as symlinks).
|
|
50
|
+
*
|
|
51
|
+
* Security note: Following symlinks may include unintended files
|
|
52
|
+
* from outside the source directory.
|
|
57
53
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
setFollowSymlinks(follow?: boolean | undefined | null): this
|
|
60
55
|
/**
|
|
61
|
-
* Sets
|
|
62
|
-
* Default: 500 MB (524,288,000 bytes)
|
|
63
|
-
*/
|
|
64
|
-
maxTotalSize(size: number): this;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Sets the maximum compression ratio.
|
|
68
|
-
* Default: 100.0
|
|
56
|
+
* Sets whether to include hidden files (files starting with '.').
|
|
69
57
|
*
|
|
70
|
-
*
|
|
58
|
+
* Default: false.
|
|
71
59
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
setIncludeHidden(include?: boolean | undefined | null): this
|
|
74
61
|
/**
|
|
75
|
-
* Sets
|
|
76
|
-
*
|
|
62
|
+
* Sets maximum size for a single file in bytes.
|
|
63
|
+
*
|
|
64
|
+
* Files larger than this limit will be skipped.
|
|
65
|
+
*
|
|
66
|
+
* # Errors
|
|
67
|
+
*
|
|
68
|
+
* Returns error if size is negative.
|
|
77
69
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
setMaxFileSize(size: number): this
|
|
80
71
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
72
|
+
* Adds an exclude pattern.
|
|
73
|
+
*
|
|
74
|
+
* Files matching this pattern will be skipped.
|
|
75
|
+
*
|
|
76
|
+
* # Errors
|
|
77
|
+
*
|
|
78
|
+
* Returns error if pattern contains null bytes.
|
|
83
79
|
*/
|
|
84
|
-
|
|
80
|
+
addExcludePattern(pattern: string): this
|
|
81
|
+
/** Finalizes the configuration (for API consistency). */
|
|
82
|
+
build(): this
|
|
83
|
+
/** Compression level (1-9). */
|
|
84
|
+
get compressionLevel(): number | null
|
|
85
|
+
/** Whether to preserve permissions. */
|
|
86
|
+
get preservePermissions(): boolean
|
|
87
|
+
/** Whether to follow symlinks. */
|
|
88
|
+
get followSymlinks(): boolean
|
|
89
|
+
/** Whether to include hidden files. */
|
|
90
|
+
get includeHidden(): boolean
|
|
91
|
+
/** Maximum file size in bytes. */
|
|
92
|
+
get maxFileSize(): number | null
|
|
93
|
+
/** List of exclude patterns. */
|
|
94
|
+
get excludePatterns(): Array<string>
|
|
95
|
+
}
|
|
85
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Security configuration for archive extraction.
|
|
99
|
+
*
|
|
100
|
+
* All security features default to deny (secure-by-default policy).
|
|
101
|
+
*
|
|
102
|
+
* # Defaults
|
|
103
|
+
*
|
|
104
|
+
* | Setting | Default Value |
|
|
105
|
+
* |---------|--------------|
|
|
106
|
+
* | `max_file_size` | 50 MB (52,428,800 bytes) |
|
|
107
|
+
* | `max_total_size` | 500 MB (524,288,000 bytes) |
|
|
108
|
+
* | `max_compression_ratio` | 100.0 |
|
|
109
|
+
* | `max_file_count` | 10,000 |
|
|
110
|
+
* | `max_path_depth` | 32 |
|
|
111
|
+
* | `allow_symlinks` | false |
|
|
112
|
+
* | `allow_hardlinks` | false |
|
|
113
|
+
* | `allow_absolute_paths` | false |
|
|
114
|
+
* | `allow_world_writable` | false |
|
|
115
|
+
* | `preserve_permissions` | false |
|
|
116
|
+
* | `allowed_extensions` | empty (all allowed) |
|
|
117
|
+
* | `banned_path_components` | `.git`, `.ssh` |
|
|
118
|
+
*/
|
|
119
|
+
export declare class SecurityConfig {
|
|
120
|
+
/** Creates a new `SecurityConfig` with secure defaults. */
|
|
121
|
+
constructor()
|
|
86
122
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
123
|
+
* Creates a `SecurityConfig` with secure defaults.
|
|
124
|
+
*
|
|
125
|
+
* This is equivalent to calling `new SecurityConfig()`.
|
|
89
126
|
*/
|
|
90
|
-
|
|
91
|
-
|
|
127
|
+
static default(): SecurityConfig
|
|
92
128
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
129
|
+
* Creates a permissive configuration for trusted archives.
|
|
130
|
+
*
|
|
131
|
+
* Enables: symlinks, hardlinks, absolute paths, world-writable files.
|
|
132
|
+
* Use only for archives from trusted sources.
|
|
95
133
|
*/
|
|
96
|
-
|
|
97
|
-
|
|
134
|
+
static permissive(): SecurityConfig
|
|
98
135
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
136
|
+
* Sets the maximum file size in bytes.
|
|
137
|
+
*
|
|
138
|
+
* # Errors
|
|
139
|
+
*
|
|
140
|
+
* Returns error if size is negative.
|
|
101
141
|
*/
|
|
102
|
-
|
|
103
|
-
|
|
142
|
+
setMaxFileSize(size: number): this
|
|
104
143
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
144
|
+
* Sets the maximum total size in bytes.
|
|
145
|
+
*
|
|
146
|
+
* # Errors
|
|
147
|
+
*
|
|
148
|
+
* Returns error if size is negative.
|
|
107
149
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
150
|
+
setMaxTotalSize(size: number): this
|
|
110
151
|
/**
|
|
111
|
-
* Sets
|
|
112
|
-
*
|
|
152
|
+
* Sets the maximum compression ratio.
|
|
153
|
+
*
|
|
154
|
+
* # Errors
|
|
155
|
+
*
|
|
156
|
+
* Returns error if ratio is not a positive finite number.
|
|
113
157
|
*/
|
|
114
|
-
|
|
115
|
-
|
|
158
|
+
setMaxCompressionRatio(ratio: number): this
|
|
159
|
+
/** Sets the maximum file count. */
|
|
160
|
+
setMaxFileCount(count: number): this
|
|
161
|
+
/** Sets the maximum path depth. */
|
|
162
|
+
setMaxPathDepth(depth: number): this
|
|
163
|
+
/** Allows or denies symlinks. */
|
|
164
|
+
setAllowSymlinks(allow?: boolean | undefined | null): this
|
|
165
|
+
/** Allows or denies hardlinks. */
|
|
166
|
+
setAllowHardlinks(allow?: boolean | undefined | null): this
|
|
167
|
+
/** Allows or denies absolute paths. */
|
|
168
|
+
setAllowAbsolutePaths(allow?: boolean | undefined | null): this
|
|
169
|
+
/** Allows or denies world-writable files. */
|
|
170
|
+
setAllowWorldWritable(allow?: boolean | undefined | null): this
|
|
171
|
+
/** Sets whether to preserve permissions from archive. */
|
|
172
|
+
setPreservePermissions(preserve?: boolean | undefined | null): this
|
|
116
173
|
/**
|
|
117
174
|
* Adds an allowed file extension.
|
|
118
175
|
*
|
|
119
|
-
*
|
|
176
|
+
* # Errors
|
|
177
|
+
*
|
|
178
|
+
* Returns error if extension exceeds maximum length or contains null
|
|
179
|
+
* bytes.
|
|
120
180
|
*/
|
|
121
|
-
addAllowedExtension(ext: string): this
|
|
122
|
-
|
|
181
|
+
addAllowedExtension(ext: string): this
|
|
123
182
|
/**
|
|
124
183
|
* Adds a banned path component.
|
|
125
184
|
*
|
|
126
|
-
*
|
|
185
|
+
* # Errors
|
|
186
|
+
*
|
|
187
|
+
* Returns error if component exceeds maximum length or contains null
|
|
188
|
+
* bytes.
|
|
127
189
|
*/
|
|
128
|
-
addBannedComponent(component: string): this
|
|
129
|
-
|
|
190
|
+
addBannedComponent(component: string): this
|
|
130
191
|
/**
|
|
131
192
|
* Finalizes the configuration (for API consistency).
|
|
132
193
|
*
|
|
133
194
|
* This method is provided for builder pattern consistency but is optional.
|
|
134
195
|
* The configuration is always valid and can be used directly.
|
|
135
196
|
*/
|
|
136
|
-
build(): this
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
197
|
+
build(): this
|
|
198
|
+
/** Checks if a path component is allowed. */
|
|
199
|
+
isPathComponentAllowed(component: string): boolean
|
|
200
|
+
/** Checks if a file extension is allowed. */
|
|
201
|
+
isExtensionAllowed(extension: string): boolean
|
|
202
|
+
/** Maximum file size in bytes. */
|
|
203
|
+
get maxFileSize(): number
|
|
204
|
+
/** Maximum total size in bytes. */
|
|
205
|
+
get maxTotalSize(): number
|
|
206
|
+
/** Maximum compression ratio. */
|
|
207
|
+
get maxCompressionRatio(): number
|
|
208
|
+
/** Maximum file count. */
|
|
209
|
+
get maxFileCount(): number
|
|
210
|
+
/** Maximum path depth. */
|
|
211
|
+
get maxPathDepth(): number
|
|
212
|
+
/** Whether to preserve permissions from archive. */
|
|
213
|
+
get preservePermissions(): boolean
|
|
214
|
+
/** Whether symlinks are allowed. */
|
|
215
|
+
get allowSymlinks(): boolean
|
|
216
|
+
/** Whether hardlinks are allowed. */
|
|
217
|
+
get allowHardlinks(): boolean
|
|
218
|
+
/** Whether absolute paths are allowed. */
|
|
219
|
+
get allowAbsolutePaths(): boolean
|
|
220
|
+
/** Whether world-writable files are allowed. */
|
|
221
|
+
get allowWorldWritable(): boolean
|
|
140
222
|
/**
|
|
141
|
-
*
|
|
223
|
+
* List of allowed file extensions.
|
|
224
|
+
*
|
|
225
|
+
* Note: This getter clones the underlying data. For performance-critical
|
|
226
|
+
* code that only needs to count or check membership, use
|
|
227
|
+
* `getAllowedExtensionsCount()` or `hasAllowedExtension()` instead.
|
|
142
228
|
*/
|
|
143
|
-
|
|
144
|
-
|
|
229
|
+
get allowedExtensions(): Array<string>
|
|
230
|
+
/** Returns the number of allowed extensions. */
|
|
231
|
+
getAllowedExtensionsCount(): number
|
|
232
|
+
/** Checks if a specific extension is in the allowed list. */
|
|
233
|
+
hasAllowedExtension(ext: string): boolean
|
|
145
234
|
/**
|
|
146
|
-
*
|
|
235
|
+
* List of banned path components.
|
|
236
|
+
*
|
|
237
|
+
* Note: This getter clones the underlying data. For performance-critical
|
|
238
|
+
* code that only needs to count or check membership, use
|
|
239
|
+
* `getBannedPathComponentsCount()` or `hasBannedPathComponent()` instead.
|
|
147
240
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
readonly maxFileSize: number;
|
|
154
|
-
|
|
155
|
-
/** Maximum total extraction size in bytes */
|
|
156
|
-
readonly maxTotalSize: number;
|
|
157
|
-
|
|
158
|
-
/** Maximum compression ratio */
|
|
159
|
-
readonly maxCompressionRatio: number;
|
|
160
|
-
|
|
161
|
-
/** Maximum number of files */
|
|
162
|
-
readonly maxFileCount: number;
|
|
163
|
-
|
|
164
|
-
/** Maximum path depth */
|
|
165
|
-
readonly maxPathDepth: number;
|
|
166
|
-
|
|
167
|
-
/** Whether file permissions are preserved from archive */
|
|
168
|
-
readonly preservePermissions: boolean;
|
|
169
|
-
|
|
170
|
-
/** Whether symlinks are allowed */
|
|
171
|
-
readonly allowSymlinks: boolean;
|
|
172
|
-
|
|
173
|
-
/** Whether hardlinks are allowed */
|
|
174
|
-
readonly allowHardlinks: boolean;
|
|
175
|
-
|
|
176
|
-
/** Whether absolute paths are allowed */
|
|
177
|
-
readonly allowAbsolutePaths: boolean;
|
|
178
|
-
|
|
179
|
-
/** Whether world-writable files are allowed */
|
|
180
|
-
readonly allowWorldWritable: boolean;
|
|
181
|
-
|
|
182
|
-
/** List of allowed file extensions */
|
|
183
|
-
readonly allowedExtensions: string[];
|
|
184
|
-
|
|
185
|
-
/** List of banned path components */
|
|
186
|
-
readonly bannedPathComponents: string[];
|
|
241
|
+
get bannedPathComponents(): Array<string>
|
|
242
|
+
/** Returns the number of banned path components. */
|
|
243
|
+
getBannedPathComponentsCount(): number
|
|
244
|
+
/** Checks if a specific component is in the banned list. */
|
|
245
|
+
hasBannedPathComponent(component: string): boolean
|
|
187
246
|
}
|
|
188
247
|
|
|
189
248
|
/**
|
|
190
|
-
*
|
|
249
|
+
* Single entry in archive manifest.
|
|
191
250
|
*
|
|
192
|
-
* Contains
|
|
251
|
+
* Contains metadata about a file, directory, symlink, or hardlink
|
|
252
|
+
* without extracting it to disk.
|
|
193
253
|
*/
|
|
194
|
-
export interface
|
|
195
|
-
/**
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
|
|
254
|
+
export interface ArchiveEntry {
|
|
255
|
+
/** Entry path (relative, as stored in archive). */
|
|
256
|
+
path: string
|
|
257
|
+
/** Entry type ("File", "Directory", "Symlink", "Hardlink"). */
|
|
258
|
+
entryType: string
|
|
259
|
+
/** Uncompressed size in bytes (0 for directories). */
|
|
260
|
+
size: number
|
|
261
|
+
/** Compressed size in bytes (if available, ZIP only). */
|
|
262
|
+
compressedSize?: number
|
|
263
|
+
/** File permissions (Unix mode). */
|
|
264
|
+
mode?: number
|
|
265
|
+
/** Modification time (milliseconds since Unix epoch). */
|
|
266
|
+
modified?: number
|
|
267
|
+
/** Symlink target (if `entry_type` is "Symlink"). */
|
|
268
|
+
symlinkTarget?: string
|
|
269
|
+
/** Hardlink target (if `entry_type` is "Hardlink"). */
|
|
270
|
+
hardlinkTarget?: string
|
|
271
|
+
}
|
|
203
272
|
|
|
204
|
-
|
|
205
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Complete manifest of archive contents.
|
|
275
|
+
*
|
|
276
|
+
* Generated by `listArchive()`, contains metadata about all entries
|
|
277
|
+
* without extracting them to disk.
|
|
278
|
+
*/
|
|
279
|
+
export interface ArchiveManifest {
|
|
280
|
+
/** All entries in the archive (files, dirs, symlinks, hardlinks). */
|
|
281
|
+
entries: Array<ArchiveEntry>
|
|
282
|
+
/** Total number of entries. */
|
|
283
|
+
totalEntries: number
|
|
284
|
+
/** Total uncompressed size in bytes. */
|
|
285
|
+
totalSize: number
|
|
286
|
+
/** Archive format (e.g., `TarGz`, `Zip`). */
|
|
287
|
+
format: string
|
|
288
|
+
}
|
|
206
289
|
|
|
207
|
-
|
|
208
|
-
|
|
290
|
+
/**
|
|
291
|
+
* Create an archive from source files and directories (async).
|
|
292
|
+
*
|
|
293
|
+
* # Arguments
|
|
294
|
+
*
|
|
295
|
+
* * `output_path` - Path to output archive file
|
|
296
|
+
* * `sources` - Array of source files/directories to include
|
|
297
|
+
* * `config` - Optional `CreationConfig` (uses defaults if omitted)
|
|
298
|
+
*
|
|
299
|
+
* # Returns
|
|
300
|
+
*
|
|
301
|
+
* Promise resolving to `CreationReport` with creation statistics
|
|
302
|
+
*
|
|
303
|
+
* # Errors
|
|
304
|
+
*
|
|
305
|
+
* Returns error if path validation fails, archive creation fails, or I/O
|
|
306
|
+
* errors occur.
|
|
307
|
+
*
|
|
308
|
+
* # Examples
|
|
309
|
+
*
|
|
310
|
+
* ```javascript
|
|
311
|
+
* // Use defaults
|
|
312
|
+
* const report = await createArchive('output.tar.gz', ['source_dir/']);
|
|
313
|
+
* console.log(`Created archive with ${report.filesAdded} files`);
|
|
314
|
+
*
|
|
315
|
+
* // Customize configuration
|
|
316
|
+
* const config = new CreationConfig().compressionLevel(9);
|
|
317
|
+
* const report = await createArchive('output.tar.gz', ['src/'], config);
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
export declare function createArchive(outputPath: string, sources: Array<string>, config?: CreationConfig | undefined | null): Promise<CreationReport>
|
|
209
321
|
|
|
210
|
-
|
|
211
|
-
|
|
322
|
+
/**
|
|
323
|
+
* Create an archive from source files and directories (sync).
|
|
324
|
+
*
|
|
325
|
+
* Synchronous version of `createArchive`. Blocks the event loop until
|
|
326
|
+
* creation completes. Prefer the async version for most use cases.
|
|
327
|
+
*
|
|
328
|
+
* # Arguments
|
|
329
|
+
*
|
|
330
|
+
* * `output_path` - Path to output archive file
|
|
331
|
+
* * `sources` - Array of source files/directories to include
|
|
332
|
+
* * `config` - Optional `CreationConfig` (uses defaults if omitted)
|
|
333
|
+
*
|
|
334
|
+
* # Returns
|
|
335
|
+
*
|
|
336
|
+
* `CreationReport` with creation statistics
|
|
337
|
+
*
|
|
338
|
+
* # Errors
|
|
339
|
+
*
|
|
340
|
+
* Returns error if path validation fails, archive creation fails, or I/O
|
|
341
|
+
* errors occur.
|
|
342
|
+
*
|
|
343
|
+
* # Examples
|
|
344
|
+
*
|
|
345
|
+
* ```javascript
|
|
346
|
+
* // Use defaults
|
|
347
|
+
* const report = createArchiveSync('output.tar.gz', ['source_dir/']);
|
|
348
|
+
* console.log(`Created archive with ${report.filesAdded} files`);
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
export declare function createArchiveSync(outputPath: string, sources: Array<string>, config?: CreationConfig | undefined | null): CreationReport
|
|
212
352
|
|
|
213
|
-
|
|
214
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Report of an archive creation operation.
|
|
355
|
+
*
|
|
356
|
+
* Contains statistics and metadata about the creation process.
|
|
357
|
+
*/
|
|
358
|
+
export interface CreationReport {
|
|
359
|
+
/** Number of files added to the archive. */
|
|
360
|
+
filesAdded: number
|
|
361
|
+
/** Number of directories added to the archive. */
|
|
362
|
+
directoriesAdded: number
|
|
363
|
+
/** Number of symlinks added to the archive. */
|
|
364
|
+
symlinksAdded: number
|
|
365
|
+
/** Total bytes written to the archive (uncompressed). */
|
|
366
|
+
bytesWritten: number
|
|
367
|
+
/** Total bytes in the final archive (compressed). */
|
|
368
|
+
bytesCompressed: number
|
|
369
|
+
/** Duration of the creation operation in milliseconds. */
|
|
370
|
+
durationMs: number
|
|
371
|
+
/** Number of files skipped (due to filters or errors). */
|
|
372
|
+
filesSkipped: number
|
|
373
|
+
/** Warnings generated during creation. */
|
|
374
|
+
warnings: Array<string>
|
|
215
375
|
}
|
|
216
376
|
|
|
217
377
|
/**
|
|
@@ -222,7 +382,37 @@ export interface ExtractionReport {
|
|
|
222
382
|
* configuration that blocks symlinks, hardlinks, absolute paths, and
|
|
223
383
|
* enforces resource quotas.
|
|
224
384
|
*
|
|
225
|
-
*
|
|
385
|
+
* # Security Considerations
|
|
386
|
+
*
|
|
387
|
+
* ## Thread Safety and TOCTOU
|
|
388
|
+
*
|
|
389
|
+
* The extraction runs on a libuv thread pool worker thread. This creates
|
|
390
|
+
* a Time-Of-Check-Time-Of-Use (TOCTOU) race condition where the archive
|
|
391
|
+
* file could be modified between validation and extraction. This is an
|
|
392
|
+
* accepted tradeoff for async performance. For untrusted archives, ensure
|
|
393
|
+
* exclusive access to the archive file during extraction.
|
|
394
|
+
*
|
|
395
|
+
* ## Input Validation
|
|
396
|
+
*
|
|
397
|
+
* - Paths containing null bytes are rejected (security)
|
|
398
|
+
* - Paths exceeding 4096 bytes are rejected (`DoS` prevention)
|
|
399
|
+
* - All validation happens at the Node.js boundary before calling core library
|
|
400
|
+
*
|
|
401
|
+
* # Arguments
|
|
402
|
+
*
|
|
403
|
+
* * `archive_path` - Path to the archive file
|
|
404
|
+
* * `output_dir` - Directory where files will be extracted
|
|
405
|
+
* * `config` - Optional `SecurityConfig` (uses secure defaults if omitted)
|
|
406
|
+
*
|
|
407
|
+
* # Returns
|
|
408
|
+
*
|
|
409
|
+
* Promise resolving to `ExtractionReport` with extraction statistics
|
|
410
|
+
*
|
|
411
|
+
* # Errors
|
|
412
|
+
*
|
|
413
|
+
* Returns error for security violations or I/O errors. Error messages are
|
|
414
|
+
* prefixed with error codes for discrimination in JavaScript:
|
|
415
|
+
*
|
|
226
416
|
* - `PATH_TRAVERSAL`: Path traversal attempt detected
|
|
227
417
|
* - `SYMLINK_ESCAPE`: Symlink points outside extraction directory
|
|
228
418
|
* - `HARDLINK_ESCAPE`: Hardlink target outside extraction directory
|
|
@@ -234,14 +424,9 @@ export interface ExtractionReport {
|
|
|
234
424
|
* - `INVALID_ARCHIVE`: Archive is corrupted
|
|
235
425
|
* - `IO_ERROR`: I/O operation failed
|
|
236
426
|
*
|
|
237
|
-
*
|
|
238
|
-
* @param outputDir - Directory where files will be extracted
|
|
239
|
-
* @param config - Optional SecurityConfig (uses secure defaults if omitted)
|
|
240
|
-
* @returns Promise resolving to ExtractionReport with extraction statistics
|
|
241
|
-
* @throws Error for security violations or I/O errors
|
|
427
|
+
* # Examples
|
|
242
428
|
*
|
|
243
|
-
*
|
|
244
|
-
* ```typescript
|
|
429
|
+
* ```javascript
|
|
245
430
|
* // Use secure defaults
|
|
246
431
|
* const report = await extractArchive('archive.tar.gz', '/tmp/output');
|
|
247
432
|
* console.log(`Extracted ${report.filesExtracted} files`);
|
|
@@ -251,26 +436,32 @@ export interface ExtractionReport {
|
|
|
251
436
|
* const report = await extractArchive('archive.tar.gz', '/tmp/output', config);
|
|
252
437
|
* ```
|
|
253
438
|
*/
|
|
254
|
-
export function extractArchive(
|
|
255
|
-
archivePath: string,
|
|
256
|
-
outputDir: string,
|
|
257
|
-
config?: SecurityConfig
|
|
258
|
-
): Promise<ExtractionReport>;
|
|
439
|
+
export declare function extractArchive(archivePath: string, outputDir: string, config?: SecurityConfig | undefined | null): Promise<ExtractionReport>
|
|
259
440
|
|
|
260
441
|
/**
|
|
261
442
|
* Extract an archive to the specified directory (sync).
|
|
262
443
|
*
|
|
263
|
-
* Synchronous version of extractArchive
|
|
444
|
+
* Synchronous version of `extractArchive`. Blocks the event loop until
|
|
264
445
|
* extraction completes. Prefer the async version for most use cases.
|
|
265
446
|
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
447
|
+
* # Arguments
|
|
448
|
+
*
|
|
449
|
+
* * `archive_path` - Path to the archive file
|
|
450
|
+
* * `output_dir` - Directory where files will be extracted
|
|
451
|
+
* * `config` - Optional `SecurityConfig` (uses secure defaults if omitted)
|
|
452
|
+
*
|
|
453
|
+
* # Returns
|
|
271
454
|
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
455
|
+
* `ExtractionReport` with extraction statistics
|
|
456
|
+
*
|
|
457
|
+
* # Errors
|
|
458
|
+
*
|
|
459
|
+
* Returns error for security violations or I/O errors. See `extract_archive`
|
|
460
|
+
* for error code documentation.
|
|
461
|
+
*
|
|
462
|
+
* # Examples
|
|
463
|
+
*
|
|
464
|
+
* ```javascript
|
|
274
465
|
* // Use secure defaults
|
|
275
466
|
* const report = extractArchiveSync('archive.tar.gz', '/tmp/output');
|
|
276
467
|
* console.log(`Extracted ${report.filesExtracted} files`);
|
|
@@ -280,8 +471,187 @@ export function extractArchive(
|
|
|
280
471
|
* const report = extractArchiveSync('archive.tar.gz', '/tmp/output', config);
|
|
281
472
|
* ```
|
|
282
473
|
*/
|
|
283
|
-
export function extractArchiveSync(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
474
|
+
export declare function extractArchiveSync(archivePath: string, outputDir: string, config?: SecurityConfig | undefined | null): ExtractionReport
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Report of an archive extraction operation.
|
|
478
|
+
*
|
|
479
|
+
* Contains statistics and metadata about the extraction process.
|
|
480
|
+
*/
|
|
481
|
+
export interface ExtractionReport {
|
|
482
|
+
/** Number of files successfully extracted. */
|
|
483
|
+
filesExtracted: number
|
|
484
|
+
/** Number of directories created. */
|
|
485
|
+
directoriesCreated: number
|
|
486
|
+
/** Number of symlinks created. */
|
|
487
|
+
symlinksCreated: number
|
|
488
|
+
/** Total bytes written to disk. */
|
|
489
|
+
bytesWritten: number
|
|
490
|
+
/** Extraction duration in milliseconds. */
|
|
491
|
+
durationMs: number
|
|
492
|
+
/** Number of files skipped due to security checks. */
|
|
493
|
+
filesSkipped: number
|
|
494
|
+
/** List of warning messages. */
|
|
495
|
+
warnings: Array<string>
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* List archive contents without extracting (async).
|
|
500
|
+
*
|
|
501
|
+
* # Arguments
|
|
502
|
+
*
|
|
503
|
+
* * `archive_path` - Path to archive file
|
|
504
|
+
* * `config` - Optional `SecurityConfig` (uses secure defaults if omitted)
|
|
505
|
+
*
|
|
506
|
+
* # Returns
|
|
507
|
+
*
|
|
508
|
+
* Promise resolving to `ArchiveManifest` with entry metadata
|
|
509
|
+
*
|
|
510
|
+
* # Errors
|
|
511
|
+
*
|
|
512
|
+
* Returns error if path validation fails, archive is invalid, or I/O errors
|
|
513
|
+
* occur.
|
|
514
|
+
*
|
|
515
|
+
* # Examples
|
|
516
|
+
*
|
|
517
|
+
* ```javascript
|
|
518
|
+
* const manifest = await listArchive('archive.tar.gz');
|
|
519
|
+
* for (const entry of manifest.entries) {
|
|
520
|
+
* console.log(`${entry.path}: ${entry.size} bytes`);
|
|
521
|
+
* }
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
export declare function listArchive(archivePath: string, config?: SecurityConfig | undefined | null): Promise<ArchiveManifest>
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* List archive contents without extracting (sync).
|
|
528
|
+
*
|
|
529
|
+
* Synchronous version of `listArchive`. Blocks the event loop until
|
|
530
|
+
* listing completes. Prefer the async version for most use cases.
|
|
531
|
+
*
|
|
532
|
+
* # Arguments
|
|
533
|
+
*
|
|
534
|
+
* * `archive_path` - Path to archive file
|
|
535
|
+
* * `config` - Optional `SecurityConfig` (uses secure defaults if omitted)
|
|
536
|
+
*
|
|
537
|
+
* # Returns
|
|
538
|
+
*
|
|
539
|
+
* `ArchiveManifest` with entry metadata
|
|
540
|
+
*
|
|
541
|
+
* # Errors
|
|
542
|
+
*
|
|
543
|
+
* Returns error if path validation fails, archive is invalid, or I/O errors
|
|
544
|
+
* occur.
|
|
545
|
+
*
|
|
546
|
+
* # Examples
|
|
547
|
+
*
|
|
548
|
+
* ```javascript
|
|
549
|
+
* const manifest = listArchiveSync('archive.tar.gz');
|
|
550
|
+
* for (const entry of manifest.entries) {
|
|
551
|
+
* console.log(`${entry.path}: ${entry.size} bytes`);
|
|
552
|
+
* }
|
|
553
|
+
* ```
|
|
554
|
+
*/
|
|
555
|
+
export declare function listArchiveSync(archivePath: string, config?: SecurityConfig | undefined | null): ArchiveManifest
|
|
556
|
+
|
|
557
|
+
/** Single verification issue. */
|
|
558
|
+
export interface VerificationIssue {
|
|
559
|
+
/** Issue severity level ("Critical", "High", "Medium", "Low", "Info"). */
|
|
560
|
+
severity: string
|
|
561
|
+
/** Issue category (`PathTraversal`, `SymlinkEscape`, etc.). */
|
|
562
|
+
category: string
|
|
563
|
+
/** Entry path that triggered issue (if applicable). */
|
|
564
|
+
entryPath?: string
|
|
565
|
+
/** Human-readable description. */
|
|
566
|
+
message: string
|
|
567
|
+
/** Optional context (compression ratio, target path, etc.). */
|
|
568
|
+
context?: string
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Result of archive verification.
|
|
573
|
+
*
|
|
574
|
+
* Generated by `verifyArchive()`, contains security and integrity checks
|
|
575
|
+
* performed without extracting files to disk.
|
|
576
|
+
*/
|
|
577
|
+
export interface VerificationReport {
|
|
578
|
+
/** Overall verification status ("Pass", "Fail", "Warning"). */
|
|
579
|
+
status: string
|
|
580
|
+
/** Integrity check result ("Pass", "Fail", "Warning", "Skipped"). */
|
|
581
|
+
integrityStatus: string
|
|
582
|
+
/** Security check result ("Pass", "Fail", "Warning", "Skipped"). */
|
|
583
|
+
securityStatus: string
|
|
584
|
+
/** List of all issues found (sorted by severity). */
|
|
585
|
+
issues: Array<VerificationIssue>
|
|
586
|
+
/** Total entries scanned. */
|
|
587
|
+
totalEntries: number
|
|
588
|
+
/** Entries flagged as suspicious. */
|
|
589
|
+
suspiciousEntries: number
|
|
590
|
+
/** Total uncompressed size. */
|
|
591
|
+
totalSize: number
|
|
592
|
+
/** Archive format (e.g., `TarGz`, `Zip`). */
|
|
593
|
+
format: string
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Verify archive integrity and security (async).
|
|
598
|
+
*
|
|
599
|
+
* # Arguments
|
|
600
|
+
*
|
|
601
|
+
* * `archive_path` - Path to archive file
|
|
602
|
+
* * `config` - Optional `SecurityConfig` (uses secure defaults if omitted)
|
|
603
|
+
*
|
|
604
|
+
* # Returns
|
|
605
|
+
*
|
|
606
|
+
* Promise resolving to `VerificationReport` with validation results
|
|
607
|
+
*
|
|
608
|
+
* # Errors
|
|
609
|
+
*
|
|
610
|
+
* Returns error if path validation fails, archive is invalid, or I/O errors
|
|
611
|
+
* occur.
|
|
612
|
+
*
|
|
613
|
+
* # Examples
|
|
614
|
+
*
|
|
615
|
+
* ```javascript
|
|
616
|
+
* const report = await verifyArchive('archive.tar.gz');
|
|
617
|
+
* if (report.status === 'PASS') {
|
|
618
|
+
* console.log('Archive is safe to extract');
|
|
619
|
+
* } else {
|
|
620
|
+
* for (const issue of report.issues) {
|
|
621
|
+
* console.log(`[${issue.severity}] ${issue.message}`);
|
|
622
|
+
* }
|
|
623
|
+
* }
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
export declare function verifyArchive(archivePath: string, config?: SecurityConfig | undefined | null): Promise<VerificationReport>
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Verify archive integrity and security (sync).
|
|
630
|
+
*
|
|
631
|
+
* Synchronous version of `verifyArchive`. Blocks the event loop until
|
|
632
|
+
* verification completes. Prefer the async version for most use cases.
|
|
633
|
+
*
|
|
634
|
+
* # Arguments
|
|
635
|
+
*
|
|
636
|
+
* * `archive_path` - Path to archive file
|
|
637
|
+
* * `config` - Optional `SecurityConfig` (uses secure defaults if omitted)
|
|
638
|
+
*
|
|
639
|
+
* # Returns
|
|
640
|
+
*
|
|
641
|
+
* `VerificationReport` with validation results
|
|
642
|
+
*
|
|
643
|
+
* # Errors
|
|
644
|
+
*
|
|
645
|
+
* Returns error if path validation fails, archive is invalid, or I/O errors
|
|
646
|
+
* occur.
|
|
647
|
+
*
|
|
648
|
+
* # Examples
|
|
649
|
+
*
|
|
650
|
+
* ```javascript
|
|
651
|
+
* const report = verifyArchiveSync('archive.tar.gz');
|
|
652
|
+
* if (report.status === 'PASS') {
|
|
653
|
+
* console.log('Archive is safe to extract');
|
|
654
|
+
* }
|
|
655
|
+
* ```
|
|
656
|
+
*/
|
|
657
|
+
export declare function verifyArchiveSync(archivePath: string, config?: SecurityConfig | undefined | null): VerificationReport
|