diff --git a/engines/viperjs/Dockerfile b/engines/viperjs/Dockerfile
new file mode 100644
index 00000000..c750a27d
--- /dev/null
+++ b/engines/viperjs/Dockerfile
@@ -0,0 +1,19 @@
+# SPDX-FileCopyrightText: 2026 Ivan Krasilnikov
+# SPDX-License-Identifier: MIT
+
+ARG BASE=jsz-rust
+FROM $BASE
+
+WORKDIR /src
+ARG REPO=https://github.com/MerlijnW70/viperjs.git
+RUN git clone --depth=1 "$REPO" .
+
+ARG REV=master
+RUN git fetch --depth=1 origin "$REV" && git checkout FETCH_HEAD && git rev-parse HEAD
+
+# No system dependencies: the engine has zero runtime dependencies and an empty
+# dependency table, so the base image's stable toolchain is all that is needed.
+RUN cargo build --release --bin viper
+
+COPY build/dist.py ./
+RUN ./dist.py /dist/viperjs --binary=/src/target/release/viper
diff --git a/engines/viperjs/Makefile b/engines/viperjs/Makefile
new file mode 100644
index 00000000..56866004
--- /dev/null
+++ b/engines/viperjs/Makefile
@@ -0,0 +1,6 @@
+# SPDX-FileCopyrightText: 2026 Ivan Krasilnikov
+# SPDX-License-Identifier: MIT
+
+include ../../build/build.mk
+
+$(eval $(call build_engine,viperjs,Dockerfile))
diff --git a/engines/viperjs/README.md b/engines/viperjs/README.md
new file mode 100644
index 00000000..f2870f72
--- /dev/null
+++ b/engines/viperjs/README.md
@@ -0,0 +1,22 @@
+# ViperJS
+
+Embeddable JavaScript engine in safe Rust, with zero runtime dependencies.
+
+* Repository: [MerlijnW70/viperjs](https://github.com/MerlijnW70/viperjs.git) 
+* LOC: [103829](# "cloc --not_match_d='(?i)(test)' src")
+* Language: Rust
+* License: MIT OR Apache-2.0
+* Standard: ES2023 (partial)
+* Years: 2026-
+* Interpreter: stack-based VM
+* Regex engine: own (backtracking)
+
+Notable for what it refuses rather than what it adds: the dependency table is empty and checked
+in CI, the crate is `#![forbid(unsafe_code)]`, and no input may panic. `RegExp` is therefore its
+own backtracking engine rather than a crate, and there is no `require`, no `fs` and no module
+loading in the command-line host — the embedder provides I/O.
+
+The command line binds `print` and a `console` of six logging methods — `log`, `info` and `debug`
+to standard output, `warn`, `error` and `trace` to standard error. A run can be given a wall-clock
+budget that a script cannot `catch`, and a memory budget it cannot exceed, which is what makes an
+untrusted script safe to embed.
diff --git a/harness/config.yml b/harness/config.yml
index 8ba29bd1..53706e17 100644
--- a/harness/config.yml
+++ b/harness/config.yml
@@ -1426,6 +1426,19 @@ yantra: &yantra
timeout_sec: 10
<<: *oom_prone
+viperjs:
+ console_log: print
+ crash_re:
+ - *rust_crash_re
+ stderr_replace_re:
+ - *rust_crash_norm_re
+ errors_re:
+ # viper: TypeError: cannot read a property of something that is not an object
+ # An uncaught throw is reported on stderr, prefixed with the program name, and exits 1.
+ - '^viper: (?P[A-Za-z0-9]*Error): (?P.+)$'
+ # A thrown value that is not an Error keeps whatever ToString gives it.
+ - '^viper: (?P.+)$'
+
yrm006:
console_log: print
stdout_replace_re: