feat: add multi-engine regex flavour support
This commit is contained in:
@@ -23,10 +23,67 @@ untrusted.
|
||||
identities. Pattern, subject, flags and replacement remain string data passed
|
||||
to the fixed application bridge; no user-supplied Python source is evaluated.
|
||||
Native code-point boundaries are checked before conversion to editor UTF-16.
|
||||
Bounded replacement bytes use canonical base64 rather than content-dependent
|
||||
JSON escaping; declared length, request cap and canonical UTF-8 are validated
|
||||
before the output is exposed.
|
||||
- Java starts only after the worker verifies the TeaVM bridge ABI, engine
|
||||
identity and compiled self-test. It exposes only fixed bounded
|
||||
`Pattern`/`Matcher` entry points; no JVM, Java class loading or user-supplied
|
||||
JavaScript is available. The runtime is TeaVM, not OpenJDK.
|
||||
- PHP starts only after the worker verifies PHP 8.5.8, PCRE2 10.44 and the
|
||||
fixed bridge ABI. User values are JSON data written to a private virtual
|
||||
filesystem; the bridge chooses a safe delimiter, allowlists modifiers and
|
||||
invokes only fixed `preg_*` operations.
|
||||
- The legacy Perl worker writes exact-key, byte-bounded JSON to a fixed MEMFS
|
||||
request path and invokes only the constant `RegexTools::run_request()` entry
|
||||
point. The bridge uses `no re 'eval'`, rejects `(?{...})` and `(??{...})`
|
||||
outside escaped literals/classes, pre-tokenizes its non-executable
|
||||
replacement grammar and streams bounded UTF-8 chunks from native match spans.
|
||||
Successful output uses a separate fixed binary file, never the JSON response;
|
||||
the worker verifies exact bytes, limit and canonical UTF-8 before decoding
|
||||
it. Replacement stops at the match/capture-row bound and leaves the
|
||||
unprocessed subject tail unchanged. WebPerl 0.09-beta's unmodified generated
|
||||
loader contains one `eval(code)` site in an optional
|
||||
JavaScript-interoperability import; the fixed bridge never loads or calls it.
|
||||
The checksummed asset passes the browser CSP smoke without broad
|
||||
`'unsafe-eval'`.
|
||||
- Ruby evaluates only the fixed application bridge during worker startup.
|
||||
Pattern, subject, flags, limits and replacement travel in one bounded,
|
||||
length-prefixed file in the worker-local WASI memory filesystem. Native
|
||||
`String#gsub`/`String#sub` block iteration cannot materialize expanded user
|
||||
output: a fixed CRuby 4.0.0-compatible expander stops at the byte limit and
|
||||
writes that prefix to a separate bounded file. The inert JSON response
|
||||
contains metadata only and is assembled without per-code-point arrays. No
|
||||
user value is interpolated into source or sent through ruby.wasm's
|
||||
`RubyVM.wrap`/`toJS` JavaScript-eval conversion path. Unpaired browser
|
||||
surrogates are rejected before UTF-8 encoding. Ruby cold startup passes the
|
||||
strict-CSP release browser gate.
|
||||
- C++ accepts only structured fixed Embind calls and is compiled with
|
||||
Emscripten `-sDYNAMIC_EXECUTION=0`; the generated module is checked for
|
||||
dynamic-source construction. Its libc++-compatible replacement expander
|
||||
appends directly through the UTF-8 byte cap and is parity-checked at load.
|
||||
Embind returns a structured JavaScript string rather than JSON, so there is
|
||||
no escape amplification; the 64 MiB native buffer and its bounded UTF-16
|
||||
conversion are the explicit peak-output copies.
|
||||
- Go and Rust accept JSON data only through fixed exports. Each validates its
|
||||
request and enforces pattern, subject, result and output caps inside
|
||||
WebAssembly. Adapters measure exact encoded request bytes; the native request
|
||||
cap covers worst-case sixfold JSON escaping for every accepted string field,
|
||||
so control-heavy values retain the documented decoded field limits. Their
|
||||
native-compatible replacement token streams stop at the output cap without
|
||||
allocating a whole capture expansion. Bounded UTF-8 output crosses the JSON
|
||||
bridge as fixed 4:3 base64 rather than content-dependent escaped text. Rust
|
||||
additionally caps compiled-regex and DFA storage.
|
||||
- .NET accepts bounded JSON only through fixed `[JSExport]` methods and never
|
||||
evaluates user input as managed or JavaScript source. A native regex timeout
|
||||
complements the supervisor timeout. Its fixed replacement parser streams
|
||||
native-compatible token fragments through the UTF-8 byte cap, verifies
|
||||
parity with `Match.Result` at load and transports output as canonical base64
|
||||
to avoid JSON escaping amplification. The shipped .NET host contains runtime
|
||||
debugging machinery, but normal production startup disables debugging and
|
||||
is verified under the documented CSP.
|
||||
- Scala compatibility shares the TeaVM Java bridge. It introduces no Scala
|
||||
runtime, dynamic compiler or additional execution surface.
|
||||
- Every bundled engine directory has a closed file set, deterministic
|
||||
metadata/checksums and licence material verified both before installation and
|
||||
in `dist/`. Runtime imports and fetches resolve only against the same-origin
|
||||
@@ -86,12 +143,15 @@ untrusted.
|
||||
closed. Subjects and results are ephemeral and never uploaded or persisted.
|
||||
- No backend, uploads, telemetry, remote corpus URL, CDN, remote font,
|
||||
arbitrary command line or unsafe HTML rendering exists. Application code
|
||||
does not evaluate user-controlled JavaScript or Python. The generic generated
|
||||
Pyodide loader contains an Emscripten dynamic-link branch that uses
|
||||
JavaScript `eval`, but the shipped self-contained CPython/stdlib path does not
|
||||
exercise it and loads under the CSP below without broad `'unsafe-eval'`.
|
||||
does not evaluate user-controlled source in any language. The generic
|
||||
generated Pyodide loader contains an Emscripten dynamic-link branch that
|
||||
uses JavaScript `eval`, while the legacy WebPerl loader contains the optional
|
||||
interop site described above. Neither shipped fixed execution path exercises
|
||||
those branches, and both load under the CSP below without broad
|
||||
`'unsafe-eval'`.
|
||||
|
||||
The engine-enabled build needs a CSP equivalent to:
|
||||
Every enabled profile, including a cold Ruby start, passes the release CSP
|
||||
equivalent to:
|
||||
|
||||
```text
|
||||
default-src 'self';
|
||||
@@ -107,11 +167,12 @@ base-uri 'none';
|
||||
form-action 'none';
|
||||
```
|
||||
|
||||
The Toolbox shell currently requires inline styles. Corpus ZIP generation,
|
||||
PCRE2, Pyodide and TeaVM use self-hosted modules/assets and local workers under
|
||||
the existing `worker-src` and `connect-src` policy. Broad `'unsafe-eval'` is not
|
||||
required; `'wasm-unsafe-eval'` remains required for the two WebAssembly
|
||||
runtimes.
|
||||
The Toolbox shell currently requires inline styles. Corpus ZIP generation and
|
||||
every engine pack use self-hosted modules/assets and local workers under the
|
||||
existing `worker-src` and `connect-src` policy. Broad `'unsafe-eval'` must not
|
||||
be added to accommodate an engine. The release gate blocks any future profile
|
||||
that fails this strict-CSP browser matrix. `'wasm-unsafe-eval'` remains required
|
||||
for the WebAssembly runtimes.
|
||||
|
||||
Report vulnerabilities privately to the repository owner before public issue
|
||||
details are posted.
|
||||
|
||||
Reference in New Issue
Block a user