memento-mcp-server 1.16.2-a → 1.16.3-a
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/dist/domains/anchor/services/anchor/n-hop-search-service.d.ts.map +1 -1
- package/dist/domains/anchor/services/anchor/n-hop-search-service.js +4 -5
- package/dist/domains/anchor/services/anchor/n-hop-search-service.js.map +1 -1
- package/dist/domains/embedding/services/embedding-service.d.ts.map +1 -1
- package/dist/domains/embedding/services/embedding-service.js +5 -2
- package/dist/domains/embedding/services/embedding-service.js.map +1 -1
- package/dist/domains/embedding/services/gemini-embedding-service.d.ts.map +1 -1
- package/dist/domains/embedding/services/gemini-embedding-service.js +6 -3
- package/dist/domains/embedding/services/gemini-embedding-service.js.map +1 -1
- package/dist/domains/embedding/services/lightweight-embedding-service.d.ts.map +1 -1
- package/dist/domains/embedding/services/lightweight-embedding-service.js +4 -2
- package/dist/domains/embedding/services/lightweight-embedding-service.js.map +1 -1
- package/dist/domains/embedding/services/minilm-embedding-service.d.ts.map +1 -1
- package/dist/domains/embedding/services/minilm-embedding-service.js +6 -3
- package/dist/domains/embedding/services/minilm-embedding-service.js.map +1 -1
- package/dist/domains/embedding/services/openai-embedding-service.d.ts.map +1 -1
- package/dist/domains/embedding/services/openai-embedding-service.js +5 -2
- package/dist/domains/embedding/services/openai-embedding-service.js.map +1 -1
- package/dist/domains/embedding/services/unified-embedding-service.d.ts.map +1 -1
- package/dist/domains/embedding/services/unified-embedding-service.js +6 -3
- package/dist/domains/embedding/services/unified-embedding-service.js.map +1 -1
- package/dist/domains/forgetting/services/forgetting-policy-service.d.ts.map +1 -1
- package/dist/domains/forgetting/services/forgetting-policy-service.js +3 -1
- package/dist/domains/forgetting/services/forgetting-policy-service.js.map +1 -1
- package/dist/domains/memory/services/memory-embedding-service.d.ts +1 -0
- package/dist/domains/memory/services/memory-embedding-service.d.ts.map +1 -1
- package/dist/domains/memory/services/memory-embedding-service.js +43 -39
- package/dist/domains/memory/services/memory-embedding-service.js.map +1 -1
- package/dist/domains/memory/services/memory-neighbor-service.d.ts.map +1 -1
- package/dist/domains/memory/services/memory-neighbor-service.js +13 -4
- package/dist/domains/memory/services/memory-neighbor-service.js.map +1 -1
- package/dist/domains/memory/tools/convert-episodic-to-semantic-tool.js +5 -6
- package/dist/domains/memory/tools/convert-episodic-to-semantic-tool.js.map +1 -1
- package/dist/domains/memory/tools/forget-tool.d.ts.map +1 -1
- package/dist/domains/memory/tools/forget-tool.js +5 -2
- package/dist/domains/memory/tools/forget-tool.js.map +1 -1
- package/dist/domains/memory/tools/memory-injection-prompt.d.ts.map +1 -1
- package/dist/domains/memory/tools/memory-injection-prompt.js +3 -1
- package/dist/domains/memory/tools/memory-injection-prompt.js.map +1 -1
- package/dist/domains/memory/tools/pin-tool.d.ts.map +1 -1
- package/dist/domains/memory/tools/pin-tool.js +5 -2
- package/dist/domains/memory/tools/pin-tool.js.map +1 -1
- package/dist/domains/memory/tools/unpin-tool.d.ts.map +1 -1
- package/dist/domains/memory/tools/unpin-tool.js +5 -2
- package/dist/domains/memory/tools/unpin-tool.js.map +1 -1
- package/dist/domains/monitoring/services/error-logging-service.d.ts +5 -0
- package/dist/domains/monitoring/services/error-logging-service.d.ts.map +1 -1
- package/dist/domains/monitoring/services/error-logging-service.js +28 -10
- package/dist/domains/monitoring/services/error-logging-service.js.map +1 -1
- package/dist/domains/monitoring/services/performance-alert-service.d.ts.map +1 -1
- package/dist/domains/monitoring/services/performance-alert-service.js +5 -2
- package/dist/domains/monitoring/services/performance-alert-service.js.map +1 -1
- package/dist/domains/relation/services/relation-graph.d.ts.map +1 -1
- package/dist/domains/relation/services/relation-graph.js +3 -4
- package/dist/domains/relation/services/relation-graph.js.map +1 -1
- package/dist/domains/search/algorithms/hybrid-search-engine.d.ts.map +1 -1
- package/dist/domains/search/algorithms/hybrid-search-engine.js +15 -10
- package/dist/domains/search/algorithms/hybrid-search-engine.js.map +1 -1
- package/dist/domains/search/algorithms/search-engine.d.ts.map +1 -1
- package/dist/domains/search/algorithms/search-engine.js +8 -4
- package/dist/domains/search/algorithms/search-engine.js.map +1 -1
- package/dist/domains/search/algorithms/vector-search-engine-migration.d.ts.map +1 -1
- package/dist/domains/search/algorithms/vector-search-engine-migration.js +9 -4
- package/dist/domains/search/algorithms/vector-search-engine-migration.js.map +1 -1
- package/dist/domains/search/algorithms/vector-search-engine.d.ts +1 -0
- package/dist/domains/search/algorithms/vector-search-engine.d.ts.map +1 -1
- package/dist/domains/search/algorithms/vector-search-engine.js +25 -22
- package/dist/domains/search/algorithms/vector-search-engine.js.map +1 -1
- package/dist/domains/search/repositories/vector-performance.repository.d.ts.map +1 -1
- package/dist/domains/search/repositories/vector-performance.repository.js +3 -1
- package/dist/domains/search/repositories/vector-performance.repository.js.map +1 -1
- package/dist/domains/search/repositories/vector-search.repository.d.ts +1 -0
- package/dist/domains/search/repositories/vector-search.repository.d.ts.map +1 -1
- package/dist/domains/search/repositories/vector-search.repository.js +154 -149
- package/dist/domains/search/repositories/vector-search.repository.js.map +1 -1
- package/dist/domains/search/services/vector-search/vector-index-manager.d.ts.map +1 -1
- package/dist/domains/search/services/vector-search/vector-index-manager.js +7 -3
- package/dist/domains/search/services/vector-search/vector-index-manager.js.map +1 -1
- package/dist/domains/search/services/vector-search/vector-performance-tester.d.ts.map +1 -1
- package/dist/domains/search/services/vector-search/vector-performance-tester.js +3 -1
- package/dist/domains/search/services/vector-search/vector-performance-tester.js.map +1 -1
- package/dist/infrastructure/database/database/init.d.ts.map +1 -1
- package/dist/infrastructure/database/database/init.js +29 -7
- package/dist/infrastructure/database/database/init.js.map +1 -1
- package/dist/infrastructure/database/database/migrate.d.ts.map +1 -1
- package/dist/infrastructure/database/database/migrate.js +5 -2
- package/dist/infrastructure/database/database/migrate.js.map +1 -1
- package/dist/infrastructure/database/database/migration/backup-manager.d.ts.map +1 -1
- package/dist/infrastructure/database/database/migration/backup-manager.js +11 -5
- package/dist/infrastructure/database/database/migration/backup-manager.js.map +1 -1
- package/dist/infrastructure/database/database/migration/migration-detector.d.ts.map +1 -1
- package/dist/infrastructure/database/database/migration/migration-detector.js +3 -1
- package/dist/infrastructure/database/database/migration/migration-detector.js.map +1 -1
- package/dist/infrastructure/database/database/migration/migration-logger.d.ts.map +1 -1
- package/dist/infrastructure/database/database/migration/migration-logger.js +5 -2
- package/dist/infrastructure/database/database/migration/migration-logger.js.map +1 -1
- package/dist/infrastructure/database/database/migration/migration-runner.d.ts.map +1 -1
- package/dist/infrastructure/database/database/migration/migration-runner.js +24 -13
- package/dist/infrastructure/database/database/migration/migration-runner.js.map +1 -1
- package/dist/infrastructure/database/database/migration/schema-version-manager.d.ts.map +1 -1
- package/dist/infrastructure/database/database/migration/schema-version-manager.js +7 -3
- package/dist/infrastructure/database/database/migration/schema-version-manager.js.map +1 -1
- package/dist/infrastructure/database/database-optimizer.d.ts.map +1 -1
- package/dist/infrastructure/database/database-optimizer.js +7 -6
- package/dist/infrastructure/database/database-optimizer.js.map +1 -1
- package/dist/infrastructure/database/migration-history-service.d.ts.map +1 -1
- package/dist/infrastructure/database/migration-history-service.js +3 -1
- package/dist/infrastructure/database/migration-history-service.js.map +1 -1
- package/dist/infrastructure/logging/triple-extraction-logger.d.ts +6 -0
- package/dist/infrastructure/logging/triple-extraction-logger.d.ts.map +1 -1
- package/dist/infrastructure/logging/triple-extraction-logger.js +50 -12
- package/dist/infrastructure/logging/triple-extraction-logger.js.map +1 -1
- package/dist/infrastructure/scheduler/batch-scheduler.d.ts.map +1 -1
- package/dist/infrastructure/scheduler/batch-scheduler.js +5 -2
- package/dist/infrastructure/scheduler/batch-scheduler.js.map +1 -1
- package/dist/infrastructure/scheduler/file-logger.d.ts +4 -1
- package/dist/infrastructure/scheduler/file-logger.d.ts.map +1 -1
- package/dist/infrastructure/scheduler/file-logger.js +46 -16
- package/dist/infrastructure/scheduler/file-logger.js.map +1 -1
- package/dist/scripts/check-migration-status.d.ts.map +1 -1
- package/dist/scripts/check-migration-status.js +19 -6
- package/dist/scripts/check-migration-status.js.map +1 -1
- package/dist/services/quality-assurance/quality-recorder.js +2 -2
- package/dist/services/quality-assurance/quality-recorder.js.map +1 -1
- package/dist/services/quality-assurance/quality-threshold-manager.js +1 -1
- package/dist/services/quality-assurance/quality-threshold-manager.js.map +1 -1
- package/dist/shared/config/environment.d.ts.map +1 -1
- package/dist/shared/config/environment.js +3 -1
- package/dist/shared/config/environment.js.map +1 -1
- package/dist/shared/utils/fts5-migration-status.d.ts.map +1 -1
- package/dist/shared/utils/fts5-migration-status.js +6 -2
- package/dist/shared/utils/fts5-migration-status.js.map +1 -1
- package/dist/shared/utils/logger.d.ts.map +1 -1
- package/dist/shared/utils/logger.js +15 -2
- package/dist/shared/utils/logger.js.map +1 -1
- package/dist/shared/utils/path-validator.d.ts +27 -0
- package/dist/shared/utils/path-validator.d.ts.map +1 -0
- package/dist/shared/utils/path-validator.js +166 -0
- package/dist/shared/utils/path-validator.js.map +1 -0
- package/dist/shared/utils/pii-masker.d.ts +31 -0
- package/dist/shared/utils/pii-masker.d.ts.map +1 -1
- package/dist/shared/utils/pii-masker.js +99 -0
- package/dist/shared/utils/pii-masker.js.map +1 -1
- package/dist/shared/utils/procedural-memory-extractor.d.ts.map +1 -1
- package/dist/shared/utils/procedural-memory-extractor.js +39 -33
- package/dist/shared/utils/procedural-memory-extractor.js.map +1 -1
- package/dist/shared/utils/prompt-template-loader.d.ts +6 -0
- package/dist/shared/utils/prompt-template-loader.d.ts.map +1 -1
- package/dist/shared/utils/prompt-template-loader.js +20 -8
- package/dist/shared/utils/prompt-template-loader.js.map +1 -1
- package/dist/shared/utils/reflection-notes-merge.d.ts.map +1 -1
- package/dist/shared/utils/reflection-notes-merge.js +5 -4
- package/dist/shared/utils/reflection-notes-merge.js.map +1 -1
- package/dist/shared/utils/sql-security-validator.d.ts +25 -0
- package/dist/shared/utils/sql-security-validator.d.ts.map +1 -0
- package/dist/shared/utils/sql-security-validator.js +67 -0
- package/dist/shared/utils/sql-security-validator.js.map +1 -0
- package/dist/shared/utils/write-coalescing.d.ts.map +1 -1
- package/dist/shared/utils/write-coalescing.js +7 -3
- package/dist/shared/utils/write-coalescing.js.map +1 -1
- package/package.json +2 -1
- package/scripts/backup-daily.bat +10 -2
- package/scripts/backup-embeddings.js +22 -2
- package/scripts/check-path-traversal.ts +370 -0
- package/scripts/check-pii-masking.ts +360 -0
- package/scripts/check-sql-injection.ts +610 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PII 마스킹 적용 여부 검사 스크립트
|
|
4
|
+
*
|
|
5
|
+
* PRD 0019: 보안 강화 (Phase 1) - PII 마스킹 강화
|
|
6
|
+
*
|
|
7
|
+
* 사용법:
|
|
8
|
+
* tsx scripts/check-pii-masking.ts
|
|
9
|
+
* tsx scripts/check-pii-masking.ts --ci
|
|
10
|
+
* tsx scripts/check-pii-masking.ts --directory src/
|
|
11
|
+
*
|
|
12
|
+
* 목표:
|
|
13
|
+
* - 모든 로거에서 PII 마스킹 적용 확인
|
|
14
|
+
* - 미적용 로거 0개
|
|
15
|
+
* - CI/CD 통합 가능
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { readFileSync } from 'fs';
|
|
19
|
+
import { readdir } from 'fs/promises';
|
|
20
|
+
import { join, relative } from 'path';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* CLI 옵션
|
|
24
|
+
*/
|
|
25
|
+
interface CliOptions {
|
|
26
|
+
ci?: boolean;
|
|
27
|
+
directory?: string;
|
|
28
|
+
exclude?: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* PII 마스킹 미적용 발견 위치
|
|
33
|
+
*/
|
|
34
|
+
interface PIIMaskingLocation {
|
|
35
|
+
file: string;
|
|
36
|
+
line: number;
|
|
37
|
+
column: number;
|
|
38
|
+
pattern: string; // 발견된 패턴 종류
|
|
39
|
+
context: string; // 해당 라인 내용
|
|
40
|
+
severity: 'high' | 'medium' | 'low'; // 심각도
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 검사 결과
|
|
45
|
+
*/
|
|
46
|
+
interface CheckResult {
|
|
47
|
+
total: number;
|
|
48
|
+
locations: PIIMaskingLocation[];
|
|
49
|
+
byFile: Map<string, PIIMaskingLocation[]>;
|
|
50
|
+
byPattern: Map<string, number>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 명령줄 인자 파싱
|
|
55
|
+
*/
|
|
56
|
+
function parseArgs(): CliOptions {
|
|
57
|
+
const args = process.argv.slice(2);
|
|
58
|
+
const options: CliOptions = {
|
|
59
|
+
exclude: ['**/node_modules/**', '**/dist/**', '**/*.d.ts', '**/*.spec.ts', '**/__tests__/**']
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < args.length; i++) {
|
|
63
|
+
const arg = args[i];
|
|
64
|
+
if (arg === '--ci') {
|
|
65
|
+
options.ci = true;
|
|
66
|
+
} else if (arg === '--directory' && args[i + 1]) {
|
|
67
|
+
options.directory = args[i + 1];
|
|
68
|
+
i++;
|
|
69
|
+
} else if (arg === '--exclude' && args[i + 1]) {
|
|
70
|
+
if (!options.exclude) {
|
|
71
|
+
options.exclude = [];
|
|
72
|
+
}
|
|
73
|
+
options.exclude.push(args[i + 1]);
|
|
74
|
+
i++;
|
|
75
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
76
|
+
printHelp();
|
|
77
|
+
process.exit(0);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return options;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 도움말 출력
|
|
86
|
+
*/
|
|
87
|
+
function printHelp(): void {
|
|
88
|
+
console.log(`
|
|
89
|
+
PII 마스킹 적용 여부 검사 스크립트
|
|
90
|
+
|
|
91
|
+
사용법:
|
|
92
|
+
tsx scripts/check-pii-masking.ts [options]
|
|
93
|
+
|
|
94
|
+
옵션:
|
|
95
|
+
--ci CI 모드 (미적용 로거 발견 시 exit code 1 반환)
|
|
96
|
+
--directory <path> 검사할 디렉토리 (기본값: src/)
|
|
97
|
+
--exclude <pattern> 제외할 파일 패턴 (여러 번 사용 가능)
|
|
98
|
+
--help, -h 도움말 출력
|
|
99
|
+
|
|
100
|
+
예제:
|
|
101
|
+
tsx scripts/check-pii-masking.ts
|
|
102
|
+
tsx scripts/check-pii-masking.ts --ci
|
|
103
|
+
tsx scripts/check-pii-masking.ts --directory src/domains
|
|
104
|
+
`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 파일이 제외 패턴에 해당하는지 확인
|
|
109
|
+
*/
|
|
110
|
+
function shouldExclude(file: string, excludePatterns: string[]): boolean {
|
|
111
|
+
for (const pattern of excludePatterns) {
|
|
112
|
+
// 간단한 패턴 매칭 (glob 패턴은 복잡하므로 기본적인 것만 지원)
|
|
113
|
+
if (pattern.includes('**')) {
|
|
114
|
+
const regex = new RegExp(pattern.replace(/\*\*/g, '.*').replace(/\*/g, '[^/]*'));
|
|
115
|
+
if (regex.test(file)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
} else if (file.includes(pattern)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 재귀적으로 디렉토리 탐색
|
|
127
|
+
*/
|
|
128
|
+
async function findFiles(
|
|
129
|
+
dir: string,
|
|
130
|
+
excludePatterns: string[],
|
|
131
|
+
fileList: string[] = []
|
|
132
|
+
): Promise<string[]> {
|
|
133
|
+
try {
|
|
134
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
135
|
+
|
|
136
|
+
for (const entry of entries) {
|
|
137
|
+
const fullPath = join(dir, entry.name);
|
|
138
|
+
const relativePath = relative(process.cwd(), fullPath);
|
|
139
|
+
|
|
140
|
+
if (shouldExclude(relativePath, excludePatterns)) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (entry.isDirectory()) {
|
|
145
|
+
await findFiles(fullPath, excludePatterns, fileList);
|
|
146
|
+
} else if (entry.isFile() && entry.name.endsWith('.ts')) {
|
|
147
|
+
fileList.push(fullPath);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
// 디렉토리 읽기 실패는 무시
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return fileList;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* 파일 내용에서 PII 마스킹 미적용 패턴 검색
|
|
159
|
+
*/
|
|
160
|
+
function checkFile(filePath: string): PIIMaskingLocation[] {
|
|
161
|
+
const locations: PIIMaskingLocation[] = [];
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
165
|
+
const lines = content.split('\n');
|
|
166
|
+
const relativePath = relative(process.cwd(), filePath);
|
|
167
|
+
|
|
168
|
+
// logger.ts는 이미 PII 마스킹이 적용되어 있으므로 제외
|
|
169
|
+
if (relativePath.includes('shared/utils/logger.ts')) {
|
|
170
|
+
return locations;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// logger.ts를 import하는지 확인 (이미 마스킹이 적용되어 있음)
|
|
174
|
+
const usesLoggerUtils = /import.*logger.*from.*['"]\.\.?\/.*shared\/utils\/logger|from.*['"]\.\.?\/.*shared\/utils\/logger/.test(content);
|
|
175
|
+
|
|
176
|
+
// 로거 파일인지 확인 (logger, file-logger, error-logging-service 등)
|
|
177
|
+
const isLoggerFile = /logger|log|error-logging/i.test(relativePath);
|
|
178
|
+
|
|
179
|
+
// PIIMasker import 확인
|
|
180
|
+
const hasPIIMaskerImport = /import.*PIIMasker|from.*pii-masker/.test(content);
|
|
181
|
+
|
|
182
|
+
// logger.error, logger.warn, logger.info, logger.debug 호출 확인
|
|
183
|
+
// logger.ts를 import하는 경우는 이미 마스킹이 적용되어 있으므로 제외
|
|
184
|
+
if (!usesLoggerUtils) {
|
|
185
|
+
const loggerMethodPattern = /logger\.(error|warn|info|debug|log)\s*\(/g;
|
|
186
|
+
let match;
|
|
187
|
+
|
|
188
|
+
while ((match = loggerMethodPattern.exec(content)) !== null) {
|
|
189
|
+
const lineNumber = content.substring(0, match.index).split('\n').length;
|
|
190
|
+
const line = lines[lineNumber - 1];
|
|
191
|
+
|
|
192
|
+
// PIIMasker를 사용하지 않는 logger 호출 확인
|
|
193
|
+
// 해당 메서드 호출 전후로 PIIMasker 사용 여부 확인
|
|
194
|
+
const beforeContext = content.substring(Math.max(0, match.index - 500), match.index);
|
|
195
|
+
const afterContext = content.substring(match.index, Math.min(content.length, match.index + 500));
|
|
196
|
+
|
|
197
|
+
// PIIMasker.mask가 사용되지 않은 경우
|
|
198
|
+
if (!beforeContext.includes('PIIMasker.mask') && !afterContext.includes('PIIMasker.mask')) {
|
|
199
|
+
locations.push({
|
|
200
|
+
file: relativePath,
|
|
201
|
+
line: lineNumber,
|
|
202
|
+
column: match.index - content.substring(0, match.index).lastIndexOf('\n') - 1,
|
|
203
|
+
pattern: 'logger-method-without-masking',
|
|
204
|
+
context: line.trim(),
|
|
205
|
+
severity: isLoggerFile ? 'high' : 'medium'
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// console.error에서 error.message 또는 error.stack 직접 사용 확인
|
|
212
|
+
const consoleErrorPattern = /console\.(error|warn|log|info|debug)\s*\([^)]*(error\.(message|stack)|error\))/g;
|
|
213
|
+
let consoleMatch;
|
|
214
|
+
|
|
215
|
+
while ((consoleMatch = consoleErrorPattern.exec(content)) !== null) {
|
|
216
|
+
const lineNumber = content.substring(0, consoleMatch.index).split('\n').length;
|
|
217
|
+
const line = lines[lineNumber - 1];
|
|
218
|
+
|
|
219
|
+
// PIIMasker를 사용하지 않는 console.error 호출 확인
|
|
220
|
+
const beforeContext = content.substring(Math.max(0, consoleMatch.index - 500), consoleMatch.index);
|
|
221
|
+
const afterContext = content.substring(consoleMatch.index, Math.min(content.length, consoleMatch.index + 500));
|
|
222
|
+
|
|
223
|
+
if (!beforeContext.includes('PIIMasker.mask') && !afterContext.includes('PIIMasker.mask')) {
|
|
224
|
+
// catch 블록 내부인지 확인
|
|
225
|
+
const beforeCatch = content.substring(Math.max(0, consoleMatch.index - 1000), consoleMatch.index);
|
|
226
|
+
if (beforeCatch.includes('catch') || line.includes('catch')) {
|
|
227
|
+
locations.push({
|
|
228
|
+
file: relativePath,
|
|
229
|
+
line: lineNumber,
|
|
230
|
+
column: consoleMatch.index - content.substring(0, consoleMatch.index).lastIndexOf('\n') - 1,
|
|
231
|
+
pattern: 'console-error-without-masking',
|
|
232
|
+
context: line.trim(),
|
|
233
|
+
severity: 'high'
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// logger.error에서 error 객체를 직접 전달하는 경우 확인
|
|
240
|
+
// logger.ts를 import하는 경우는 이미 마스킹이 적용되어 있으므로 제외
|
|
241
|
+
if (!usesLoggerUtils) {
|
|
242
|
+
const loggerErrorPattern = /logger\.(error|warn|info|debug)\s*\([^,)]*,\s*\{[^}]*error[^}]*\}/g;
|
|
243
|
+
let loggerErrorMatch;
|
|
244
|
+
|
|
245
|
+
while ((loggerErrorMatch = loggerErrorPattern.exec(content)) !== null) {
|
|
246
|
+
const lineNumber = content.substring(0, loggerErrorMatch.index).split('\n').length;
|
|
247
|
+
const line = lines[lineNumber - 1];
|
|
248
|
+
|
|
249
|
+
// error 객체가 마스킹되지 않은 상태로 전달되는지 확인
|
|
250
|
+
const beforeContext = content.substring(Math.max(0, loggerErrorMatch.index - 500), loggerErrorMatch.index);
|
|
251
|
+
|
|
252
|
+
if (!beforeContext.includes('PIIMasker.mask') && !line.includes('PIIMasker.mask')) {
|
|
253
|
+
locations.push({
|
|
254
|
+
file: relativePath,
|
|
255
|
+
line: lineNumber,
|
|
256
|
+
column: loggerErrorMatch.index - content.substring(0, loggerErrorMatch.index).lastIndexOf('\n') - 1,
|
|
257
|
+
pattern: 'logger-error-object-without-masking',
|
|
258
|
+
context: line.trim(),
|
|
259
|
+
severity: 'medium'
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
} catch (error) {
|
|
266
|
+
// 파일 읽기 실패는 무시
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return locations;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* 모든 파일 검사
|
|
274
|
+
*/
|
|
275
|
+
async function checkAllFiles(options: CliOptions): Promise<CheckResult> {
|
|
276
|
+
const directory = options.directory || 'src';
|
|
277
|
+
const excludePatterns = options.exclude || [];
|
|
278
|
+
|
|
279
|
+
const files = await findFiles(directory, excludePatterns);
|
|
280
|
+
const locations: PIIMaskingLocation[] = [];
|
|
281
|
+
const byFile = new Map<string, PIIMaskingLocation[]>();
|
|
282
|
+
const byPattern = new Map<string, number>();
|
|
283
|
+
|
|
284
|
+
for (const file of files) {
|
|
285
|
+
const fileLocations = checkFile(file);
|
|
286
|
+
if (fileLocations.length > 0) {
|
|
287
|
+
const relativePath = relative(process.cwd(), file);
|
|
288
|
+
locations.push(...fileLocations);
|
|
289
|
+
byFile.set(relativePath, fileLocations);
|
|
290
|
+
|
|
291
|
+
for (const loc of fileLocations) {
|
|
292
|
+
byPattern.set(loc.pattern, (byPattern.get(loc.pattern) || 0) + 1);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
total: locations.length,
|
|
299
|
+
locations,
|
|
300
|
+
byFile,
|
|
301
|
+
byPattern
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* 결과 출력
|
|
307
|
+
*/
|
|
308
|
+
function printResults(result: CheckResult): void {
|
|
309
|
+
console.log('\n⚠️ 발견된 PII 마스킹 미적용:', result.total, '개');
|
|
310
|
+
|
|
311
|
+
if (result.total === 0) {
|
|
312
|
+
console.log('✅ 모든 로거에서 PII 마스킹이 적용되어 있습니다.');
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
console.log('📁 파일별 미적용 목록:');
|
|
317
|
+
|
|
318
|
+
for (const [file, locations] of result.byFile.entries()) {
|
|
319
|
+
console.log(`\n ${file} (${locations.length}개):`);
|
|
320
|
+
|
|
321
|
+
for (const loc of locations) {
|
|
322
|
+
const severityIcon = loc.severity === 'high' ? '🔴' : loc.severity === 'medium' ? '🟡' : '🟢';
|
|
323
|
+
console.log(` ${severityIcon} 라인 ${loc.line}:${loc.column} - ${loc.pattern}`);
|
|
324
|
+
console.log(` ${loc.context}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
console.log('\n📊 패턴별 통계:');
|
|
329
|
+
for (const [pattern, count] of result.byPattern.entries()) {
|
|
330
|
+
console.log(` ${pattern}: ${count}개`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* 메인 함수
|
|
336
|
+
*/
|
|
337
|
+
async function main(): Promise<void> {
|
|
338
|
+
const options = parseArgs();
|
|
339
|
+
|
|
340
|
+
console.log('🔍 PII 마스킹 적용 여부 검사 시작...\n');
|
|
341
|
+
|
|
342
|
+
const result = await checkAllFiles(options);
|
|
343
|
+
printResults(result);
|
|
344
|
+
|
|
345
|
+
if (options.ci && result.total > 0) {
|
|
346
|
+
console.error('\n❌ CI 실패: PII 마스킹 미적용 로거가 발견되었습니다.');
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (result.total === 0) {
|
|
351
|
+
console.log('\n✅ 검사 완료: 모든 로거에서 PII 마스킹이 적용되어 있습니다.');
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// 스크립트 실행
|
|
356
|
+
main().catch(error => {
|
|
357
|
+
console.error('❌ 스크립트 실행 실패:', error);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
});
|
|
360
|
+
|