@deployowl/deployowl
@deployowl/deployowl
Official SDK for DeployOwl error tracking.
Security Notice (v2.3.0+)
This version fixes MAL-2026-10677. The SDK now follows the Sentry model: collect what's useful for analysis, scrub what's sensitive, document everything, let the user control it.
| Behavior | v2.1.0 (vulnerable) | v2.3.0 (fixed) |
|---|---|---|
| Environment variables | Iterated ALL of process.env, weak keyword redaction, leaked 3-char secret prefixes |
Allowlist — only vars explicitly listed in allowedEnvVars are sent (default: empty) |
eval('require') to evade static analysis |
Present | Removed — uses module.createRequire() (legitimate, scanner-visible) |
package.json dependency upload |
Full manifest via eval('require') |
Name+version pairs only via collectDependencies (default: true) |
| Infrastructure sync (nodeVersion/platform/arch) | Auto-on, undocumented | Auto-on, documented (collectInfrastructure: true) |
| Health metrics sync (CPU/memory/lag) | Auto-on, undocumented | Auto-on, documented (collectHealth: true) |
| Console monkey-patching for breadcrumbs | Auto-on, undocumented | Tied to autoCapture (documented below) |
| Hardcoded shared secret | DEPLOYOWL_SUPER_SECRET_2026_XYZ |
Removed |
No secrets are collected. The SDK does not iterate process.env. Only vars you explicitly allowlist are sent.
Installation
npm install @deployowl/deployowl
Usage
Basic Setup
import { init, captureError } from '@deployowl/deployowl';
init({
apiKey: 'your-api-key',
environment: 'production'
});
try {
riskyOperation();
} catch (error) {
captureError(error);
throw error;
}
With Context
captureError(error, {
userId: '123',
action: 'checkout',
cart: { items: 3, total: 99.99 }
});
Set User Info
import { setUser } from '@deployowl/deployowl';
setUser({
id: 'user_123',
email: 'user@example.com'
});
Configuration Options
init({
apiKey: 'your-api-key', // Required
endpoint: 'https://custom.com', // Optional: custom endpoint (default: https://api.deployowl.com)
environment: 'staging', // Optional: environment tag
batchSize: 10, // Optional: errors per flush (default: 10)
flushInterval: 5000, // Optional: ms between flushes (default: 5000)
maxBreadcrumbs: 50, // Optional: breadcrumb buffer size (default: 50)
debug: false, // Optional: verbose logging (default: false)
dryRun: false, // Optional: log payloads instead of sending (default: false)
autoCapture: true, // Optional: capture uncaughtException/unhandledRejection + console breadcrumbs (default: true)
collectDependencies: true, // Optional: send package name+version pairs on init (default: true)
collectInfrastructure: true, // Optional: send nodeVersion/platform/arch on init (default: true)
collectHealth: true, // Optional: periodically send CPU/memory/event-loop metrics (default: true)
healthInterval: 3600000, // Optional: ms between health syncs (default: 3600000 = 1 hour)
allowedEnvVars: [], // Optional: allowlist of env var names to include in error snapshots (default: [])
beforeSend: (error) => { // Optional: filter/modify errors before sending
if (error.message.includes('ignore')) {
return null; // Don't send
}
return error;
}
});
Env Var Allowlist
By default, no environment variables are sent. To include specific env vars in error snapshots, list them explicitly:
init({
apiKey: 'your-key',
allowedEnvVars: ['NODE_ENV', 'APP_NAME', 'DATABASE_CLIENT'],
// Only these 3 vars will be included in error snapshots.
// All other env vars (including secrets) are never read or sent.
});
What Data Is Sent
On captureError() — to /api/v1/errors
| Field | Source | Default |
|---|---|---|
| message, stack | Error object | always |
| timestamp, environment | SDK config | always |
| user | setUser() |
if set |
| context | captureError(err, context) |
if passed |
| breadcrumbs | console.log/warn/error (if autoCapture: true) |
if enabled |
| snapshot.env | allowedEnvVars allowlist |
empty by default |
| snapshot.url, userAgent, localStorageKeys | browser only | browser only |
On init() — to /api/v1/infrastructure
| Field | Source | Config flag | Default |
|---|---|---|---|
| nodeVersion, platform, arch | process.* |
collectInfrastructure |
true |
| dependencies | package.json name+version pairs only |
collectDependencies |
true |
What is NOT sent: env vars, secrets, scripts, package.json metadata, lockfiles, or any file contents.
Periodically — to /api/v1/health (if collectHealth: true)
| Field | Source | Default |
|---|---|---|
| cpuUsage | process.cpuUsage() |
true |
| memoryUsage | process.memoryUsage() |
true |
| eventLoopLag | measured | true |
API Reference
init(config: OwlConfig)
Initialize the SDK. Must be called before capturing errors.
captureError(error: Error, context?: object)
Capture an error with optional context.
setUser(user: { id?: string; email?: string })
Set user information to be attached to all future errors.
close()
Flush any pending errors and close the SDK. Call before process exit.
process.on('SIGTERM', async () => {
await close();
process.exit(0);
});
Privacy & Security
- No secrets are collected. The SDK does not iterate
process.env. Only vars you explicitly allowlist are sent. - No
eval()or hiddenrequire(). Usesmodule.createRequire()— a legitimate, scanner-visible pattern. - Dependency collection is name+version only. No scripts, metadata, or other package.json fields.
- All collection flags default to
truebut can be disabled:collectDependencies: false,collectInfrastructure: false,collectHealth: false. - Use
dryRun: trueto inspect payloads without sending them. - Use
beforeSendto filter or redact any data before transmission.
License
Proprietary DeployOwl. All rights reserved.