fix(wasi): reject dynamic Net URL at compile time (symmetry with Fs)#20
Merged
Conversation
In --wasi mode a dynamic (non-literal) URL passed to Net.get/post was not refused at compile time. Instead the call site emitted a runtime fail-closed (Err(IoError) without touching the network), which an Err(_) -> () arm could swallow silently, degrading output with no warning (observed in the capa_governance_pack pilot, where an interpolated URL returned "no CVE matches" instead of 4). Fs already refuses a dynamic path at compile time in _validate_wasi_caps when its preopen ceiling is not closed. This adds the symmetric Net rule: when Net.get/post is used and the NetCeiling is not closed (some dynamic URL reaches a request op), raise a clear WasmEmissionError at compile time, mirroring the Fs message and using the NetCeiling.closed flag. The net ceiling is computed before _validate_wasi_caps runs and whenever get/post is used, so every dynamic URL is covered by the compile-time refusal; no dynamic URL can still reach runtime unrefused. The runtime fail-closed in the call-site emitter is kept as defence-in-depth. Env is intentionally not aligned: it stays at Level 2 inherit_env on a dynamic key. Tests: updated the two previously-runtime-fail-closed tests to assert compile-time rejection, and added TestWasiNetDynamicUrlRejections (interpolated URL, param URL, let-bound literal, post param, mixed literal+dynamic, plus a literal-still-compiles control). Full suite: 3437 tests OK (18 skipped).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A security/usability ASYMMETRY in the experimental
--wasimode, found in the pilot:Fspath is refused at COMPILE time (clearWasmEmissionErrorin_validate_wasi_caps).NetURL (e.g. interpolated"...?q=${name}") was NOT refused at compile time. The call site instead emitted a RUNTIME fail-closed (Err(IoError)without touching the network). A program with anErr(_) -> ()arm swallowed that error silently and degraded its output with no warning (in the pilot,capa_governance_packreturned "no CVE matches" instead of 4, because the URL was interpolated).We want SYMMETRY: a dynamic
NetURL should also be refused at compile time, making the problem visible to the programmer instead of a silent degradation.Fix
In
_validate_wasi_caps(capa/ir/_emit_wasm/_wasi.py), right after the existing Fs dynamic-path refusal, add the symmetric Net refusal: when a request-building Net op (get/post) is used AND theNetCeilingis NOT closed (some dynamic URL reaches a request op), raise aWasmEmissionErrorat compile time with a clear message analogous to the Fs one, using theNetCeiling.closedflag (exact mirror of the Fs logic).Coverage: the net ceiling is computed before
_validate_wasi_capsruns and under the sameget/post-used condition, andclosedreflects EVERYget/postcall site across the whole inlined module. So every dynamic-URL program is refused at compile time; no dynamic URL can still reach runtime unrefused.The runtime fail-closed in the call-site emitter (
_emit_wasi_net_get_call/_emit_wasi_net_post_call) is RETAINED as defence-in-depth.Envis intentionally NOT aligned: it stays at Level 2inherit_envon a dynamic key.Tests
TestWasiNetCeiling/TestWasiNetPostCeiling) to assert the compile-time rejection.TestWasiNetDynamicUrlRejections: interpolated URL, param URL,let-bound literal, post param URL, mixed literal+dynamic, plus a literal-still-compiles positive control.TestWasiNetGet/Post, attenuation) stay green; Fs behaviour unchanged.Full suite:
Ran 3437 tests ... OK (skipped=18).Behaviour change
A
--wasiprogram with a dynamic URL that previously "ran" (silent fail-closed) now does NOT compile under--wasi(visibility > silent degradation). Make the URL a string literal or use the defaultcapa:hostbackend (drop--wasi).capa_governance_pack(interpolated URL) will be refused under--wasiuntil its URL is a literal; correct, handled in the program-update phase / when const-prop lands.