Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

--lockdown — Refuse Arbitrary-Code-Execution Surfaces

A single flag that fails the build if any of the standard arbitrary- code-execution vectors are reachable from the module graph. Most apps need none of them; lockdown is a one-line opt-in to “this app is provably free of arbitrary-code-execution vectors.”

Zero runtime cost. The check runs at compile time, after collect_modules, before any codegen work begins.

Cross-platform. Runs in the platform-agnostic compile_command driver, so every backend (LLVM / WASM / ArkTS / HarmonyOS / Glance / SwiftUI / JS) inherits the protection from one choke point.

What lockdown refuses

SurfaceDetected via
perry-jsruntime (QuickJS) in graphctx.needs_js_runtime flipped during collection.
perry.nativeLibrary archive referencectx.native_libraries non-empty after resolution.
child_process.* call sitesHIR walker covers every ChildProcess* variant + the general-shape NativeMethodCall { module: "child_process", … } fallback.

All three checks run together; the failure lists every offending surface in one combined diagnostic so the reviewer can address the whole surface at once.

Enabling lockdown (priority order)

  1. CLI flag: perry compile --lockdown src/main.ts. Per-build.

  2. Env var: PERRY_LOCKDOWN=1. CI-friendly. =0 explicitly disables.

  3. package.json: persistent.

    {
      "perry": {
        "lockdown": true
      }
    }
    

Precedence: package.json → env → CLI (last wins, mirrors --fast-math).

Diagnostic example

Error: `--lockdown` refused the build because the following
arbitrary-code-execution surfaces are reachable:
  - perry-jsruntime (QuickJS-based eval-equivalent) is reachable
    from the module graph — see #499 docs for the matching opt-in
    gate
  - `perry.nativeLibrary` archives referenced by: @bloomengine/engine
  - `child_process.*` reached from 2 call site(s):
      - /repo/src/main.ts: child_process.execSync
      - /repo/lib/foo.ts: child_process.spawn

The child_process site list is capped at 12 entries; trailing sites are summarised as ... and N more.

Composing with the rest of the security series

Lockdown is the umbrella mode for the wider supply-chain hardening series (#495#506):

  • #503 — refuses dynamic stdlib dispatch (obj[runtimeVar]()). On by default regardless of lockdown.
  • #499 — gates perry-jsruntime behind explicit host opt-in. Lockdown forces the gate to its strict default.
  • #497 — host allowlist for perry.nativeLibrary / compilePackages. Lockdown refuses any nativeLibrary reference, no allow-list needed.

See also

  • #496 — design discussion.