Skip to content

Commit 6be4ce3

Browse files
committed
refactor(smol): standardize naming with socketsecurity_ prefix and explicit versions
Standardize all Socket-related files with: - socketsecurity_ prefix (instead of socket_) - Explicit version numbers (v24.10.0 instead of v24) - Minimal injection pattern for all patches Changes: - Rename 6 patch files with standardized naming - Rename header: socketsecurity_brotli_builtin_loader.h - Rename 9 tool files (source + binaries) - Add bootstrap loader template with comprehensive documentation - Add minimal injection patch for bootstrap - Update all references in build.mjs Naming convention: socketsecurity_<feature>_<target>_v24.10.0.patch
1 parent b8d458a commit 6be4ce3

20 files changed

+317
-136
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
/**
2+
* Socket Security Bootstrap Loader
3+
*
4+
* ============================================================================
5+
* CRITICAL: This module MUST be called early in Node.js pre-execution phase
6+
* ============================================================================
7+
*
8+
* PURPOSE (What):
9+
* ---------------
10+
* Loads and executes Socket CLI security bootstrap code at Node.js startup.
11+
* The bootstrap monitors package installations, network requests, and file
12+
* operations to detect suspicious activity.
13+
*
14+
* WHY IT EXISTS (Why):
15+
* --------------------
16+
* 1. EARLY LOADING: Must run before user code to intercept module loading
17+
* 2. ZERO FILESYSTEM: Bootstrap embedded as base64 - no file I/O needed
18+
* 3. ASYNC SUPPORT: Allows background security monitoring without blocking startup
19+
* 4. ISOLATED CONTEXT: Runs in separate VM context to avoid polluting globals
20+
*
21+
* HOW IT WORKS (Visual Flow):
22+
* ---------------------------
23+
*
24+
* Node.js Startup
25+
* │
26+
* ├─→ lib/internal/process/pre_execution.js
27+
* │ └─→ loadPreloadModules()
28+
* │ └─→ require('internal/socketsecurity_bootstrap_loader')() ← 1-line injection
29+
* │ │
30+
* │ ├─→ [THIS FILE]
31+
* │ │ ├─→ Decode base64 bootstrap
32+
* │ │ ├─→ Create module context
33+
* │ │ ├─→ Compile with vm.compileFunction()
34+
* │ │ └─→ Execute (async background)
35+
* │ │
36+
* │ └─→ Returns immediately
37+
* │
38+
* └─→ User code starts
39+
* (Bootstrap monitors in background)
40+
*
41+
* PERFORMANCE IMPACT:
42+
* -------------------
43+
* - Decode: ~1-2ms (base64 → string)
44+
* - Compile: ~3-5ms (vm.compileFunction C++ API)
45+
* - Execute: Instant return (async code runs in background)
46+
* - Total: <10ms added to Node.js startup
47+
*
48+
* TECHNICAL DETAILS:
49+
* ------------------
50+
* 1. Uses vm.compileFunction() (C++ API) instead of eval or vm.runInThisContext()
51+
* - Faster compilation
52+
* - Proper stack traces
53+
* - Module parameter injection (exports, require, module, __filename, __dirname)
54+
*
55+
* 2. Module context created manually:
56+
* - filename: '/internal/bootstrap-smol.js' (virtual path, validation only)
57+
* - paths: Standard node_modules resolution
58+
* - require: Full require() with resolve, cache, extensions
59+
*
60+
* 3. Async execution pattern:
61+
* - Bootstrap can use main().catch(...) pattern
62+
* - Starts executing but returns immediately
63+
* - Background monitoring continues while Node.js initializes
64+
*
65+
* ERROR HANDLING:
66+
* ---------------
67+
* - Catches all errors during load/compile/execute
68+
* - Prints to stderr (console not available this early)
69+
* - Never crashes Node.js (bootstrap failures are non-fatal)
70+
*
71+
* VISUAL EXAMPLE:
72+
* ---------------
73+
*
74+
* Base64 Embedded Bootstrap
75+
* ┌──────────────────────────┐
76+
* │ ZnVuY3Rpb24gbWFpbigpIHs │ ← Build system embeds here
77+
* │ ...21,000+ lines... │
78+
* └──────────────────────────┘
79+
* │
80+
* ├─→ Buffer.from(base64) → JavaScript source
81+
* │
82+
* ├─→ vm.compileFunction(source, params) → Compiled function
83+
* │
84+
* └─→ compiledFn(exports, require, module, ...) → Execute
85+
* │
86+
* ├─→ Synchronous setup code runs immediately
87+
* └─→ main().catch(...) starts, returns immediately
88+
* │
89+
* └─→ Async monitoring continues in background
90+
*
91+
* MAINTENANCE NOTES:
92+
* ------------------
93+
* - This file is processed by build.mjs during compilation
94+
* - SOCKET_BOOTSTRAP_BASE64_PLACEHOLDER replaced with actual base64
95+
* - Final file copied to Node.js source: lib/internal/socketsecurity_bootstrap_loader.js
96+
* - Patch injects 1 line: require('internal/socketsecurity_bootstrap_loader')()
97+
*
98+
* SECURITY CONSIDERATIONS:
99+
* ------------------------
100+
* - Bootstrap runs with full Node.js internal access (can require internal modules)
101+
* - No filesystem or network access during load (embedded base64)
102+
* - Errors isolated (won't crash Node.js)
103+
* - Module context prevents global pollution
104+
*
105+
* @module internal/socketsecurity_bootstrap_loader
106+
* @requires internal/modules/cjs/loader - Module system access
107+
* @requires internal/modules/helpers - makeRequireFunction()
108+
* @requires vm - Compilation API
109+
* @requires buffer - Base64 decoding
110+
*/
111+
112+
'use strict';
113+
114+
/**
115+
* Load and execute the Socket bootstrap.
116+
*
117+
* Called from lib/internal/process/pre_execution.js during Node.js startup.
118+
* This function MUST return quickly to avoid blocking Node.js initialization.
119+
*
120+
* EXECUTION FLOW:
121+
* ---------------
122+
* 1. Decode base64 → JavaScript source code
123+
* 2. Create module context (exports, require, module, __filename, __dirname)
124+
* 3. Compile source with vm.compileFunction() (C++ API, fast!)
125+
* 4. Execute compiled function (synchronous setup + async background)
126+
* 5. Return immediately (async code continues in background)
127+
*
128+
* ERROR BEHAVIOR:
129+
* ---------------
130+
* - Any error during load/compile/execute is caught
131+
* - Error printed to stderr (console not available)
132+
* - Node.js continues initialization (non-fatal)
133+
* - User code runs normally (bootstrap disabled)
134+
*
135+
* @returns {void}
136+
* @throws {never} All errors caught and logged to stderr
137+
*/
138+
module.exports = function loadSocketBootstrap() {
139+
// Bootstrap code embedded as base64 (build system replaces this placeholder).
140+
// Split across multiple lines for readability and to avoid line length limits.
141+
//
142+
// PLACEHOLDER REPLACEMENT:
143+
// ├─→ Build system (build.mjs) reads bootstrap source
144+
// ├─→ Encodes as base64 (1275KB → 1700KB)
145+
// ├─→ Splits into 80-char chunks
146+
// └─→ Replaces SOCKET_BOOTSTRAP_BASE64_PLACEHOLDER
147+
const SOCKET_BOOTSTRAP_B64 = (
148+
SOCKET_BOOTSTRAP_BASE64_PLACEHOLDER
149+
);
150+
151+
try {
152+
// STEP 1: Load Node.js internals.
153+
// --------------------------------
154+
// These modules MUST be available during pre-execution phase.
155+
// If any are missing, the catch block will handle gracefully.
156+
const Module = require('internal/modules/cjs/loader').Module;
157+
const { makeRequireFunction } = require('internal/modules/helpers');
158+
const vm = require('vm');
159+
const { Buffer } = require('buffer');
160+
161+
// STEP 2: Decode bootstrap from base64.
162+
// --------------------------------------
163+
// Performance: ~1-2ms for 1700KB base64 → 1275KB JavaScript
164+
// Result: Plain JavaScript source code ready for compilation
165+
const bootstrapCode = Buffer.from(SOCKET_BOOTSTRAP_B64, 'base64').toString('utf8');
166+
167+
// STEP 3: Create module context.
168+
// -------------------------------
169+
// This gives the bootstrap access to require(), module.exports, etc.
170+
//
171+
// CRITICAL: filename MUST be absolute path format for validation.
172+
// - Module.createRequire() validates filename is absolute
173+
// - Doesn't need to exist as real file, just valid path format
174+
// - Using '/internal/bootstrap-smol.js' (Node.js internal path style)
175+
const bootstrapModule = new Module('socket:bootstrap', null);
176+
bootstrapModule.filename = '/internal/bootstrap-smol.js'; // Virtual path (validation only)
177+
bootstrapModule.paths = Module._nodeModulePaths(process.cwd()); // Standard resolution
178+
const exports = {};
179+
bootstrapModule.exports = exports;
180+
181+
// STEP 4: Create require function.
182+
// ---------------------------------
183+
// makeRequireFunction() adds:
184+
// - require.resolve()
185+
// - require.cache
186+
// - require.extensions
187+
// - require.main
188+
const moduleRequire = makeRequireFunction(bootstrapModule);
189+
190+
// STEP 5: Compile using C++ API.
191+
// -------------------------------
192+
// vm.compileFunction() is FASTER than:
193+
// - eval() (no stack traces, security issues)
194+
// - vm.runInThisContext() (slower, no parameter injection)
195+
// - Module.wrap() + compilation (extra wrapping overhead)
196+
//
197+
// Parameters: ['exports', 'require', 'module', '__filename', '__dirname']
198+
// These match standard CommonJS module parameters.
199+
const compiledFn = vm.compileFunction(
200+
bootstrapCode,
201+
['exports', 'require', 'module', '__filename', '__dirname'],
202+
{
203+
filename: '/internal/bootstrap-smol.js', // For stack traces
204+
lineOffset: 0, // Source starts at line 0
205+
columnOffset: 0, // Source starts at column 0
206+
}
207+
);
208+
209+
// STEP 6: Execute with module context.
210+
// -------------------------------------
211+
// Reflect.apply() provides clean invocation:
212+
// - thisArg: exports (standard CommonJS)
213+
// - args: [exports, require, module, __filename, __dirname]
214+
//
215+
// ASYNC BEHAVIOR:
216+
// - If bootstrap has main().catch(...), it starts executing
217+
// - Function returns immediately (doesn't wait for async)
218+
// - Async operations continue in background
219+
// - Node.js initialization proceeds normally
220+
Reflect.apply(compiledFn, exports, [
221+
exports, // exports object
222+
moduleRequire, // require() with resolve, cache, etc.
223+
bootstrapModule, // module object
224+
'/internal/bootstrap-smol.js', // __filename (virtual)
225+
'/internal' // __dirname (virtual)
226+
]);
227+
228+
// Returns here immediately, even if bootstrap has async code!
229+
// Background monitoring continues while Node.js initializes.
230+
231+
} catch (err) {
232+
// ERROR HANDLING:
233+
// ---------------
234+
// - console.* not available this early in bootstrap
235+
// - Use process.stderr.write() for direct output
236+
// - Include stack trace for debugging
237+
// - Never throw (would crash Node.js)
238+
//
239+
// FAILURE MODES:
240+
// 1. Module loading error (require fails) → Bootstrap disabled
241+
// 2. Base64 decode error → Bootstrap disabled
242+
// 3. Compilation error (invalid syntax) → Bootstrap disabled
243+
// 4. Execution error (runtime error) → Bootstrap disabled
244+
//
245+
// In all cases: Node.js continues, user code runs normally.
246+
process.stderr.write(`Socket bootstrap error: ${err.message}\n${err.stack}\n`);
247+
}
248+
};

packages/node-smol-builder/additions/src/socket_brotli_builtin_loader.h renamed to packages/node-smol-builder/additions/src/socketsecurity_brotli_builtin_loader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Socket Security - Minimal-Touch Brotli Builtin Loader
33
*
4-
* @file socket_brotli_builtin_loader.h
4+
* @file socketsecurity_brotli_builtin_loader.h
55
* @brief External header for Node.js builtin Brotli decompression
66
* @version 1.0.0
77
* @date 2025-01-17
@@ -49,8 +49,8 @@
4949
* SPDX-License-Identifier: MIT
5050
*/
5151

52-
#ifndef SOCKET_BROTLI_BUILTIN_LOADER_H_
53-
#define SOCKET_BROTLI_BUILTIN_LOADER_H_
52+
#ifndef SOCKETSECURITY_BROTLI_BUILTIN_LOADER_H_
53+
#define SOCKETSECURITY_BROTLI_BUILTIN_LOADER_H_
5454

5555
#include "node_union_bytes.h"
5656
#include "v8.h"

packages/node-smol-builder/additions/tools/socket_brotli2c.cc renamed to packages/node-smol-builder/additions/tools/socketsecurity_brotli2c.cc

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_elf_compress.c renamed to packages/node-smol-builder/additions/tools/socketsecurity_elf_compress.c

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_elf_decompress.c renamed to packages/node-smol-builder/additions/tools/socketsecurity_elf_decompress.c

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_macho_compress renamed to packages/node-smol-builder/additions/tools/socketsecurity_macho_compress

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_macho_compress.cc renamed to packages/node-smol-builder/additions/tools/socketsecurity_macho_compress.cc

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_macho_decompress renamed to packages/node-smol-builder/additions/tools/socketsecurity_macho_decompress

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_macho_decompress.cc renamed to packages/node-smol-builder/additions/tools/socketsecurity_macho_decompress.cc

File renamed without changes.

packages/node-smol-builder/additions/tools/socket_pe_compress.c renamed to packages/node-smol-builder/additions/tools/socketsecurity_pe_compress.c

File renamed without changes.

0 commit comments

Comments
 (0)