Skip to content

Commit d521004

Browse files
authored
feat: es module remote security (#191)
1 parent 649550a commit d521004

File tree

2 files changed

+392
-0
lines changed

2 files changed

+392
-0
lines changed

content/configuration/nativescript.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,60 @@ hooks: Array = []
171171

172172
See [Hooks Configuration Reference](#hooks-configuration-reference)
173173

174+
### security
175+
176+
NativeScript supports dynamic `import()` from remote URLs. This is useful during development but carries security implications in production since NativeScript code has **direct access to native platform APIs** (file system, keychain, network, camera, etc.).
177+
178+
| Mode | Remote Modules |
179+
|------|----------------|
180+
| **Debug** | ✅ Always allowed |
181+
| **Production** | ❌ Blocked by default |
182+
183+
#### Enabling Remote Modules in Production
184+
185+
If you need remote ES modules in production, explicitly opt-in:
186+
187+
```typescript
188+
import { NativeScriptConfig } from '@nativescript/core'
189+
190+
export default {
191+
id: 'org.nativescript.myapp',
192+
appPath: 'src',
193+
194+
security: {
195+
allowRemoteModules: true
196+
}
197+
} as NativeScriptConfig
198+
```
199+
200+
#### Using an Allowlist (Recommended)
201+
202+
Restrict to specific trusted origins:
203+
204+
```typescript
205+
export default {
206+
// ...
207+
security: {
208+
allowRemoteModules: true,
209+
remoteModuleAllowlist: [
210+
'https://cdn.yourcompany.com/modules/',
211+
'https://esm.sh/@yourorg/'
212+
]
213+
}
214+
} as NativeScriptConfig
215+
```
216+
217+
The allowlist uses **prefix matching** — a URL is allowed if it starts with any entry.
218+
219+
#### Security Best Practices
220+
221+
- **Keep production secure by default** - Don't enable unless necessary
222+
- **Use narrow allowlists** - Specific paths, not broad domains
223+
- **Pin versions in URLs** - Use immutable, versioned URLs
224+
- **Never use user-controlled URLs** - Injection vulnerability risk
225+
226+
For comprehensive security guidance, see the [Security Guide](/guide/security).
227+
174228
## CLI Configuration Reference
175229

176230
### cli.packageManager
@@ -482,3 +536,94 @@ Available hooks (prefix with `before-` or `after-`):
482536
- `watchPatterns` - Set up watch patterns, runs during `watch` hook
483537

484538
<!-- TODO: check if we are missing some hooks here, ie. before-gradleArgs? -->
539+
540+
## Security Configuration Reference
541+
542+
NativeScript provides security configuration options to control sensitive runtime behaviors, particularly around remote code execution via ES module imports.
543+
544+
::: tip
545+
For comprehensive security guidance and best practices, see the [Security Guide](/guide/security).
546+
:::
547+
548+
### security.allowRemoteModules
549+
550+
```ts
551+
security.allowRemoteModules: boolean = false;
552+
```
553+
554+
Enable remote ES module loading in production builds.
555+
556+
| Mode | Remote Modules |
557+
|------|----------------|
558+
| **Debug** (local development) | ✅ Always allowed |
559+
| **Production** (Release builds) | ❌ Blocked by default |
560+
561+
When `false` (the default), any attempt to `import("https://...")` in production will throw an error. This is a security measure because NativeScript code has **direct access to native platform APIs** (file system, keychain, network, camera, etc.).
562+
563+
```ts
564+
export default {
565+
// ...
566+
security: {
567+
allowRemoteModules: true
568+
}
569+
} as NativeScriptConfig
570+
```
571+
572+
::: warning Security Implications
573+
Remote modules bypass App Store/Play Store code review and can access any native API your app has access to. Only enable this if you have a specific, justified need and understand the implications.
574+
:::
575+
576+
### security.remoteModuleAllowlist
577+
578+
```ts
579+
security.remoteModuleAllowlist: string[] = [];
580+
```
581+
582+
Restrict remote modules to specific URL prefixes. Only used when `allowRemoteModules` is `true`.
583+
584+
The allowlist uses **prefix matching** — a URL is allowed if it starts with any entry in the list.
585+
586+
```ts
587+
export default {
588+
// ...
589+
security: {
590+
allowRemoteModules: true,
591+
remoteModuleAllowlist: [
592+
'https://cdn.yourcompany.com/modules/',
593+
'https://esm.sh/@yourorg/'
594+
]
595+
}
596+
} as NativeScriptConfig
597+
```
598+
599+
#### Allowlist Examples
600+
601+
| Allowlist Entry | Allowed URLs | Blocked URLs |
602+
|-----------------|--------------|--------------|
603+
| `https://cdn.example.com/` | `https://cdn.example.com/mod.js` | `https://other.com/mod.js` |
604+
| `https://esm.sh/@myorg/` | `https://esm.sh/@myorg/pkg` | `https://esm.sh/@other/pkg` |
605+
| `https://unpkg.com/` | `https://unpkg.com/lodash` | `http://unpkg.com/lodash` (http blocked) |
606+
607+
If the allowlist is empty or not provided (and `allowRemoteModules` is `true`), all HTTPS URLs are allowed — this is **not recommended** for production.
608+
609+
### Error Messages
610+
611+
When remote module loading is blocked, you'll see clear error messages:
612+
613+
```
614+
// Remote modules disabled
615+
Remote ES modules are not allowed in production. URL: https://example.com/mod.js.
616+
Enable via security.allowRemoteModules in nativescript.config.ts
617+
618+
// URL not in allowlist
619+
Remote URL not in security.remoteModuleAllowlist: https://untrusted.com/mod.js
620+
```
621+
622+
### Best Practices
623+
624+
1. **Keep production secure by default** — Don't enable `allowRemoteModules` unless necessary
625+
2. **Use narrow allowlists** — Specific paths, not broad domains
626+
3. **Pin versions in URLs** — Use immutable, versioned URLs over mutable endpoints
627+
4. **Never use user-controlled URLs** — Avoid injection vulnerabilities
628+
629+
For more details on security implications and additional best practices, see the [Security Guide](/guide/security).

0 commit comments

Comments
 (0)