Why deny-by-default?
Codemods run arbitrary code transformations on your codebase. By restricting capabilities by default, jssg ensures:- Safe execution: Untrusted codemods cannot access sensitive resources without explicit permission
- Audit trail: The
capabilitiesfield incodemod.yamlprovides a clear record of what permissions a codemod requires - Principle of least privilege: Codemods only get the minimum permissions they need
Unsafe modules (require explicit permission)
These modules require explicit opt-in via thecapabilities field:
fs
File system accessRead, write, list, and delete files on disk
fetch
Network requestsMake HTTP/HTTPS requests
child_process
Process spawningExecute external commands
Default (safe) modules
These modules are always available and require no special permissions:Core utilities (13 modules)
Core utilities (13 modules)
assert- Assertion testingbuffer- Binary data manipulationconsole- Logging and debuggingcrypto- Cryptographic operationsevents- Event emitter patternsos- Operating system information (read-only)path- File path utilitiesperf_hooks- Performance measurementprocess- Process information (read-only, no spawning)string_decoder- String encoding/decodingtimers- Timer functionstty- TTY operationsutil- Utility functions
Web standards (3 modules)
Web standards (3 modules)
stream_web- Web Streams APIurl- URL parsing and manipulationzlib- Compression/decompression
All default modules are considered safe because they don’t perform file I/O, network requests, or process spawning.
Enabling capabilities
To enable unsafe modules, add acapabilities field to your codemod.yaml file:
codemod.yaml
Only enable capabilities that your codemod actually needs. Each capability increases the potential security risk if the codemod is untrusted.
Capability names
Use these exact strings in thecapabilities array:
| Capability | Modules Enabled | Use Case |
|---|---|---|
fs | fs, fs/promises | Reading/writing files, checking file existence |
fetch | fetch global | Making HTTP requests to APIs |
child_process | child_process | Running Git, npm, or other CLI tools |
Usage examples
File system operations
1
Enable fs capability
codemod.yaml
2
Use fs in your transform
scripts/codemod.ts
Network requests
1
Enable fetch capability
codemod.yaml
2
Use fetch in your transform
scripts/codemod.ts
Note the
async transform function when using fetch or other asynchronous operations.Running external commands
1
Enable child_process capability
codemod.yaml
2
Spawn processes in your transform
scripts/codemod.ts
Always validate and sanitize any user input before passing it to
execSync or spawn to prevent command injection vulnerabilities.CLI override flags
You can also enable capabilities via CLI flags when running a codemod:CLI flags take precedence over
codemod.yaml. This is useful for testing or one-off runs where you trust the codemod source.Best practices
Minimize required capabilities
Minimize required capabilities
Only request capabilities your codemod truly needs. For example, if you only need to read files, document that your codemod won’t write or delete files.
Document why capabilities are needed
Document why capabilities are needed
In your README, explain why each capability is required and what operations use it.
README.md
Validate inputs when using child_process
Validate inputs when using child_process
Never pass unsanitized user input to shell commands:
Consider publishing capability-free versions
Consider publishing capability-free versions
If possible, provide a version of your codemod that works without unsafe capabilities for maximum trust.
Security considerations
Untrusted codemods: Never run codemods from untrusted sources with capabilities enabled without reviewing the code first.