Installation
Runnable Examples
Use the repository examples for end-to-end runnable flows:
/examples/js/01-support-check.js
/examples/js/02-build-capabilities.js
/examples/js/03-query-policy.js
/examples/js/04-state-roundtrip.js
/examples/js/05-safe-apply-pattern.js
/examples/ts/01-support-check.ts
/examples/ts/02-build-capabilities.ts
/examples/ts/03-query-policy.ts
/examples/ts/04-state-roundtrip.ts
/examples/ts/05-safe-apply-pattern.ts
npm run examples:list
npm run example:all
For the guarded apply demos, set NONO_APPLY=1.
Basic Usage
Before applying a sandbox, verify that the current platform supports it:
import { isSupported, supportInfo } from 'nono-ts';
if (!isSupported()) {
const info = supportInfo();
console.error(`Sandboxing not available: ${info.details}`);
process.exit(1);
}
2. Define Capabilities
Create a CapabilitySet and add the permissions your application needs:
import { CapabilitySet, AccessMode } from 'nono-ts';
const caps = new CapabilitySet();
// Allow read/write access to a directory
caps.allowPath('/var/data', AccessMode.ReadWrite);
// Allow read-only access to system libraries
caps.allowPath('/usr/lib', AccessMode.Read);
caps.allowPath('/lib', AccessMode.Read);
// Allow access to a specific file
caps.allowFile('/etc/ssl/certs/ca-certificates.crt', AccessMode.Read);
3. Apply the Sandbox
Calling apply() is irreversible. Once applied, the sandbox cannot be weakened or removed for the lifetime of the process.
import { apply } from 'nono-ts';
// Apply the sandbox
apply(caps);
// From this point forward, the process can only access granted resources
Complete Example
Here’s a complete example of a sandboxed file processor:
import { CapabilitySet, AccessMode, apply, isSupported } from 'nono-ts';
import * as fs from 'fs';
import * as path from 'path';
const INPUT_DIR = '/var/input';
const OUTPUT_DIR = '/var/output';
function setupSandbox() {
if (!isSupported()) {
throw new Error('Sandboxing not supported on this platform');
}
const caps = new CapabilitySet();
// Read from input directory
caps.allowPath(INPUT_DIR, AccessMode.Read);
// Write to output directory
caps.allowPath(OUTPUT_DIR, AccessMode.ReadWrite);
// Node.js runtime needs
caps.allowPath('/usr/lib', AccessMode.Read);
caps.allowPath('/lib', AccessMode.Read);
// Block network access
caps.blockNetwork();
// Apply sandbox
apply(caps);
console.log('Sandbox applied successfully');
}
function processFiles() {
const files = fs.readdirSync(INPUT_DIR);
for (const file of files) {
const input = path.join(INPUT_DIR, file);
const output = path.join(OUTPUT_DIR, `processed_${file}`);
const content = fs.readFileSync(input, 'utf-8');
const processed = content.toUpperCase(); // Example transformation
fs.writeFileSync(output, processed);
console.log(`Processed: ${file}`);
}
}
// Setup sandbox first
setupSandbox();
// Now process files with restricted permissions
processFiles();
Testing Before Applying
Use QueryContext to test whether operations would be permitted before applying the sandbox:
import { CapabilitySet, QueryContext, AccessMode } from 'nono-ts';
const caps = new CapabilitySet();
caps.allowPath('/tmp', AccessMode.ReadWrite);
caps.blockNetwork();
const query = new QueryContext(caps);
// Test file access
const fileResult = query.queryPath('/tmp/test.txt', AccessMode.Write);
console.log(`Write to /tmp/test.txt: ${fileResult.status}`);
// Output: Write to /tmp/test.txt: allowed
const homeResult = query.queryPath('/home/user/secret.txt', AccessMode.Read);
console.log(`Read /home/user/secret.txt: ${homeResult.status}`);
// Output: Read /home/user/secret.txt: denied
// Test network access
const netResult = query.queryNetwork();
console.log(`Network access: ${netResult.status}`);
// Output: Network access: denied
Error Handling
The SDK throws errors for invalid operations:
import { CapabilitySet, AccessMode, apply } from 'nono-ts';
const caps = new CapabilitySet();
try {
// This will throw if /nonexistent doesn't exist
caps.allowPath('/nonexistent', AccessMode.Read);
} catch (error) {
console.error('Failed to add capability:', error.message);
}
try {
apply(caps);
} catch (error) {
console.error('Failed to apply sandbox:', error.message);
}
Next Steps