Files
skills/docs/devtools/tooling/sandbox/src/code-transformer/code-transformer.md
2026-05-29 08:20:56 +01:00

3.0 KiB

CodeTransformer

(no submodules)

Purpose

CodeTransformer is a defence-in-depth layer that pattern-matches dangerous code constructs before they reach the engine. The eleven built-in rules catch the obvious foot-guns — process.exit, require, dynamic import, eval, the Function constructor, globalThis, prototype-chain probes, and the constructor['constructor'] escape — plus two warning-only rules for infinite loops and a maxCodeLength guard that caps script size at 100KB by default.

The transformer is regex-based by design. A full AST parser would catch contrived bypasses (commented-out code that gets reassembled at runtime, string concatenation that builds a denylisted identifier) but at the cost of pulling in a megabyte of parser. The engine-level boundary (vm-engine, worker-engine, spawn-engine) is the actual security layer; the transformer raises the floor on accidental harm and surfaces clearly-named blocks for malicious harm.

Features

  • Ten built-in security rules covering the documented OWASP-recommended dangerous-pattern catalogue for in-process script execution.
  • One max-code-length guard for script size.
  • enableBuiltinRules: false opt-out for callers shipping their own rules.
  • customRules slot for additive caller rules.
  • transform(code) returns { code, blocked, blockedBy?, applied, warnings }.
  • wouldBlock(code) returns { blocked, reason? } for cheap pre-flight checks.
  • Every block fires an OTel counter via recordRuleBlock(rule).

Usage: Basic

import { CodeTransformer } from "@suaveplan/sandbox/code-transformer";

const t = new CodeTransformer();
const r = t.transform("1 + 1");
console.log(r.blocked, r.applied);

Usage: Advanced

Extend the transformer with a custom auditing rule that rewrites a vendor SDK call into a logged wrapper before execution:

import { CodeTransformer } from "@suaveplan/sandbox/code-transformer";

const t = new CodeTransformer({
    customRules: [
        {
            name: "audit-vendor-call",
            pattern: /\bvendor\.send\(/g,
            replacement: "vendor.__audited_send(",
            blocking: false,
        },
    ],
});

API Reference

  • BUILTIN_RULES: readonly TransformRule[].
  • new CodeTransformer(config?: CodeTransformerConfig).
  • transform(code: string): TransformResult.
  • wouldBlock(code: string): { blocked: boolean; reason?: string }.
  • getRules(): readonly TransformRule[].

Implementation Notes

The rule list is iterated in declaration order; the first matching blocking rule wins. Replacement rules apply globally (the g flag is forced on every regex) so multiple occurrences are rewritten in one pass. Warning-only rules that aren't replacements only append a warning string — they never mutate the code. Pattern strings (vs. literal regex) get the g flag added in ruleRegex so caller-supplied string patterns behave consistently with caller-supplied regex patterns.