Skip to content

feat: make V8 JS the primary rule engine; add --js-file; remove -r/--rule#27

Merged
ammario merged 25 commits intomainfrom
blink/v8-js-rule-engine
Sep 11, 2025
Merged

feat: make V8 JS the primary rule engine; add --js-file; remove -r/--rule#27
ammario merged 25 commits intomainfrom
blink/v8-js-rule-engine

Conversation

@blink-so
Copy link
Copy Markdown
Contributor

@blink-so blink-so Bot commented Sep 11, 2025

This PR promotes JavaScript (V8) to the primary rule engine, adds --js-file, and removes the legacy -r/--rule pattern engine.

Key changes:

  • Make JavaScript evaluation first-class (non-experimental)
  • Add --js-file flag to load JS source from a file (conflicts with --js)
  • Remove -r/--rule and the PatternRuleEngine
  • Convert tests to use JS-based rules
  • Default deny policy when no evaluator is provided
  • Keep script evaluation (--script) as an alternative
  • Update README and examples to use JS and --js-file

Developer notes:

  • Linux/macOS integration tests were updated to express previous rule semantics in JS
  • CLI help reflects the new flags and conflicts

If you want me to split this into smaller PRs or retain -r as a deprecated alias temporarily, say the word and I can adjust.

blink-so Bot and others added 4 commits September 11, 2025 14:02
Adds experimental support for JavaScript-based request evaluation using
Google's V8 engine via the rusty_v8 crate. This provides more flexible
and powerful rule logic compared to regex patterns or shell scripts.

Features:
- New --js flag for JavaScript rule evaluation
- V8 isolate-based execution for security and performance
- Global variables: url, method, host, scheme, path
- Return true to allow, false to block requests
- Fresh context per evaluation for thread safety
- Comprehensive error handling for syntax and runtime errors
- Full test coverage including unit and integration tests
- Updated documentation with examples and performance notes

The implementation prioritizes thread safety over performance optimization
by creating fresh V8 contexts for each evaluation. This ensures reliable
operation in the async, multi-threaded environment while maintaining
the security sandbox properties of V8.

Conflicts with --script, --rule, and --config flags as only one
evaluation method can be active at a time.

Co-authored-by: ammario <7416144+ammario@users.noreply.github.com>
@ammario ammario marked this pull request as ready for review September 11, 2025 14:23
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex Review: Here are some suggestions.

Reply with @codex fix comments to fix any unresolved comments.

About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you open a pull request for review, mark a draft as ready, or comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex fix this CI failure" or "@codex address that feedback".

Comment thread src/rules/v8_js.rs
Comment on lines +31 to +34
V8_INIT.call_once(|| {
let platform = v8::new_default_platform(0, false).make_shared();
v8::V8::initialize_platform(platform);
v8::V8::initialize();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] Keep V8 platform alive for entire process

The V8 engine requires the platform object passed to V8::initialize_platform to remain alive for the duration of the program. V8JsRuleEngine::new allocates the platform inside a Once and immediately drops it (lines 31‑34). After the call_once closure returns, the SharedRef’s refcount reaches zero, so V8 continues running with a dangling pointer. Any subsequent isolate creation can crash or exhibit undefined behaviour as soon as JavaScript evaluation is attempted. Store the SharedRef in a static (e.g., OnceLock<SharedRef<Platform>>) so it outlives all isolates before calling initialize_platform.

Useful? React with 👍 / 👎.

- Remove legacy -r/--rule flag and rule config workflows
- Add --js-file flag (conflicts with --js) to load JavaScript from file
- Make JavaScript evaluation first-class (non-experimental)
- Remove PatternRuleEngine; refactor tests to use JS
- Update README to document JS and --js-file; remove regex/config docs
- Keep script evaluation; default to deny-all when no evaluator provided

Co-authored-by: ammario <7416144+ammario@users.noreply.github.com>
@blink-so blink-so Bot changed the title feat: add V8 JavaScript rule engine with --js flag feat: make V8 JS the primary rule engine; add --js-file; remove -r/--rule Sep 11, 2025
blink-so Bot and others added 20 commits September 11, 2025 14:50
…st platform; adjust logs per CLI guidance; resolve merge in tests/common
- Changed JS API from function-based to expression-based evaluation
  - Before: --js "return host === 'github.com'"
  - After: --js "r.host === 'github.com'"
- Moved all jail variables into 'r' namespace object
  - Variables now accessed as r.url, r.method, r.host, r.scheme, r.path
  - Frees up global scope for user-defined variables
- Added r.block_message for custom denial messages
  - Scripts can set r.block_message to provide context in 403 responses
- Updated all tests and documentation for new API

This makes JS rules more concise and provides better separation between
jail-provided variables and user code.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
The test_server_mode test was still using the old regex-based rule
syntax (-r flag). Updated to use the new JavaScript expression syntax.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
The CI was incorrectly using --bins flag which doesn't run the library
unit tests where the V8 JS tests are located. Changed to --lib to run
the actual unit tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed all remaining unit tests that were still using the old function-based
JavaScript syntax with 'return' statements. Updated to use the new expression
evaluation syntax with 'r.' namespace for variables.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Updated all integration tests to use the new JavaScript expression evaluation
syntax with 'r.' namespace. Removed old regex-based rule syntax (-r flag)
from concurrent isolation tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove 'return' statements from JS expressions in system_integration tests
- Replace -r flag with --js in network diagnostic tests
- Simplify boolean logic for HTTPS connect tests
- Document how to SSH into ci-1 instance for debugging
- Note that only Coder employees have access
- Add commands for manual testing on CI
…y files

- Scan /etc/netns directory directly for orphaned namespace configs
- Handle cases where /tmp is cleaned but namespace configs remain
- Avoid duplicate cleanup of same jail ID
- Should fix CI connectivity issues from leftover resources
The proxy was binding to 127.0.0.1 by default, making it inaccessible
from the veth interface in the network namespace. This caused all
connections to be refused in strong jail mode.

- Bind to 0.0.0.0 when in strong jail mode (not weak, not server)
- Keep localhost binding for weak mode and server mode
- This fixes the Linux integration test failures on CI
- Replace old -r regex flag with --js in Linux-specific test
- Remove unused mut warning (HashSet only modified on Linux)
- All Linux integration tests now passing
The mut is needed on Linux but not on macOS, causing platform-specific
clippy warnings. Added #[allow(unused_mut)] attribute to handle this.
Remove 'return' from JS expressions in test_comprehensive_resource_cleanup
and test_cleanup_after_sigint tests.
The proxy needs to be accessible from the network namespace's veth interface.
Since localhost (127.0.0.1) in the namespace is isolated from the host's
localhost, we must bind to an IP reachable from the namespace.

Current approach binds to 0.0.0.0 which works but has security implications.
Added TODO comment referencing GitHub issue #31 for tracking the proper fix
(binding to specific veth IP instead of all interfaces).
- Replace old rule-based examples (-r flag) with JavaScript expressions
- Update configuration file examples from rules.txt to rules.js
- Show proper JavaScript syntax for regex patterns and method-specific filtering
- Maintain consistency with the new V8 JS evaluation approach
@ammario ammario merged commit 40276c2 into main Sep 11, 2025
7 checks passed
@ammario ammario deleted the blink/v8-js-rule-engine branch September 11, 2025 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant