native-update 1.0.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/CapacitorNativeUpdate.podspec +18 -0
- package/LICENSE +21 -0
- package/Readme.md +451 -0
- package/android/build.gradle +92 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +8 -0
- package/android/gradle.properties +17 -0
- package/android/proguard-rules.pro +29 -0
- package/android/settings.gradle +2 -0
- package/android/src/main/AndroidManifest.xml +34 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/AppReviewPlugin.kt +153 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/AppUpdatePlugin.kt +275 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundNotificationManager.kt +390 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateManager.kt +46 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdatePlugin.kt +333 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateWorker.kt +251 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/CapacitorNativeUpdatePlugin.kt +265 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/LiveUpdatePlugin.kt +526 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/NotificationActionReceiver.kt +99 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/SecurityManager.kt +249 -0
- package/dist/esm/__tests__/bundle-manager.test.d.ts +1 -0
- package/dist/esm/__tests__/bundle-manager.test.js +123 -0
- package/dist/esm/__tests__/bundle-manager.test.js.map +1 -0
- package/dist/esm/__tests__/config.test.d.ts +1 -0
- package/dist/esm/__tests__/config.test.js +69 -0
- package/dist/esm/__tests__/config.test.js.map +1 -0
- package/dist/esm/__tests__/integration.test.d.ts +1 -0
- package/dist/esm/__tests__/integration.test.js +78 -0
- package/dist/esm/__tests__/integration.test.js.map +1 -0
- package/dist/esm/__tests__/security.test.d.ts +1 -0
- package/dist/esm/__tests__/security.test.js +54 -0
- package/dist/esm/__tests__/security.test.js.map +1 -0
- package/dist/esm/__tests__/version-manager.test.d.ts +1 -0
- package/dist/esm/__tests__/version-manager.test.js +45 -0
- package/dist/esm/__tests__/version-manager.test.js.map +1 -0
- package/dist/esm/app-review/app-review-manager.d.ts +24 -0
- package/dist/esm/app-review/app-review-manager.js +195 -0
- package/dist/esm/app-review/app-review-manager.js.map +1 -0
- package/dist/esm/app-review/index.d.ts +5 -0
- package/dist/esm/app-review/index.js +6 -0
- package/dist/esm/app-review/index.js.map +1 -0
- package/dist/esm/app-review/platform-review-handler.d.ts +20 -0
- package/dist/esm/app-review/platform-review-handler.js +138 -0
- package/dist/esm/app-review/platform-review-handler.js.map +1 -0
- package/dist/esm/app-review/review-conditions-checker.d.ts +22 -0
- package/dist/esm/app-review/review-conditions-checker.js +155 -0
- package/dist/esm/app-review/review-conditions-checker.js.map +1 -0
- package/dist/esm/app-review/review-rate-limiter.d.ts +23 -0
- package/dist/esm/app-review/review-rate-limiter.js +164 -0
- package/dist/esm/app-review/review-rate-limiter.js.map +1 -0
- package/dist/esm/app-review/types.d.ts +41 -0
- package/dist/esm/app-review/types.js +2 -0
- package/dist/esm/app-review/types.js.map +1 -0
- package/dist/esm/app-update/app-update-checker.d.ts +13 -0
- package/dist/esm/app-update/app-update-checker.js +104 -0
- package/dist/esm/app-update/app-update-checker.js.map +1 -0
- package/dist/esm/app-update/app-update-installer.d.ts +19 -0
- package/dist/esm/app-update/app-update-installer.js +123 -0
- package/dist/esm/app-update/app-update-installer.js.map +1 -0
- package/dist/esm/app-update/app-update-manager.d.ts +28 -0
- package/dist/esm/app-update/app-update-manager.js +199 -0
- package/dist/esm/app-update/app-update-manager.js.map +1 -0
- package/dist/esm/app-update/app-update-notifier.d.ts +14 -0
- package/dist/esm/app-update/app-update-notifier.js +100 -0
- package/dist/esm/app-update/app-update-notifier.js.map +1 -0
- package/dist/esm/app-update/index.d.ts +6 -0
- package/dist/esm/app-update/index.js +7 -0
- package/dist/esm/app-update/index.js.map +1 -0
- package/dist/esm/app-update/platform-app-update.d.ts +19 -0
- package/dist/esm/app-update/platform-app-update.js +129 -0
- package/dist/esm/app-update/platform-app-update.js.map +1 -0
- package/dist/esm/app-update/types.d.ts +58 -0
- package/dist/esm/app-update/types.js +12 -0
- package/dist/esm/app-update/types.js.map +1 -0
- package/dist/esm/background-update/background-scheduler.d.ts +17 -0
- package/dist/esm/background-update/background-scheduler.js +195 -0
- package/dist/esm/background-update/background-scheduler.js.map +1 -0
- package/dist/esm/background-update/index.d.ts +3 -0
- package/dist/esm/background-update/index.js +3 -0
- package/dist/esm/background-update/index.js.map +1 -0
- package/dist/esm/background-update/notification-manager.d.ts +29 -0
- package/dist/esm/background-update/notification-manager.js +89 -0
- package/dist/esm/background-update/notification-manager.js.map +1 -0
- package/dist/esm/core/analytics.d.ts +70 -0
- package/dist/esm/core/analytics.js +137 -0
- package/dist/esm/core/analytics.js.map +1 -0
- package/dist/esm/core/cache-manager.d.ts +72 -0
- package/dist/esm/core/cache-manager.js +275 -0
- package/dist/esm/core/cache-manager.js.map +1 -0
- package/dist/esm/core/config.d.ts +48 -0
- package/dist/esm/core/config.js +83 -0
- package/dist/esm/core/config.js.map +1 -0
- package/dist/esm/core/errors.d.ts +51 -0
- package/dist/esm/core/errors.js +80 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/logger.d.ts +21 -0
- package/dist/esm/core/logger.js +109 -0
- package/dist/esm/core/logger.js.map +1 -0
- package/dist/esm/core/performance.d.ts +53 -0
- package/dist/esm/core/performance.js +140 -0
- package/dist/esm/core/performance.js.map +1 -0
- package/dist/esm/core/plugin-manager.d.ts +66 -0
- package/dist/esm/core/plugin-manager.js +148 -0
- package/dist/esm/core/plugin-manager.js.map +1 -0
- package/dist/esm/core/security.d.ts +93 -0
- package/dist/esm/core/security.js +315 -0
- package/dist/esm/core/security.js.map +1 -0
- package/dist/esm/definitions.d.ts +639 -0
- package/dist/esm/definitions.js +103 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +12 -0
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/live-update/bundle-manager.d.ts +94 -0
- package/dist/esm/live-update/bundle-manager.js +310 -0
- package/dist/esm/live-update/bundle-manager.js.map +1 -0
- package/dist/esm/live-update/certificate-pinning.d.ts +38 -0
- package/dist/esm/live-update/certificate-pinning.js +78 -0
- package/dist/esm/live-update/certificate-pinning.js.map +1 -0
- package/dist/esm/live-update/download-manager.d.ts +67 -0
- package/dist/esm/live-update/download-manager.js +319 -0
- package/dist/esm/live-update/download-manager.js.map +1 -0
- package/dist/esm/live-update/update-manager.d.ts +52 -0
- package/dist/esm/live-update/update-manager.js +294 -0
- package/dist/esm/live-update/update-manager.js.map +1 -0
- package/dist/esm/live-update/version-manager.d.ts +84 -0
- package/dist/esm/live-update/version-manager.js +335 -0
- package/dist/esm/live-update/version-manager.js.map +1 -0
- package/dist/esm/plugin.d.ts +6 -0
- package/dist/esm/plugin.js +283 -0
- package/dist/esm/plugin.js.map +1 -0
- package/dist/esm/security/crypto.d.ts +25 -0
- package/dist/esm/security/crypto.js +70 -0
- package/dist/esm/security/crypto.js.map +1 -0
- package/dist/esm/security/validator.d.ts +60 -0
- package/dist/esm/security/validator.js +143 -0
- package/dist/esm/security/validator.js.map +1 -0
- package/dist/esm/web.d.ts +74 -0
- package/dist/esm/web.js +595 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +2 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.esm.js +2 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/plugin.js +3 -0
- package/dist/plugin.js.map +1 -0
- package/docs/APP_REVIEW_GUIDE.md +768 -0
- package/docs/BUNDLE_SIGNING.md +264 -0
- package/docs/LIVE_UPDATES_GUIDE.md +650 -0
- package/docs/MIGRATION.md +192 -0
- package/docs/NATIVE_UPDATES_GUIDE.md +694 -0
- package/docs/QUICK_START.md +606 -0
- package/docs/README.md +111 -0
- package/docs/REMAINING_FEATURES.md +139 -0
- package/docs/api/app-review-api.md +259 -0
- package/docs/api/app-update-api.md +238 -0
- package/docs/api/events-api.md +451 -0
- package/docs/api/live-update-api.md +265 -0
- package/docs/background-updates.md +392 -0
- package/docs/examples/advanced-scenarios.md +410 -0
- package/docs/examples/basic-usage.md +185 -0
- package/docs/features/app-reviews.md +975 -0
- package/docs/features/app-updates.md +785 -0
- package/docs/features/live-updates.md +633 -0
- package/docs/getting-started/configuration.md +468 -0
- package/docs/getting-started/installation.md +209 -0
- package/docs/getting-started/quick-start.md +379 -0
- package/docs/guides/deployment-guide.md +333 -0
- package/docs/guides/migration-from-codepush.md +142 -0
- package/docs/guides/security-best-practices.md +1057 -0
- package/docs/guides/testing-guide.md +373 -0
- package/docs/production-readiness.md +478 -0
- package/docs/security/certificate-pinning.md +122 -0
- package/docs/server-requirements.md +147 -0
- package/ios/Plugin/AppReview/AppReviewPlugin.swift +158 -0
- package/ios/Plugin/AppUpdate/AppUpdatePlugin.swift +234 -0
- package/ios/Plugin/BackgroundUpdate/BackgroundNotificationManager.swift +329 -0
- package/ios/Plugin/BackgroundUpdate/BackgroundUpdatePlugin.swift +396 -0
- package/ios/Plugin/CapacitorNativeUpdatePlugin.m +45 -0
- package/ios/Plugin/CapacitorNativeUpdatePlugin.swift +190 -0
- package/ios/Plugin/Info.plist +43 -0
- package/ios/Plugin/LiveUpdate/LiveUpdatePlugin.swift +689 -0
- package/ios/Plugin/LiveUpdate/WebViewConfiguration.swift +45 -0
- package/ios/Plugin/Security/SecurityManager.swift +289 -0
- package/package.json +90 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { ConfigManager } from './config';
|
|
2
|
+
import { ValidationError, ErrorCode } from './errors';
|
|
3
|
+
import { Logger } from './logger';
|
|
4
|
+
export class SecurityValidator {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.configManager = ConfigManager.getInstance();
|
|
7
|
+
this.logger = Logger.getInstance();
|
|
8
|
+
}
|
|
9
|
+
static getInstance() {
|
|
10
|
+
if (!SecurityValidator.instance) {
|
|
11
|
+
SecurityValidator.instance = new SecurityValidator();
|
|
12
|
+
}
|
|
13
|
+
return SecurityValidator.instance;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validate URL is HTTPS
|
|
17
|
+
*/
|
|
18
|
+
static validateUrl(url) {
|
|
19
|
+
try {
|
|
20
|
+
const parsed = new URL(url);
|
|
21
|
+
return parsed.protocol === 'https:';
|
|
22
|
+
}
|
|
23
|
+
catch (_a) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validate checksum format
|
|
29
|
+
*/
|
|
30
|
+
static validateChecksum(checksum) {
|
|
31
|
+
return /^[a-f0-9]{64}$/i.test(checksum);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Sanitize input string
|
|
35
|
+
*/
|
|
36
|
+
static sanitizeInput(input) {
|
|
37
|
+
if (!input)
|
|
38
|
+
return '';
|
|
39
|
+
return input.replace(/<[^>]*>/g, '').replace(/[^\w\s/.-]/g, '');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validate bundle size
|
|
43
|
+
*/
|
|
44
|
+
static validateBundleSize(size) {
|
|
45
|
+
const MAX_SIZE = 100 * 1024 * 1024; // 100MB
|
|
46
|
+
return size > 0 && size <= MAX_SIZE;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Calculate SHA-256 checksum of data
|
|
50
|
+
*/
|
|
51
|
+
async calculateChecksum(data) {
|
|
52
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
53
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
54
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Verify checksum matches expected value
|
|
58
|
+
*/
|
|
59
|
+
async verifyChecksum(data, expectedChecksum) {
|
|
60
|
+
if (!expectedChecksum) {
|
|
61
|
+
this.logger.warn('No checksum provided for verification');
|
|
62
|
+
return true; // Allow if no checksum provided
|
|
63
|
+
}
|
|
64
|
+
const actualChecksum = await this.calculateChecksum(data);
|
|
65
|
+
const isValid = actualChecksum === expectedChecksum.toLowerCase();
|
|
66
|
+
if (!isValid) {
|
|
67
|
+
this.logger.error('Checksum verification failed', {
|
|
68
|
+
expected: expectedChecksum,
|
|
69
|
+
actual: actualChecksum,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return isValid;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Alias for verifyChecksum for backward compatibility
|
|
76
|
+
*/
|
|
77
|
+
async validateChecksum(data, expectedChecksum) {
|
|
78
|
+
return this.verifyChecksum(data, expectedChecksum);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Verify digital signature using Web Crypto API
|
|
82
|
+
*/
|
|
83
|
+
async verifySignature(data, signature) {
|
|
84
|
+
if (!this.configManager.get('enableSignatureValidation')) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
const publicKey = this.configManager.get('publicKey');
|
|
88
|
+
if (!publicKey) {
|
|
89
|
+
throw new ValidationError(ErrorCode.SIGNATURE_INVALID, 'Public key not configured for signature validation');
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
// Import public key
|
|
93
|
+
const cryptoKey = await crypto.subtle.importKey('spki', this.pemToArrayBuffer(publicKey), {
|
|
94
|
+
name: 'RSA-PSS',
|
|
95
|
+
hash: 'SHA-256',
|
|
96
|
+
}, false, ['verify']);
|
|
97
|
+
// Verify signature
|
|
98
|
+
const isValid = await crypto.subtle.verify({
|
|
99
|
+
name: 'RSA-PSS',
|
|
100
|
+
saltLength: 32,
|
|
101
|
+
}, cryptoKey, this.base64ToArrayBuffer(signature), data);
|
|
102
|
+
if (!isValid) {
|
|
103
|
+
this.logger.error('Signature verification failed');
|
|
104
|
+
}
|
|
105
|
+
return isValid;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
this.logger.error('Signature verification error', error);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Convert PEM to ArrayBuffer
|
|
114
|
+
*/
|
|
115
|
+
pemToArrayBuffer(pem) {
|
|
116
|
+
const base64 = pem
|
|
117
|
+
.replace(/-----BEGIN PUBLIC KEY-----/g, '')
|
|
118
|
+
.replace(/-----END PUBLIC KEY-----/g, '')
|
|
119
|
+
.replace(/\s/g, '');
|
|
120
|
+
return this.base64ToArrayBuffer(base64);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Convert base64 to ArrayBuffer
|
|
124
|
+
*/
|
|
125
|
+
base64ToArrayBuffer(base64) {
|
|
126
|
+
const binaryString = atob(base64);
|
|
127
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
128
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
129
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
130
|
+
}
|
|
131
|
+
return bytes.buffer;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Sanitize file path to prevent directory traversal
|
|
135
|
+
*/
|
|
136
|
+
sanitizePath(path) {
|
|
137
|
+
// Remove any parent directory references
|
|
138
|
+
const sanitized = path
|
|
139
|
+
.split('/')
|
|
140
|
+
.filter((part) => part !== '..' && part !== '.')
|
|
141
|
+
.join('/');
|
|
142
|
+
// Ensure path doesn't start with /
|
|
143
|
+
return sanitized.replace(/^\/+/, '');
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Validate bundle ID format
|
|
147
|
+
*/
|
|
148
|
+
validateBundleId(bundleId) {
|
|
149
|
+
if (!bundleId || typeof bundleId !== 'string') {
|
|
150
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Bundle ID must be a non-empty string');
|
|
151
|
+
}
|
|
152
|
+
// Allow alphanumeric, hyphens, underscores, and dots
|
|
153
|
+
const validPattern = /^[a-zA-Z0-9\-_.]+$/;
|
|
154
|
+
if (!validPattern.test(bundleId)) {
|
|
155
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Bundle ID contains invalid characters');
|
|
156
|
+
}
|
|
157
|
+
if (bundleId.length > 100) {
|
|
158
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Bundle ID is too long (max 100 characters)');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Validate semantic version format
|
|
163
|
+
*/
|
|
164
|
+
validateVersion(version) {
|
|
165
|
+
if (!version || typeof version !== 'string') {
|
|
166
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Version must be a non-empty string');
|
|
167
|
+
}
|
|
168
|
+
// Basic semantic versioning pattern
|
|
169
|
+
const semverPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
|
|
170
|
+
if (!semverPattern.test(version)) {
|
|
171
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Version must follow semantic versioning format (e.g., 1.2.3)');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check if version is a downgrade
|
|
176
|
+
*/
|
|
177
|
+
isVersionDowngrade(currentVersion, newVersion) {
|
|
178
|
+
const current = this.parseVersion(currentVersion);
|
|
179
|
+
const next = this.parseVersion(newVersion);
|
|
180
|
+
if (next.major < current.major)
|
|
181
|
+
return true;
|
|
182
|
+
if (next.major > current.major)
|
|
183
|
+
return false;
|
|
184
|
+
if (next.minor < current.minor)
|
|
185
|
+
return true;
|
|
186
|
+
if (next.minor > current.minor)
|
|
187
|
+
return false;
|
|
188
|
+
return next.patch < current.patch;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Parse semantic version
|
|
192
|
+
*/
|
|
193
|
+
parseVersion(version) {
|
|
194
|
+
const parts = version.split('-')[0].split('.'); // Ignore pre-release
|
|
195
|
+
return {
|
|
196
|
+
major: parseInt(parts[0], 10) || 0,
|
|
197
|
+
minor: parseInt(parts[1], 10) || 0,
|
|
198
|
+
patch: parseInt(parts[2], 10) || 0,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Validate URL format and security
|
|
203
|
+
*/
|
|
204
|
+
validateUrl(url) {
|
|
205
|
+
if (!url || typeof url !== 'string') {
|
|
206
|
+
throw new ValidationError(ErrorCode.INVALID_URL, 'URL must be a non-empty string');
|
|
207
|
+
}
|
|
208
|
+
let parsedUrl;
|
|
209
|
+
try {
|
|
210
|
+
parsedUrl = new URL(url);
|
|
211
|
+
}
|
|
212
|
+
catch (_a) {
|
|
213
|
+
throw new ValidationError(ErrorCode.INVALID_URL, 'Invalid URL format');
|
|
214
|
+
}
|
|
215
|
+
// Enforce HTTPS
|
|
216
|
+
if (parsedUrl.protocol !== 'https:') {
|
|
217
|
+
throw new ValidationError(ErrorCode.INVALID_URL, 'Only HTTPS URLs are allowed');
|
|
218
|
+
}
|
|
219
|
+
// Check against allowed hosts
|
|
220
|
+
const allowedHosts = this.configManager.get('allowedHosts');
|
|
221
|
+
if (allowedHosts.length > 0 && !allowedHosts.includes(parsedUrl.hostname)) {
|
|
222
|
+
throw new ValidationError(ErrorCode.UNAUTHORIZED_HOST, `Host ${parsedUrl.hostname} is not in the allowed hosts list`);
|
|
223
|
+
}
|
|
224
|
+
// Prevent localhost/private IPs in production
|
|
225
|
+
const privatePatterns = [
|
|
226
|
+
/^localhost$/i,
|
|
227
|
+
/^127\./,
|
|
228
|
+
/^10\./,
|
|
229
|
+
/^172\.(1[6-9]|2[0-9]|3[0-1])\./,
|
|
230
|
+
/^192\.168\./,
|
|
231
|
+
/^::1$/,
|
|
232
|
+
/^fc00:/i,
|
|
233
|
+
/^fe80:/i,
|
|
234
|
+
];
|
|
235
|
+
if (privatePatterns.some((pattern) => pattern.test(parsedUrl.hostname))) {
|
|
236
|
+
throw new ValidationError(ErrorCode.UNAUTHORIZED_HOST, 'Private/local addresses are not allowed');
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Validate file size
|
|
241
|
+
*/
|
|
242
|
+
validateFileSize(size) {
|
|
243
|
+
if (typeof size !== 'number' || size < 0) {
|
|
244
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'File size must be a non-negative number');
|
|
245
|
+
}
|
|
246
|
+
const maxSize = this.configManager.get('maxBundleSize');
|
|
247
|
+
if (size > maxSize) {
|
|
248
|
+
throw new ValidationError(ErrorCode.BUNDLE_TOO_LARGE, `File size ${size} exceeds maximum allowed size of ${maxSize} bytes`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Generate a secure random ID
|
|
253
|
+
*/
|
|
254
|
+
generateSecureId() {
|
|
255
|
+
const array = new Uint8Array(16);
|
|
256
|
+
crypto.getRandomValues(array);
|
|
257
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Validate certificate pinning for HTTPS connections
|
|
261
|
+
* Note: This is a placeholder for web implementation as certificate pinning
|
|
262
|
+
* is primarily implemented at the native layer
|
|
263
|
+
*/
|
|
264
|
+
async validateCertificatePin(hostname, certificate) {
|
|
265
|
+
// Certificate pinning is not available in PluginConfig type
|
|
266
|
+
const certificatePins = this.configManager.certificatePins;
|
|
267
|
+
if (!certificatePins ||
|
|
268
|
+
!Array.isArray(certificatePins) ||
|
|
269
|
+
certificatePins.length === 0) {
|
|
270
|
+
// No pins configured, allow connection
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
const hostPins = certificatePins.filter((pin) => pin.hostname === hostname);
|
|
274
|
+
if (hostPins.length === 0) {
|
|
275
|
+
// No pins for this host, allow connection
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
// Check if certificate matches any of the pins
|
|
279
|
+
const certificateHash = await this.calculateCertificateHash(certificate);
|
|
280
|
+
const isValid = hostPins.some((pin) => pin.sha256 === certificateHash);
|
|
281
|
+
if (!isValid) {
|
|
282
|
+
this.logger.error('Certificate pinning validation failed', {
|
|
283
|
+
hostname,
|
|
284
|
+
expectedPins: hostPins.map((p) => p.sha256),
|
|
285
|
+
actualHash: certificateHash,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return isValid;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Calculate SHA-256 hash of certificate
|
|
292
|
+
*/
|
|
293
|
+
async calculateCertificateHash(certificate) {
|
|
294
|
+
const encoder = new TextEncoder();
|
|
295
|
+
const data = encoder.encode(certificate);
|
|
296
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
297
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
298
|
+
return 'sha256/' + btoa(String.fromCharCode(...hashArray));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Validate metadata object
|
|
302
|
+
*/
|
|
303
|
+
validateMetadata(metadata) {
|
|
304
|
+
if (metadata && typeof metadata !== 'object') {
|
|
305
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Metadata must be an object');
|
|
306
|
+
}
|
|
307
|
+
// Limit metadata size to prevent abuse
|
|
308
|
+
const metadataStr = JSON.stringify(metadata || {});
|
|
309
|
+
if (metadataStr.length > 10240) {
|
|
310
|
+
// 10KB limit
|
|
311
|
+
throw new ValidationError(ErrorCode.INVALID_BUNDLE_FORMAT, 'Metadata is too large (max 10KB)');
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../../src/core/security.ts"],"names":[],"mappings":"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"}
|