autosnippet 3.1.3 → 3.1.4

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/bin/mcp-server.js CHANGED
File without changes
@@ -9,6 +9,7 @@
9
9
  import fs from 'node:fs/promises';
10
10
  import path from 'node:path';
11
11
  import Logger from '../../../../../infrastructure/logging/Logger.js';
12
+ import pathGuard from '../../../../../shared/PathGuard.js';
12
13
 
13
14
  const logger = Logger.getInstance();
14
15
 
@@ -79,8 +80,12 @@ export async function loadCheckpoints(projectRoot) {
79
80
  export async function clearCheckpoints(projectRoot) {
80
81
  try {
81
82
  const checkpointDir = path.join(projectRoot, '.autosnippet', 'bootstrap-checkpoint');
83
+ pathGuard.assertSafe(checkpointDir);
82
84
  await fs.rm(checkpointDir, { recursive: true, force: true });
83
- } catch {
84
- /* ignore */
85
+ } catch (err) {
86
+ if (err?.name === 'PathGuardError') {
87
+ throw err;
88
+ }
89
+ /* ignore other errors */
85
90
  }
86
91
  }
@@ -309,6 +309,7 @@ export class KnowledgeFileWriter {
309
309
  if (entry.sourceFile) {
310
310
  const fullPath = path.join(this.projectRoot, entry.sourceFile);
311
311
  if (fs.existsSync(fullPath)) {
312
+ pathGuard.assertSafe(fullPath);
312
313
  fs.unlinkSync(fullPath);
313
314
  this.logger.info('Knowledge entry file removed', {
314
315
  entryId: entry.id,
@@ -328,6 +329,7 @@ export class KnowledgeFileWriter {
328
329
  for (const dir of searchDirs) {
329
330
  const fp = path.join(dir, filename);
330
331
  if (fs.existsSync(fp)) {
332
+ pathGuard.assertSafe(fp);
331
333
  fs.unlinkSync(fp);
332
334
  this.logger.info('Knowledge entry file removed', { entryId: entry.id, path: fp });
333
335
  return true;
@@ -358,6 +360,7 @@ export class KnowledgeFileWriter {
358
360
 
359
361
  // 删除旧文件
360
362
  if (oldPath && fs.existsSync(oldPath)) {
363
+ pathGuard.assertSafe(oldPath);
361
364
  fs.unlinkSync(oldPath);
362
365
  this.logger.info('Removed old knowledge entry file on lifecycle change', {
363
366
  entryId: entry.id,
@@ -392,6 +395,7 @@ export class KnowledgeFileWriter {
392
395
  }
393
396
  const oldPath = path.join(this.projectRoot, entry.sourceFile);
394
397
  if (oldPath !== newPath && fs.existsSync(oldPath)) {
398
+ pathGuard.assertSafe(oldPath);
395
399
  fs.unlinkSync(oldPath);
396
400
  this.logger.info('Cleaned up old knowledge entry file', {
397
401
  entryId: entry.id,
@@ -675,6 +679,7 @@ function _walkAndRemoveById(dir, id) {
675
679
  } else if (entry.name.endsWith('.md') && !entry.name.startsWith('_')) {
676
680
  const head = fs.readFileSync(full, 'utf8').slice(0, 500);
677
681
  if (head.includes(`id: ${id}`)) {
682
+ pathGuard.assertSafe(full);
678
683
  fs.unlinkSync(full);
679
684
  return true;
680
685
  }
@@ -332,6 +332,10 @@ export function dedup(files, wikiDir, emit) {
332
332
  // 完全相同 hash → 移除后来的
333
333
  if (existing.hash === file.hash) {
334
334
  const fullPath = path.join(wikiDir, file.path);
335
+ if (!fullPath.startsWith(path.resolve(wikiDir) + path.sep)) {
336
+ logger.warn(`[WikiGenerator] Dedup: path escape blocked — ${file.path}`);
337
+ continue;
338
+ }
335
339
  try {
336
340
  fs.unlinkSync(fullPath);
337
341
  } catch {
@@ -361,6 +365,10 @@ export function dedup(files, wikiDir, emit) {
361
365
  if (isCurrentSynced && !isFirstSynced) {
362
366
  // 当前是 synced,first 是 codegen → 删除 synced
363
367
  const fullPath = path.join(wikiDir, file.path);
368
+ if (!fullPath.startsWith(path.resolve(wikiDir) + path.sep)) {
369
+ logger.warn(`[WikiGenerator] Dedup: path escape blocked — ${file.path}`);
370
+ continue;
371
+ }
364
372
  try {
365
373
  fs.unlinkSync(fullPath);
366
374
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autosnippet",
3
- "version": "3.1.3",
3
+ "version": "3.1.4",
4
4
  "description": "Extract code patterns into a knowledge base for AI coding assistants",
5
5
  "type": "module",
6
6
  "main": "lib/bootstrap.js",