constitution · epochs · watch · epoch 4

commit

c_543401e1c5e6e7e82e

tommy-mor · sha1:f7c9247de820c1be1a033e35a18817e0fd70144d

download patch · raw event

message

Bind signed-snippet slots as eval locals to close an RCE (#5)

* Bind signed-snippet slots as eval locals to close an RCE

The POST handler ran eval() on a snippet whose $slots were spliced into
the source string via repr-scrubbing. Scrubbing is safe per value, but the
library substitutes every form field in sequential passes over the evolving
string, so a value like "$q" reintroduces a live slot inside an
already-scrubbed literal; scrubbing the referenced field's payload then
realigns the string quotes and lands attacker bytes in code position. An
authenticated user could reach arbitrary code execution through the redeem
form.

Verify the signature and one-time nonce, then rewrite each $slot to a bare
name and bind its value into eval's locals. Request values are handed to
eval as data and are never parsed as code, so the injection class is gone.
Only declared slots are bound, so extra fields cannot shadow globals.

Co-authored-by: tommy <thmorriss@gmail.com>

* Adopt upstream evaleval snippet-binding fix; drop local workaround

evaleval e330d82 fixes the nested-$ snippet RCE at the source: verify_snippet
now returns a BoundSnippet that binds each $slot's value as an eval local
instead of splicing it into the source string. Repin to that commit and call
signer.verify_snippet(form).eval(globals()), removing the local _bind_snippet
shim added while the upstream fix was pending.

Regression tests updated to drive the real verify_snippet/BoundSnippet path:
the nested-$ payload is evaluated as an inert string, extra fields can't
shadow globals, bad signatures and reused nonces are rejected.

Co-authored-by: tommy <thmorriss@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

comparisons involving this commit

None yet.

The full patch is loaded only by the download route: download patch

Metadata
commit_idc_543401e1c5e6e7e82e1d16e0717d3c64992f271935d7f855647f11ce1e29cfd6
patch_sha256f59cfe2894a65142f1f1003d84d18744b3218f027d6513db0e494e2471ed83de
patch_identitygit-patch-id-stable-v1:e6f623451d650d66b41a42d32585c1f0c6434837
committer_timestamp_ms1784629783000