@xrift/code-security 0.1.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/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # @xrift/code-security
2
+
3
+ JavaScript コードの静的セキュリティ解析パッケージ。acorn ベースの AST 解析により、危険な API 使用や難読化パターンを検出します。
4
+
5
+ ## インストール
6
+
7
+ ```bash
8
+ npm install @xrift/code-security
9
+ ```
10
+
11
+ ## 使い方
12
+
13
+ ### CodeSecurityService(推奨)
14
+
15
+ ```typescript
16
+ import { CodeSecurityService } from '@xrift/code-security'
17
+
18
+ const service = new CodeSecurityService()
19
+
20
+ const result = service.validate({
21
+ code: 'const x = 1;',
22
+ packageJson: {
23
+ dependencies: {}
24
+ }
25
+ })
26
+
27
+ console.log(result.valid) // true
28
+ console.log(result.securityScore) // 0
29
+ console.log(result.violations) // { critical: [], warnings: [] }
30
+ ```
31
+
32
+ ### analyzeCodeSecurity(低レベル API)
33
+
34
+ ```typescript
35
+ import { analyzeCodeSecurity } from '@xrift/code-security'
36
+
37
+ const signals = analyzeCodeSecurity('eval("alert(1)")')
38
+
39
+ console.log(signals.hasEval) // true
40
+ console.log(signals.detectedViolations) // [{ rule: 'no-eval', ... }]
41
+ ```
42
+
43
+ ### ネットワーク権限の付与
44
+
45
+ ```typescript
46
+ const result = service.validate({
47
+ code: `fetch('https://api.example.com/data')`,
48
+ packageJson: { dependencies: {} },
49
+ manifestConfig: {
50
+ permissions: {
51
+ network: {
52
+ allowedDomains: ['api.example.com']
53
+ }
54
+ }
55
+ }
56
+ })
57
+ ```
58
+
59
+ ## 検出ルール
60
+
61
+ | ルール | 説明 | 重大度 |
62
+ |--------|------|--------|
63
+ | `no-eval` | `eval()` の使用 | critical |
64
+ | `no-string-timeout` | `setTimeout/setInterval` への文字列引数 | critical |
65
+ | `no-storage-access` | `localStorage/sessionStorage` アクセス | critical |
66
+ | `no-cookie-access` | `document.cookie` アクセス | critical |
67
+ | `no-indexeddb-access` | `indexedDB` アクセス | critical |
68
+ | `no-storage-event` | `addEventListener('storage')` / `onstorage` | critical |
69
+ | `no-navigator-access` | `navigator.*` アクセス | critical |
70
+ | `no-dangerous-dom` | `innerHTML` 代入 / `createElement('script')` | critical |
71
+ | `no-global-override` | `window/document/navigator` の改ざん | critical |
72
+ | `no-prototype-pollution` | `Object.prototype` 汚染 | critical |
73
+ | `no-obfuscation` | `atob/btoa/String.fromCharCode` 等 | critical |
74
+ | `no-external-import` | 外部 URL からの `import` | critical |
75
+ | `no-network-without-permission` | 未許可ドメインへの通信 | critical |
76
+
77
+ ## API リファレンス
78
+
79
+ ### クラス
80
+
81
+ - **`CodeSecurityService`** - セキュリティ解析サービス
82
+ - `validate(request: ValidateCodeRequest): ValidateCodeResponse`
83
+
84
+ ### 関数
85
+
86
+ - **`analyzeCodeSecurity(code, permissions?)`** - コードの AST 解析を実行
87
+ - **`calculateSecurityScore(signals)`** - セキュリティスコアを算出(0-100)
88
+ - **`getSecurityVerdict(score)`** - スコアから判定結果を返す(`APPROVE` / `REVIEW` / `REJECT`)
89
+ - **`determineFileContext(filePath)`** - ファイルパスからコンテキストを判定
90
+ - **`adjustViolationSeverity(rule, severity, context)`** - コンテキストに基づき重大度を調整
91
+
92
+ ### 型
93
+
94
+ - `ValidateCodeRequest` / `ValidateCodeResponse`
95
+ - `SecuritySignals` / `Violation`
96
+ - `CodePermissions` / `FileContext`
97
+
98
+ ## License
99
+
100
+ MIT
@@ -0,0 +1,6 @@
1
+ import type { SecuritySignals, CodePermissions } from './types.js';
2
+ /**
3
+ * コードのセキュリティ解析を実行
4
+ */
5
+ export declare function analyzeCodeSecurity(code: string, permissions?: CodePermissions): SecuritySignals;
6
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAChB,MAAM,YAAY,CAAA;AAkCnB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,eAAe,GAC5B,eAAe,CAqajB"}
@@ -0,0 +1,278 @@
1
+ import * as acorn from 'acorn';
2
+ import * as walk from 'acorn-walk';
3
+ import { calculateEntropy, calculateAverageEntropy, extractDomains, getCalleeName, getLocation, ALLOWED_DOMAINS } from './utils/helpers.js';
4
+ /**
5
+ * エントロピー閾値
6
+ * GLSLシェーダーや複雑な正規のコードを許容するため7.0に設定
7
+ */
8
+ const ENTROPY_THRESHOLD = 7.0;
9
+ /**
10
+ * Violationオブジェクトを作成するヘルパー関数
11
+ */
12
+ function createViolation(rule, severity, message, node) {
13
+ const location = node ? getLocation(node) : undefined;
14
+ return {
15
+ rule,
16
+ severity,
17
+ message,
18
+ ...(location && { location }),
19
+ };
20
+ }
21
+ /**
22
+ * コードのセキュリティ解析を実行
23
+ */
24
+ export function analyzeCodeSecurity(code, permissions) {
25
+ const ast = acorn.parse(code, {
26
+ ecmaVersion: 'latest',
27
+ sourceType: 'module',
28
+ locations: true,
29
+ });
30
+ const signals = {
31
+ hasEval: false,
32
+ hasDynamicCodeExecution: false,
33
+ hasNetworkAPI: false,
34
+ hasNetworkWithoutPermission: false,
35
+ hasDynamicURLConstruction: false,
36
+ hasObfuscatedCode: false,
37
+ hasGlobalVariableOverride: false,
38
+ hasStorageAccess: false,
39
+ hasNavigatorAccess: false,
40
+ hasDangerousDOMManipulation: false,
41
+ entropy: 0,
42
+ suspiciousVariableNames: false,
43
+ importedPackages: [],
44
+ referencedDomains: [],
45
+ detectedViolations: [],
46
+ };
47
+ const urlStrings = [];
48
+ const stringLiterals = [];
49
+ const variableNames = [];
50
+ walk.ancestor(ast, {
51
+ // 1. コード実行系
52
+ CallExpression(node, ancestors) {
53
+ const calleeName = getCalleeName(node.callee);
54
+ // eval検出
55
+ if (calleeName === 'eval') {
56
+ signals.hasEval = true;
57
+ signals.detectedViolations.push(createViolation('no-eval', 'critical', 'eval()の使用は禁止されています', node));
58
+ }
59
+ // setTimeout/setInterval の文字列引数
60
+ if (['setTimeout', 'setInterval'].includes(calleeName || '')) {
61
+ const firstArg = node.arguments[0];
62
+ if (firstArg?.type === 'Literal' && typeof firstArg.value === 'string') {
63
+ signals.hasDynamicCodeExecution = true;
64
+ signals.detectedViolations.push(createViolation('no-string-timeout', 'critical', `${calleeName}に文字列を渡すことは禁止されています`, node));
65
+ }
66
+ }
67
+ // ネットワークAPI検出
68
+ if (['fetch', 'XMLHttpRequest'].includes(calleeName || '')) {
69
+ signals.hasNetworkAPI = true;
70
+ // 引数からURL抽出
71
+ const urlArg = node.arguments[0];
72
+ if (urlArg?.type === 'Literal' && typeof urlArg.value === 'string') {
73
+ urlStrings.push(urlArg.value);
74
+ }
75
+ else {
76
+ // 動的URL構築の疑い
77
+ signals.hasDynamicURLConstruction = true;
78
+ }
79
+ }
80
+ // WebSocket検出
81
+ if (calleeName === 'WebSocket') {
82
+ signals.hasNetworkAPI = true;
83
+ const urlArg = node.arguments[0];
84
+ if (urlArg?.type === 'Literal' && typeof urlArg.value === 'string') {
85
+ urlStrings.push(urlArg.value);
86
+ }
87
+ }
88
+ // navigator.sendBeacon検出
89
+ if (node.callee.type === 'MemberExpression') {
90
+ const obj = node.callee.object;
91
+ const prop = node.callee.property;
92
+ if (obj?.type === 'Identifier' &&
93
+ obj.name === 'navigator' &&
94
+ prop?.type === 'Identifier' &&
95
+ prop.name === 'sendBeacon') {
96
+ signals.hasNetworkAPI = true;
97
+ signals.hasNavigatorAccess = true;
98
+ signals.detectedViolations.push(createViolation('no-navigator-access', 'critical', 'navigator.sendBeacon()の使用は禁止されています', node));
99
+ }
100
+ }
101
+ // 危険なDOM操作メソッド検出
102
+ if (['insertAdjacentHTML'].includes(calleeName || '')) {
103
+ signals.hasDangerousDOMManipulation = true;
104
+ signals.detectedViolations.push(createViolation('no-dangerous-dom', 'critical', `${calleeName}()の使用は禁止されています(XSS攻撃のリスク)`, node));
105
+ }
106
+ // document.createElement('script') / document.createElement('iframe')
107
+ if (calleeName === 'createElement' && node.callee.type === 'MemberExpression') {
108
+ const obj = node.callee.object;
109
+ if (obj?.type === 'Identifier' && obj.name === 'document') {
110
+ const tagArg = node.arguments[0];
111
+ if (tagArg?.type === 'Literal' && typeof tagArg.value === 'string') {
112
+ const tagName = tagArg.value.toLowerCase();
113
+ if (['script', 'iframe'].includes(tagName)) {
114
+ signals.hasDangerousDOMManipulation = true;
115
+ signals.detectedViolations.push(createViolation('no-dangerous-dom', 'critical', `document.createElement('${tagName}')の使用は禁止されています`, node));
116
+ }
117
+ }
118
+ }
119
+ }
120
+ // 難読化検出(Critical)
121
+ if (['atob', 'btoa', 'unescape', 'decodeURIComponent'].includes(calleeName || '')) {
122
+ signals.hasObfuscatedCode = true;
123
+ signals.detectedViolations.push(createViolation('no-obfuscation', 'critical', `難読化関数 ${calleeName}() の使用は禁止されています`, node));
124
+ }
125
+ // String.fromCharCode検出
126
+ if (node.callee.type === 'MemberExpression' &&
127
+ node.callee.object.type === 'Identifier' &&
128
+ node.callee.object.name === 'String' &&
129
+ node.callee.property.type === 'Identifier' &&
130
+ node.callee.property.name === 'fromCharCode') {
131
+ signals.hasObfuscatedCode = true;
132
+ signals.detectedViolations.push(createViolation('no-obfuscation', 'critical', 'String.fromCharCode()の使用は禁止されています', node));
133
+ }
134
+ // addEventListener('storage', ...) 検出
135
+ if (node.callee.type === 'MemberExpression' &&
136
+ node.callee.property.type === 'Identifier' &&
137
+ node.callee.property.name === 'addEventListener') {
138
+ const firstArg = node.arguments[0];
139
+ if (firstArg?.type === 'Literal' && typeof firstArg.value === 'string' && firstArg.value === 'storage') {
140
+ signals.hasStorageAccess = true;
141
+ signals.detectedViolations.push(createViolation('no-storage-event', 'critical', "addEventListener('storage', ...)の使用は禁止されています(トークン傍受のリスク)", node));
142
+ }
143
+ }
144
+ },
145
+ // 2. グローバル変数改ざん
146
+ AssignmentExpression(node, _ancestors) {
147
+ const left = node.left;
148
+ // window.xxx = ... 検出
149
+ if (left.type === 'MemberExpression' &&
150
+ left.object.type === 'Identifier' &&
151
+ ['window', 'globalThis', 'document', 'navigator'].includes(left.object.name)) {
152
+ signals.hasGlobalVariableOverride = true;
153
+ if (left.object.name === 'navigator') {
154
+ signals.hasNavigatorAccess = true;
155
+ }
156
+ signals.detectedViolations.push(createViolation('no-global-override', 'critical', `グローバルオブジェクト ${left.object.name} の改ざんは禁止されています`, node));
157
+ }
158
+ // Object.prototype.xxx = ... 検出
159
+ if (left.type === 'MemberExpression' &&
160
+ left.object.type === 'MemberExpression' &&
161
+ left.object.property.type === 'Identifier' &&
162
+ left.object.property.name === 'prototype') {
163
+ signals.hasGlobalVariableOverride = true;
164
+ signals.detectedViolations.push(createViolation('no-prototype-pollution', 'critical', 'プロトタイプ汚染は禁止されています', node));
165
+ }
166
+ // onstorage への代入検出
167
+ if (left.type === 'MemberExpression' &&
168
+ left.property.type === 'Identifier' &&
169
+ left.property.name === 'onstorage') {
170
+ signals.hasStorageAccess = true;
171
+ signals.detectedViolations.push(createViolation('no-storage-event', 'critical', 'onstorageへの代入は禁止されています(トークン傍受のリスク)', node));
172
+ }
173
+ },
174
+ // 3. ストレージアクセス & Navigator アクセス & DOM操作
175
+ MemberExpression(node, ancestors) {
176
+ const objectName = node.object.type === 'Identifier'
177
+ ? node.object.name
178
+ : null;
179
+ const propertyName = node.property.type === 'Identifier'
180
+ ? node.property.name
181
+ : null;
182
+ // localStorage/sessionStorage検出
183
+ if (['localStorage', 'sessionStorage'].includes(objectName || '')) {
184
+ signals.hasStorageAccess = true;
185
+ signals.detectedViolations.push(createViolation('no-storage-access', 'critical', `${objectName}へのアクセスは禁止されています`, node));
186
+ }
187
+ // document.cookie検出
188
+ if (objectName === 'document' && propertyName === 'cookie') {
189
+ signals.hasStorageAccess = true;
190
+ signals.detectedViolations.push(createViolation('no-cookie-access', 'critical', 'Cookieへのアクセスは禁止されています', node));
191
+ }
192
+ // indexedDB検出
193
+ if (objectName === 'indexedDB') {
194
+ signals.hasStorageAccess = true;
195
+ signals.detectedViolations.push(createViolation('no-indexeddb-access', 'critical', 'IndexedDBへのアクセスは禁止されています', node));
196
+ }
197
+ // navigator.* すべてを禁止
198
+ if (objectName === 'navigator') {
199
+ signals.hasNavigatorAccess = true;
200
+ signals.detectedViolations.push(createViolation('no-navigator-access', 'critical', `navigator.${propertyName || '*'}へのアクセスは禁止されています(フィンガープリンティング防止)`, node));
201
+ }
202
+ // innerHTML / outerHTML への書き込み検出
203
+ if (['innerHTML', 'outerHTML'].includes(propertyName || '')) {
204
+ // 親がAssignmentExpressionで、leftがこのMemberExpressionの場合
205
+ const parent = ancestors[ancestors.length - 2];
206
+ if (parent?.type === 'AssignmentExpression' && parent.left === node) {
207
+ signals.hasDangerousDOMManipulation = true;
208
+ signals.detectedViolations.push(createViolation('no-dangerous-dom', 'critical', `${propertyName}への代入は禁止されています(XSS攻撃のリスク)`, node));
209
+ }
210
+ }
211
+ // document.head への要素追加検出
212
+ if (objectName === 'document' && propertyName === 'head') {
213
+ signals.hasDangerousDOMManipulation = true;
214
+ signals.detectedViolations.push(createViolation('no-dangerous-dom', 'critical', 'document.headへのアクセスは禁止されています(スクリプト注入のリスク)', node));
215
+ }
216
+ },
217
+ // 4. インポート解析
218
+ ImportDeclaration(node, _ancestors) {
219
+ const source = node.source.value;
220
+ signals.importedPackages.push(source);
221
+ // 外部URL import検出
222
+ if (source.startsWith('http://') || source.startsWith('https://')) {
223
+ signals.detectedViolations.push(createViolation('no-external-import', 'critical', '外部URLからのimportは禁止されています', node));
224
+ }
225
+ },
226
+ // 5. 変数名収集
227
+ Identifier(node, ancestors) {
228
+ variableNames.push(node.name);
229
+ // navigator 変数への直接参照も検出
230
+ if (node.name === 'navigator') {
231
+ const parent = ancestors[ancestors.length - 2];
232
+ if (parent?.type !== 'MemberExpression' || parent.object !== node) {
233
+ signals.hasNavigatorAccess = true;
234
+ signals.detectedViolations.push(createViolation('no-navigator-access', 'critical', 'navigatorオブジェクトへのアクセスは禁止されています', node));
235
+ }
236
+ }
237
+ },
238
+ // 6. 文字列リテラル収集(StringLiteral → Literal + string ガード)
239
+ Literal(node, _ancestors) {
240
+ if (typeof node.value !== 'string')
241
+ return;
242
+ stringLiterals.push(node.value);
243
+ // 16進数エスケープ・Unicodeエスケープの検出
244
+ const value = node.value;
245
+ if (/\\x[0-9a-fA-F]{2}/.test(value) || /\\u[0-9a-fA-F]{4}/.test(value)) {
246
+ signals.hasObfuscatedCode = true;
247
+ signals.detectedViolations.push(createViolation('no-obfuscation', 'critical', '16進数/Unicodeエスケープによる難読化は禁止されています', node));
248
+ }
249
+ },
250
+ });
251
+ // エントロピー計算
252
+ signals.entropy = calculateAverageEntropy(stringLiterals);
253
+ // 高エントロピー文字列の検出(Critical)
254
+ if (signals.entropy > ENTROPY_THRESHOLD) {
255
+ signals.hasObfuscatedCode = true;
256
+ signals.detectedViolations.push(createViolation('no-obfuscation', 'critical', `文字列のエントロピーが異常に高い(${signals.entropy.toFixed(2)})- 難読化の疑い`));
257
+ }
258
+ // 疑わしい変数名チェック(Critical)
259
+ const suspiciousVars = variableNames.filter(name => /^[_$][a-zA-Z0-9_$]{4,}$/.test(name) && calculateEntropy(name) > 3.5);
260
+ if (suspiciousVars.length > 0) {
261
+ signals.hasObfuscatedCode = true;
262
+ signals.suspiciousVariableNames = true;
263
+ signals.detectedViolations.push(createViolation('no-obfuscation', 'critical', `疑わしい変数名が検出されました: ${suspiciousVars.slice(0, 3).join(', ')}...`));
264
+ }
265
+ // URL解析
266
+ signals.referencedDomains = extractDomains(urlStrings);
267
+ // 権限チェック
268
+ if (signals.hasNetworkAPI) {
269
+ const allowedDomains = permissions?.network?.allowedDomains || [];
270
+ const hasUnauthorizedDomain = signals.referencedDomains.some(domain => !allowedDomains.includes(domain) && !ALLOWED_DOMAINS.includes(domain));
271
+ if (hasUnauthorizedDomain || signals.hasDynamicURLConstruction) {
272
+ signals.hasNetworkWithoutPermission = true;
273
+ signals.detectedViolations.push(createViolation('no-network-without-permission', 'critical', 'ネットワーク通信にはxrift.config.tsでの権限宣言が必要です'));
274
+ }
275
+ }
276
+ return signals;
277
+ }
278
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ValidateCodeRequest, ValidateCodeResponse } from './types.js';
2
+ /**
3
+ * コードセキュリティ解析サービス
4
+ */
5
+ export declare class CodeSecurityService {
6
+ /**
7
+ * コードを検証
8
+ */
9
+ validate(request: ValidateCodeRequest): ValidateCodeResponse;
10
+ }
11
+ export { analyzeCodeSecurity } from './analyzer.js';
12
+ export { calculateSecurityScore, getSecurityVerdict } from './scoring.js';
13
+ export { determineFileContext, adjustViolationSeverity } from './utils/file-context.js';
14
+ export * from './types.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAA;AAOnB;;GAEG;AACH,qBAAa,mBAAmB;IAC9B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,oBAAoB;CA+E7D;AAED,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACzE,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AACvF,cAAc,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,91 @@
1
+ import { analyzeCodeSecurity } from './analyzer.js';
2
+ import { calculateSecurityScore } from './scoring.js';
3
+ import { adjustViolationSeverity, determineFileContext } from './utils/file-context.js';
4
+ /**
5
+ * エントロピー閾値(analyzer.ts, scoring.tsと同じ値)
6
+ */
7
+ const ENTROPY_THRESHOLD = 7.0;
8
+ /**
9
+ * コードセキュリティ解析サービス
10
+ */
11
+ export class CodeSecurityService {
12
+ /**
13
+ * コードを検証
14
+ */
15
+ validate(request) {
16
+ // ファイルコンテキストを判定(指定されていない場合は自動判定)
17
+ const fileContext = request.fileContext || determineFileContext(request.code);
18
+ // セキュリティ解析実行
19
+ const signals = analyzeCodeSecurity(request.code, request.manifestConfig?.permissions);
20
+ // ファイルコンテキストに基づいて違反の重大度を調整
21
+ const adjustedViolations = signals.detectedViolations.map(violation => {
22
+ const adjustedSeverity = adjustViolationSeverity(violation.rule, violation.severity, fileContext);
23
+ return {
24
+ ...violation,
25
+ severity: adjustedSeverity
26
+ };
27
+ });
28
+ // セキュリティスコア計算
29
+ const securityScore = calculateSecurityScore(signals);
30
+ // 違反を分類(調整後の重大度で)
31
+ const critical = [];
32
+ const warnings = [];
33
+ for (const violation of adjustedViolations) {
34
+ if (violation.severity === 'critical') {
35
+ critical.push(violation);
36
+ }
37
+ else {
38
+ warnings.push(violation);
39
+ }
40
+ }
41
+ // 検出されたAPI一覧
42
+ const detectedAPIs = [];
43
+ if (signals.hasEval)
44
+ detectedAPIs.push('eval');
45
+ if (signals.hasDynamicCodeExecution)
46
+ detectedAPIs.push('setTimeout/setInterval(string)');
47
+ if (signals.hasNetworkAPI)
48
+ detectedAPIs.push('fetch/WebSocket/XMLHttpRequest');
49
+ if (signals.hasStorageAccess)
50
+ detectedAPIs.push('localStorage/sessionStorage/indexedDB/cookie');
51
+ if (signals.hasNavigatorAccess)
52
+ detectedAPIs.push('navigator');
53
+ if (signals.hasDangerousDOMManipulation)
54
+ detectedAPIs.push('innerHTML/outerHTML/createElement');
55
+ if (signals.hasObfuscatedCode)
56
+ detectedAPIs.push('obfuscation (atob/btoa/fromCharCode)');
57
+ // 疑わしいパターン
58
+ const suspiciousPatterns = [];
59
+ if (signals.hasDynamicURLConstruction)
60
+ suspiciousPatterns.push('動的URL構築');
61
+ if (signals.hasGlobalVariableOverride)
62
+ suspiciousPatterns.push('グローバル変数改ざん');
63
+ if (signals.entropy > ENTROPY_THRESHOLD)
64
+ suspiciousPatterns.push(`高エントロピー文字列 (${signals.entropy.toFixed(2)})`);
65
+ if (signals.suspiciousVariableNames)
66
+ suspiciousPatterns.push('疑わしい変数名');
67
+ // 外部依存パッケージ
68
+ const externalDependencies = signals.importedPackages.filter(pkg => pkg.startsWith('http://') || pkg.startsWith('https://'));
69
+ // Critical違反の有無のみで判定
70
+ const valid = critical.length === 0;
71
+ return {
72
+ valid,
73
+ securityScore,
74
+ violations: {
75
+ critical,
76
+ warnings
77
+ },
78
+ analysis: {
79
+ entropy: signals.entropy,
80
+ suspiciousPatterns,
81
+ detectedAPIs,
82
+ externalDependencies
83
+ }
84
+ };
85
+ }
86
+ }
87
+ export { analyzeCodeSecurity } from './analyzer.js';
88
+ export { calculateSecurityScore, getSecurityVerdict } from './scoring.js';
89
+ export { determineFileContext, adjustViolationSeverity } from './utils/file-context.js';
90
+ export * from './types.js';
91
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { SecuritySignals } from './types.js';
2
+ /**
3
+ * セキュリティスコアを計算(0-100、高いほど危険)
4
+ */
5
+ export declare function calculateSecurityScore(signals: SecuritySignals): number;
6
+ /**
7
+ * 判定基準:
8
+ * - score >= 70: 拒否
9
+ * - 50 <= score < 70: 要人的レビュー
10
+ * - score < 50: 自動承認
11
+ */
12
+ export declare function getSecurityVerdict(score: number): 'REJECT' | 'REVIEW' | 'APPROVE';
13
+ //# sourceMappingURL=scoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../src/scoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAQjD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAoCvE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAIjF"}
@@ -0,0 +1,58 @@
1
+ import { ALLOWED_PACKAGES } from './utils/helpers.js';
2
+ /**
3
+ * エントロピー閾値(analyzer.tsと同じ値)
4
+ */
5
+ const ENTROPY_THRESHOLD = 7.0;
6
+ /**
7
+ * セキュリティスコアを計算(0-100、高いほど危険)
8
+ */
9
+ export function calculateSecurityScore(signals) {
10
+ let score = 0;
11
+ // Critical violations(即100点 = 拒否)
12
+ if (signals.hasEval)
13
+ return 100;
14
+ if (signals.hasDynamicCodeExecution)
15
+ return 100;
16
+ if (signals.hasNetworkWithoutPermission)
17
+ return 100;
18
+ if (signals.hasGlobalVariableOverride)
19
+ return 100;
20
+ if (signals.hasStorageAccess)
21
+ return 100;
22
+ if (signals.hasNavigatorAccess)
23
+ return 100;
24
+ if (signals.hasDangerousDOMManipulation)
25
+ return 100;
26
+ if (signals.hasObfuscatedCode)
27
+ return 100;
28
+ // 疑わしいパターンの組み合わせ
29
+ if (signals.hasDynamicURLConstruction && signals.hasNetworkAPI) {
30
+ score += 40;
31
+ }
32
+ if (signals.entropy > ENTROPY_THRESHOLD) {
33
+ score += 15;
34
+ }
35
+ if (signals.suspiciousVariableNames) {
36
+ score += 10;
37
+ }
38
+ // 未許可パッケージ
39
+ const unknownPackages = signals.importedPackages.filter(pkg => !ALLOWED_PACKAGES.some(allowed => pkg.startsWith(allowed)));
40
+ score += unknownPackages.length * 20;
41
+ // 外部ドメイン参照(許可リスト外)
42
+ score += signals.referencedDomains.length * 25;
43
+ return Math.min(score, 100);
44
+ }
45
+ /**
46
+ * 判定基準:
47
+ * - score >= 70: 拒否
48
+ * - 50 <= score < 70: 要人的レビュー
49
+ * - score < 50: 自動承認
50
+ */
51
+ export function getSecurityVerdict(score) {
52
+ if (score >= 70)
53
+ return 'REJECT';
54
+ if (score >= 50)
55
+ return 'REVIEW';
56
+ return 'APPROVE';
57
+ }
58
+ //# sourceMappingURL=scoring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring.js","sourceRoot":"","sources":["../src/scoring.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD;;GAEG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAE7B;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAwB;IAC7D,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,kCAAkC;IAClC,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO,GAAG,CAAA;IAC/B,IAAI,OAAO,CAAC,uBAAuB;QAAE,OAAO,GAAG,CAAA;IAC/C,IAAI,OAAO,CAAC,2BAA2B;QAAE,OAAO,GAAG,CAAA;IACnD,IAAI,OAAO,CAAC,yBAAyB;QAAE,OAAO,GAAG,CAAA;IACjD,IAAI,OAAO,CAAC,gBAAgB;QAAE,OAAO,GAAG,CAAA;IACxC,IAAI,OAAO,CAAC,kBAAkB;QAAE,OAAO,GAAG,CAAA;IAC1C,IAAI,OAAO,CAAC,2BAA2B;QAAE,OAAO,GAAG,CAAA;IACnD,IAAI,OAAO,CAAC,iBAAiB;QAAE,OAAO,GAAG,CAAA;IAEzC,iBAAiB;IACjB,IAAI,OAAO,CAAC,yBAAyB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC/D,KAAK,IAAI,EAAE,CAAA;IACb,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,GAAG,iBAAiB,EAAE,CAAC;QACxC,KAAK,IAAI,EAAE,CAAA;IACb,CAAC;IAED,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;QACpC,KAAK,IAAI,EAAE,CAAA;IACb,CAAC;IAED,WAAW;IACX,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CACrD,GAAG,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAClE,CAAA;IACD,KAAK,IAAI,eAAe,CAAC,MAAM,GAAG,EAAE,CAAA;IAEpC,mBAAmB;IACnB,KAAK,IAAI,OAAO,CAAC,iBAAiB,CAAC,MAAM,GAAG,EAAE,CAAA;IAE9C,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAA;IAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,QAAQ,CAAA;IAChC,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * セキュリティ解析の違反情報
3
+ */
4
+ export interface Violation {
5
+ rule: string;
6
+ severity: 'critical' | 'warning';
7
+ message: string;
8
+ location?: {
9
+ line: number;
10
+ column: number;
11
+ code: string;
12
+ };
13
+ }
14
+ /**
15
+ * セキュリティシグナル(検出された脅威の情報)
16
+ */
17
+ export interface SecuritySignals {
18
+ hasEval: boolean;
19
+ hasDynamicCodeExecution: boolean;
20
+ hasNetworkAPI: boolean;
21
+ hasNetworkWithoutPermission: boolean;
22
+ hasDynamicURLConstruction: boolean;
23
+ hasObfuscatedCode: boolean;
24
+ hasGlobalVariableOverride: boolean;
25
+ hasStorageAccess: boolean;
26
+ hasNavigatorAccess: boolean;
27
+ hasDangerousDOMManipulation: boolean;
28
+ entropy: number;
29
+ suspiciousVariableNames: boolean;
30
+ importedPackages: string[];
31
+ referencedDomains: string[];
32
+ detectedViolations: Violation[];
33
+ }
34
+ /**
35
+ * コードの権限設定
36
+ */
37
+ export interface CodePermissions {
38
+ network?: {
39
+ allowedDomains: string[];
40
+ };
41
+ }
42
+ /**
43
+ * ファイルコンテキスト(検証ルールの調整に使用)
44
+ */
45
+ export interface FileContext {
46
+ filePath: string;
47
+ isUserCode: boolean;
48
+ isSharedLibrary: boolean;
49
+ isBundledDependency: boolean;
50
+ }
51
+ /**
52
+ * コード検証リクエスト
53
+ */
54
+ export interface ValidateCodeRequest {
55
+ code: string;
56
+ sourceMap?: string;
57
+ packageJson: {
58
+ dependencies: Record<string, string>;
59
+ };
60
+ manifestConfig?: {
61
+ permissions?: CodePermissions;
62
+ };
63
+ fileContext?: FileContext;
64
+ }
65
+ /**
66
+ * コード検証レスポンス
67
+ */
68
+ export interface ValidateCodeResponse {
69
+ valid: boolean;
70
+ securityScore: number;
71
+ violations: {
72
+ critical: Violation[];
73
+ warnings: Violation[];
74
+ };
75
+ analysis: {
76
+ entropy: number;
77
+ suspiciousPatterns: string[];
78
+ detectedAPIs: string[];
79
+ externalDependencies: string[];
80
+ };
81
+ }
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAA;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,uBAAuB,EAAE,OAAO,CAAA;IAChC,aAAa,EAAE,OAAO,CAAA;IACtB,2BAA2B,EAAE,OAAO,CAAA;IACpC,yBAAyB,EAAE,OAAO,CAAA;IAClC,iBAAiB,EAAE,OAAO,CAAA;IAC1B,yBAAyB,EAAE,OAAO,CAAA;IAClC,gBAAgB,EAAE,OAAO,CAAA;IACzB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,2BAA2B,EAAE,OAAO,CAAA;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,uBAAuB,EAAE,OAAO,CAAA;IAChC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,kBAAkB,EAAE,SAAS,EAAE,CAAA;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE;QACR,cAAc,EAAE,MAAM,EAAE,CAAA;KACzB,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,eAAe,EAAE,OAAO,CAAA;IACxB,mBAAmB,EAAE,OAAO,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE;QACX,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACrC,CAAA;IACD,cAAc,CAAC,EAAE;QACf,WAAW,CAAC,EAAE,eAAe,CAAA;KAC9B,CAAA;IACD,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE;QACV,QAAQ,EAAE,SAAS,EAAE,CAAA;QACrB,QAAQ,EAAE,SAAS,EAAE,CAAA;KACtB,CAAA;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAA;QACf,kBAAkB,EAAE,MAAM,EAAE,CAAA;QAC5B,YAAY,EAAE,MAAM,EAAE,CAAA;QACtB,oBAAoB,EAAE,MAAM,EAAE,CAAA;KAC/B,CAAA;CACF"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import type { FileContext } from '../types.js';
2
+ /**
3
+ * ファイルパスからコンテキストを判定
4
+ *
5
+ * 判定ロジック:
6
+ * - __federation_expose_World: ユーザーコード (最も厳格)
7
+ * - __federation_shared_: 共有ライブラリ (Module Federationが自動生成、緩和可能)
8
+ * - __federation_fn_import: Module Federationインフラ (厳格)
9
+ * - remoteEntry.js: Module Federationエントリーポイント (Module Federationが自動生成、緩和可能)
10
+ * - その他: バンドルされた依存ライブラリ (緩和可能)
11
+ */
12
+ export declare function determineFileContext(filePath: string): FileContext;
13
+ /**
14
+ * ファイルコンテキストに基づいて違反の重大度を調整
15
+ */
16
+ export declare function adjustViolationSeverity(rule: string, originalSeverity: 'critical' | 'warning', context: FileContext): 'critical' | 'warning';
17
+ /**
18
+ * ファイルコンテキストの説明を生成(デバッグ用)
19
+ */
20
+ export declare function describeFileContext(context: FileContext): string;
21
+ //# sourceMappingURL=file-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-context.d.ts","sourceRoot":"","sources":["../../src/utils/file-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAwBlE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,UAAU,GAAG,SAAS,EACxC,OAAO,EAAE,WAAW,GACnB,UAAU,GAAG,SAAS,CAwCxB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAkBhE"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * ファイルパスからコンテキストを判定
3
+ *
4
+ * 判定ロジック:
5
+ * - __federation_expose_World: ユーザーコード (最も厳格)
6
+ * - __federation_shared_: 共有ライブラリ (Module Federationが自動生成、緩和可能)
7
+ * - __federation_fn_import: Module Federationインフラ (厳格)
8
+ * - remoteEntry.js: Module Federationエントリーポイント (Module Federationが自動生成、緩和可能)
9
+ * - その他: バンドルされた依存ライブラリ (緩和可能)
10
+ */
11
+ export function determineFileContext(filePath) {
12
+ const fileName = filePath.split('/').pop() || filePath;
13
+ // 1. ユーザーコード(__federation_expose_World-*.js)
14
+ const isUserCode = fileName.includes('__federation_expose_World-') && fileName.endsWith('.js');
15
+ // 2. 共有ライブラリ(__federation_shared_*/*.js)
16
+ const isSharedLibrary = fileName.startsWith('__federation_shared_') ||
17
+ filePath.includes('__federation_shared_');
18
+ // 3. バンドルされた依存ライブラリ(その他の*.js)
19
+ const isBundledDependency = !isUserCode &&
20
+ !isSharedLibrary &&
21
+ !fileName.includes('__federation_fn_import') &&
22
+ fileName !== 'remoteEntry.js';
23
+ return {
24
+ filePath: fileName,
25
+ isUserCode,
26
+ isSharedLibrary,
27
+ isBundledDependency
28
+ };
29
+ }
30
+ /**
31
+ * ファイルコンテキストに基づいて違反の重大度を調整
32
+ */
33
+ export function adjustViolationSeverity(rule, originalSeverity, context) {
34
+ // ユーザーコードは常に厳格
35
+ if (context.isUserCode) {
36
+ return originalSeverity;
37
+ }
38
+ // __federation_fn_import は常に厳格
39
+ const fileName = context.filePath;
40
+ if (fileName.includes('__federation_fn_import')) {
41
+ return originalSeverity;
42
+ }
43
+ // 共有ライブラリ、バンドル依存、remoteEntryは一部のルールを緩和
44
+ const isRemoteEntry = fileName === 'remoteEntry.js';
45
+ if (context.isSharedLibrary || context.isBundledDependency || isRemoteEntry) {
46
+ const technicalViolations = [
47
+ 'no-obfuscation',
48
+ 'no-dangerous-dom',
49
+ 'no-navigator-access',
50
+ 'no-prototype-pollution',
51
+ 'no-global-override',
52
+ 'no-network-without-permission',
53
+ ];
54
+ if (technicalViolations.includes(rule)) {
55
+ return 'warning';
56
+ }
57
+ const criticalViolations = [
58
+ 'no-eval',
59
+ 'no-storage-access',
60
+ 'no-storage-event',
61
+ ];
62
+ if (criticalViolations.includes(rule)) {
63
+ return 'critical';
64
+ }
65
+ }
66
+ return originalSeverity;
67
+ }
68
+ /**
69
+ * ファイルコンテキストの説明を生成(デバッグ用)
70
+ */
71
+ export function describeFileContext(context) {
72
+ if (context.isUserCode) {
73
+ return 'ユーザーコード(最も厳格に検証)';
74
+ }
75
+ if (context.isSharedLibrary) {
76
+ return '共有ライブラリ(Module Federation自動生成、一部ルールを緩和)';
77
+ }
78
+ if (context.isBundledDependency) {
79
+ return 'バンドルされた依存ライブラリ(技術的違反を緩和)';
80
+ }
81
+ const fileName = context.filePath;
82
+ if (fileName === 'remoteEntry.js') {
83
+ return 'Module Federationエントリーポイント(Module Federation自動生成、一部ルールを緩和)';
84
+ }
85
+ if (fileName.includes('__federation_fn_import')) {
86
+ return 'Module Federation動的インポート(厳格に検証)';
87
+ }
88
+ return 'その他のファイル(標準的な検証)';
89
+ }
90
+ //# sourceMappingURL=file-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-context.js","sourceRoot":"","sources":["../../src/utils/file-context.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,QAAQ,CAAA;IAEtD,6CAA6C;IAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,4BAA4B,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE9F,yCAAyC;IACzC,MAAM,eAAe,GACnB,QAAQ,CAAC,UAAU,CAAC,sBAAsB,CAAC;QAC3C,QAAQ,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAA;IAE3C,8BAA8B;IAC9B,MAAM,mBAAmB,GACvB,CAAC,UAAU;QACX,CAAC,eAAe;QAChB,CAAC,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAC5C,QAAQ,KAAK,gBAAgB,CAAA;IAE/B,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,UAAU;QACV,eAAe;QACf,mBAAmB;KACpB,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAY,EACZ,gBAAwC,EACxC,OAAoB;IAEpB,eAAe;IACf,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;IACjC,IAAI,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;QAChD,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED,uCAAuC;IACvC,MAAM,aAAa,GAAG,QAAQ,KAAK,gBAAgB,CAAA;IACnD,IAAI,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,mBAAmB,IAAI,aAAa,EAAE,CAAC;QAC5E,MAAM,mBAAmB,GAAG;YAC1B,gBAAgB;YAChB,kBAAkB;YAClB,qBAAqB;YACrB,wBAAwB;YACxB,oBAAoB;YACpB,+BAA+B;SAChC,CAAA;QAED,IAAI,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,MAAM,kBAAkB,GAAG;YACzB,SAAS;YACT,mBAAmB;YACnB,kBAAkB;SACnB,CAAA;QAED,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,OAAO,UAAU,CAAA;QACnB,CAAC;IACH,CAAC;IAED,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAoB;IACtD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,kBAAkB,CAAA;IAC3B,CAAC;IACD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,OAAO,yCAAyC,CAAA;IAClD,CAAC;IACD,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAChC,OAAO,0BAA0B,CAAA;IACnC,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;IACjC,IAAI,QAAQ,KAAK,gBAAgB,EAAE,CAAC;QAClC,OAAO,4DAA4D,CAAA;IACrE,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;QAChD,OAAO,iCAAiC,CAAA;IAC1C,CAAC;IACD,OAAO,kBAAkB,CAAA;AAC3B,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { Node } from 'acorn';
2
+ /**
3
+ * シャノンエントロピーを計算(0-8の範囲)
4
+ */
5
+ export declare function calculateEntropy(str: string): number;
6
+ /**
7
+ * 文字列配列の平均エントロピーを計算
8
+ */
9
+ export declare function calculateAverageEntropy(strings: string[]): number;
10
+ /**
11
+ * URL文字列からドメイン名を抽出
12
+ */
13
+ export declare function extractDomains(urls: string[]): string[];
14
+ /**
15
+ * CallExpressionの呼び出し先名を取得
16
+ */
17
+ export declare function getCalleeName(callee: any): string | null;
18
+ /**
19
+ * ASTノードから位置情報を取得
20
+ */
21
+ export declare function getLocation(node: Node): {
22
+ line: number;
23
+ column: number;
24
+ code: string;
25
+ } | undefined;
26
+ /**
27
+ * 許可されたパッケージリスト
28
+ */
29
+ export declare const ALLOWED_PACKAGES: string[];
30
+ /**
31
+ * 許可されたドメイン(CDN)
32
+ */
33
+ export declare const ALLOWED_DOMAINS: string[];
34
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAepD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAUjE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAUvD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAWxD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQlG;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,UAQ5B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UAI3B,CAAA"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * シャノンエントロピーを計算(0-8の範囲)
3
+ */
4
+ export function calculateEntropy(str) {
5
+ if (str.length === 0)
6
+ return 0;
7
+ const frequency = {};
8
+ for (const char of str) {
9
+ frequency[char] = (frequency[char] || 0) + 1;
10
+ }
11
+ let entropy = 0;
12
+ for (const char in frequency) {
13
+ const p = frequency[char] / str.length;
14
+ entropy -= p * Math.log2(p);
15
+ }
16
+ return entropy;
17
+ }
18
+ /**
19
+ * 文字列配列の平均エントロピーを計算
20
+ */
21
+ export function calculateAverageEntropy(strings) {
22
+ if (strings.length === 0)
23
+ return 0;
24
+ const entropies = strings
25
+ .filter(s => s.length > 20) // 20文字以上の文字列のみ対象
26
+ .map(calculateEntropy);
27
+ return entropies.length > 0
28
+ ? entropies.reduce((a, b) => a + b, 0) / entropies.length
29
+ : 0;
30
+ }
31
+ /**
32
+ * URL文字列からドメイン名を抽出
33
+ */
34
+ export function extractDomains(urls) {
35
+ return urls
36
+ .map(url => {
37
+ try {
38
+ return new URL(url).hostname;
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ })
44
+ .filter((domain) => domain !== null);
45
+ }
46
+ /**
47
+ * CallExpressionの呼び出し先名を取得
48
+ */
49
+ export function getCalleeName(callee) {
50
+ if (callee.type === 'Identifier') {
51
+ return callee.name;
52
+ }
53
+ if (callee.type === 'MemberExpression') {
54
+ const property = callee.property;
55
+ if (property.type === 'Identifier') {
56
+ return property.name;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ /**
62
+ * ASTノードから位置情報を取得
63
+ */
64
+ export function getLocation(node) {
65
+ if (!node.loc)
66
+ return undefined;
67
+ return {
68
+ line: node.loc.start.line,
69
+ column: node.loc.start.column,
70
+ code: '(code snippet)'
71
+ };
72
+ }
73
+ /**
74
+ * 許可されたパッケージリスト
75
+ */
76
+ export const ALLOWED_PACKAGES = [
77
+ 'react',
78
+ 'react-dom',
79
+ 'three',
80
+ '@react-three/fiber',
81
+ '@react-three/rapier',
82
+ '@react-three/drei',
83
+ '@xrift/world-sdk',
84
+ ];
85
+ /**
86
+ * 許可されたドメイン(CDN)
87
+ */
88
+ export const ALLOWED_DOMAINS = [
89
+ 'cdn.jsdelivr.net',
90
+ 'unpkg.com',
91
+ 'esm.sh',
92
+ ];
93
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/utils/helpers.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@xrift/code-security",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Code security analyzer powered by acorn",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "clean": "rm -rf dist",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "security",
26
+ "code-analysis",
27
+ "acorn"
28
+ ],
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "acorn": "^8.14.0",
32
+ "acorn-walk": "^8.3.4"
33
+ },
34
+ "devDependencies": {
35
+ "typescript": "^5.7.0",
36
+ "vitest": "^3.0.0"
37
+ }
38
+ }