5295 Commits

Author SHA1 Message Date
Greg Johnston
8b28a95966 fix: handle <For/> keys correctly in non-async HTML rendering (see 2026-07-08 09:33:12 -04:00
Greg Johnston
7c0d1c169b chore: publish patch version 2026-06-28 07:38:09 -04:00
Greg Johnston
7b86fc62f5 Revert "fix(tachys): escape <textarea> children to prevent XSS" (#4819)
This reverts commit 9417ed441e.
2026-06-28 07:33:38 -04:00
Greg Johnston
e9246c90d0 chore: publish patch version 2026-06-25 10:42:39 -04:00
Greg Johnston
c3f7392398 Revert "chore: don't rely on unstable wasm bindgen apis (#4741)" (#4816)
This reverts commit 00a388a021.
2026-06-25 10:40:23 -04:00
Greg Johnston
30fa4e0394 chore: publish patch versions v0.8.19 2026-06-25 06:43:31 -04:00
Greg Johnston
a3038e41b4 Merge pull request #4812 from leptos-rs/escaping-fixes
Escaping fixes backported from 0.9
2026-06-25 06:39:48 -04:00
Greg Johnston
7eb5061e2f fix: respect Axum/Actix built-in body size limits (#4813) 2026-06-25 06:39:30 -04:00
autofix-ci[bot]
14a34578a6 [autofix.ci] apply automated fixes 2026-06-25 01:16:25 +00:00
Saber Haj Rabiee
d5b7dcb94d chore: cargo fmt
(cherry picked from commit 6e44ab2d0c)
2026-06-24 20:06:43 -04:00
Saber Haj Rabiee
12e1d7c04c fix(leptos_macro): escape <textarea> content in inert HTML path
The `view!` macro's static ("inert") HTML generator grouped `<textarea>`
with the true raw-text elements `<script>` and `<style>`, emitting its
children without HTML escaping.

Unlike `<script>`/`<style>`, `<textarea>` is *escapable* raw text per the
HTML spec, so its content must be escaped. Leaving it unescaped diverged
from the runtime render path (which escapes textarea children) and could
emit malformed markup for static content containing `<`, `>`, or `&`.

Drop `textarea` from the raw-text exemption at all three inert-path sites
(element, SVG element, and the node dispatcher) so its children are
escaped like every other normal element.

Adds SSR integration tests covering both the inert (static) textarea path
and the runtime (dynamic) textarea path.

(cherry picked from commit fce59d4766)
2026-06-24 20:06:36 -04:00
Saber Haj Rabiee
9417ed441e fix(tachys): escape <textarea> children to prevent XSS
`<textarea>` was declared with `ESCAPE_CHILDREN: false`, lumping it in
with the true raw-text elements `<script>`, `<style>`, and `<noscript>`.

Per the HTML spec, `<textarea>` content is *escapable* raw text: it
cannot contain a literal `<` or `&`, and any case-insensitive
`</textarea>` closes the element. Treating it as non-escapable meant an
untrusted string flowing into a textarea body was emitted verbatim, so
input such as `</textarea><script>alert('xss')</script>` broke out of
the element and injected live markup — an XSS sink.

Flip `ESCAPE_CHILDREN` to `true` for the `textarea` row so its children
are HTML-escaped like every other normal element.

Adds an SSR regression test asserting the breakout payload is escaped.

(cherry picked from commit c7acf0cb23)
2026-06-24 20:06:26 -04:00
Saber Haj Rabiee
889e0b5b52 fix(tachys): escape char when rendering to HTML
`RenderHtml::to_html_with_buf` for primitive types ignored the `escape`
argument and wrote the value directly with `write!(buf, "{}", self)`.

For numeric / `bool` / `IpAddr` / `NonZero*` primitives this is harmless:
their `Display` output is a syntactic subset of HTML text. `char`,
however, can be any Unicode scalar value, including `<`, `>`, `&`, `"`,
and `'`. Writing an untrusted `char` into an element body without
escaping is an HTML-injection / XSS sink, and it contradicts the
documented contract of the `escape` flag (already honored for
`&str` / `String` / `Cow<str>` / `Arc<str>`).

Parametrize `render_primitive!` with an escaping flag. `char` is now
rendered through `html_escape::encode_text` when the enclosing element
escapes its children; in a raw-text context (`escape == false`) it is
still written verbatim. All other primitives keep their previous,
allocation-free direct write, so their output is byte-identical.

Adds regression tests covering the escaped, raw-text, and numeric cases.

(cherry picked from commit b84df90e44)
2026-06-24 20:06:14 -04:00
Saber Haj Rabiee
e47704fbe6 fix(hydration_context): escape < in serialized errors to block <script> breakout
`SsrSharedContext::pending_data` and `AsyncDataStream::poll_next` emit each
registered error into a `<script>` block as `[<boundary>, <id>, {:?}]` where
the third field is the error's `Display` output. Rust's `{:?}` only escapes
`"` and `\` — it does not escape `<`. The matching resolved-resource path is
already careful to do `data.replace('<', "\\u003c")` before formatting, but
the error path was not, so any `</script>` substring that ends up inside an
error message closes the surrounding script tag in the browser's HTML
tokenizer and lets the following bytes be parsed as new HTML.

Reproducer:

    use hydration_context::{SerializedDataId, SharedContext, SsrSharedContext};
    use throw_error::{Error, ErrorId};
    use std::fmt;
    use futures::{StreamExt, executor::block_on};

    #[derive(Debug)]
    struct E(&'static str); impl fmt::Display for E {
        fn fmt( & self, f: & mut fmt::Formatter<'_>) -> fmt::Result {
            f.write_str(self.0)
        }
    }
    impl std::error::Error for E {}

    let ctx = SsrSharedContext::new();
    ctx.register_error(
        SerializedDataId::new(0),
        ErrorId::from(0_usize),
        Error::from(E("boom</script><script>alert('pwned')</script><script>")),
    );
    let mut s = ctx.pending_data().unwrap();
    let chunk = block_on(s.next()).unwrap();
    // Before the fix, `chunk` contains a literal `</script>` substring
    // that closes the enclosing <script> in the streamed HTML.

Realistic input sources: any user-controllable text that can flow into an
`Error` body (route parameters, deserialization errors that echo the input,
server-fn error messages, etc.) becomes an XSS sink.

Fix: before formatting the error message, every `<` character in it is
rewritten to the six-character sequence `<` (backslash + u + 0 + 0 + 3
+ c) — the same transformation the resolved-resource path already applies
in `ResolvedData::write_to_buf` and `AsyncDataStream`. Concretely:

    let msg = error.2.to_string().replace('<', "\\u003c");
    write!(out, "[{}, {}, {:?}],", error.0.0, error.1, msg);

The HTML tokenizer scanning the resulting script body no longer sees a
literal `<`, so it cannot recognise `</script>` and the script tag stays
open. The JS engine then parses the string literal and a downstream JSON
unescape turns `<` back into `<` for the consumer, matching the
existing resource-data behaviour.

Both write sites are patched (initial chunk emission and the streaming
`__SERIALIZED_ERRORS.push(...)` path) and a regression test for each is
added — these are also the first tests this crate has ever shipped.

(cherry picked from commit 6a59c51641)
2026-06-24 20:05:09 -04:00
Greg Johnston
4bc42943a2 chore: clean up some leptos_macro docs (#4811) 2026-06-24 19:41:46 -04:00
dependabot[bot]
0aa51a3829 chore(deps): bump actions/checkout from 6 to 7 (#4808)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-24 19:35:02 -04:00
Noethix
0dabbf661d chore: return early instead of panic in Form on invalid submitter (#4798) 2026-06-24 19:34:49 -04:00
Noethix
16081db085 feat: allow fallible try_set_server_url (#4795) 2026-06-24 19:30:48 -04:00
Greg Johnston
480d615542 Merge pull request #4790 from Noethix55555/fix/static-segment-partial-match
fix(router): reject over-long static segment instead of partial-matching
2026-06-24 14:22:40 -04:00
edmondj
b0cf8b558a feat(leptos_macro): Adding a lazy_preload macro (#4729) 2026-06-24 14:20:31 -04:00
Baptiste
3e3d594b6d feat: add #[prop(marker)] for marker types (#4774) 2026-06-24 12:52:41 -04:00
Greg Johnston
4166c1a15d fix: notify when structure changes during keyed patch (closes #4806) (#4807) 2026-06-24 07:23:30 -04:00
Noethix
1d699ffd26 fix(router): propagate error instead of unwrapping in anchor click handler (#4789)
Co-authored-by: Noethix55555 <277300782+Noethix55555@users.noreply.github.com>
2026-06-19 12:24:01 -04:00
Noethix
511f41394e fix(tachys): pass FROM_SERVER=false in AnyAttribute::hydrate_from_template 2026-06-19 12:22:33 -04:00
Sai Asish Y
23e3cadd33 chore: remove unused LeptosOptions import from render_app_to_stream_with_context example (#4714) 2026-06-19 12:14:15 -04:00
Skyf0l
7233bfbea0 feat(macro): collapse reactive child closure monomorphizations on --cfg erase_components (#4711) 2026-06-19 12:13:50 -04:00
Thomas Anagrius
a6b07b193f feat(nonce): add Nonce::from_value for externally-supplied CSP nonces 2026-06-19 12:13:05 -04:00
Greg Johnston
b2d0d8fad1 add an explicit AI policy 2026-06-18 15:02:44 -04:00
Greg Johnston
f1af13231a chore: remove old TODO file 2026-06-18 15:02:39 -04:00
Noethix55555
123eec6138 fix(router): reject over-long static segment instead of partial-matching
When the pattern iterator is exhausted but the URL still has characters
remaining (not a slash), the loop was breaking out instead of returning
None. This caused StaticSegment(fo) to falsely match /foobar.
Changed the break to return None so only exact segment boundaries match.
2026-06-17 19:49:19 -04:00
Greg Johnston
2d88555f50 fix: defer owner drop in OwnedView (closes #4769) (#4771) 2026-06-10 21:51:58 -04:00
Greg Johnston
f558dfa93c fix: ensure that nested cleanups happen in right order (closes #4758) (#4762) 2026-06-05 14:23:42 -04:00
Evan Almloff
00a388a021 chore: don't rely on unstable wasm bindgen apis (#4741) 2026-05-28 20:33:49 -04:00
Saber Haj Rabiee
91c5873977 fix(CI): drop wretry wrapper from action steps (#4743)
wretry.action does not forward the wrapped action's `with` inputs, so
pnpm/action-setup ran without version: 8 and installed the latest pnpm,
which requires Node.js 22.13 and failed on the Node 20 runner. Call
actions/checkout, actions/setup-node, pnpm/action-setup and
denoland/setup-deno directly so their inputs take effect.
2026-05-27 19:45:08 -04:00
Saber Haj Rabiee
4c7e8bf698 fix(CI): use official actions for toolchain and binary installs (#4742)
Wandalen/wretry.action only supports node and docker actions and errors
on composite actions. Use dtolnay/rust-toolchain, cargo-bins/cargo-binstall
and taiki-e/install-action directly; they already retry their downloads
internally (curl --retry 10 and retry loops).
2026-05-27 17:09:19 -04:00
Saber Haj Rabiee
6d4dc8bd85 fix(CI): do not fail fast (#4740) 2026-05-27 08:55:41 -04:00
Paul Hansen
23999de81a chore: Remove regex dependency from leptos_config (#4696) v0.9.0-alpha 2026-05-08 12:57:30 -04:00
Greg Johnston
6d49f73bfc fix: issues with nested keyed store field initialization (see #4697) (#4699) 2026-05-08 12:53:10 -04:00
Greg Johnston
afcdc6c319 Merge pull request #4704 from NCura/patch-1
fix: broken link and change name in example
2026-05-06 13:48:41 -04:00
Nicolas Cura
980dad2af6 Fix broken link in MultiActionForm documentation 2026-05-06 10:01:29 +02:00
Nicolas Cura
4dc3c98ab9 Change Action to ServerAction in the example component talking about server functions 2026-05-06 09:34:18 +02:00
Alec Mocatta
fcc48d6245 fix: immediate effect memo recomputation (#4683) 2026-05-01 11:40:41 -04:00
dependabot[bot]
1e3ec4525f chore(deps): bump pnpm/action-setup from 5 to 6 (#4681)
Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 5 to 6.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v5...v6)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 11:40:05 -04:00
dependabot[bot]
aa5259eb9e chore(deps): bump autofix-ci/action from 1.3.3 to 1.3.4 (#4686)
Bumps [autofix-ci/action](https://github.com/autofix-ci/action) from 1.3.3 to 1.3.4.
- [Release notes](https://github.com/autofix-ci/action/releases)
- [Commits](https://github.com/autofix-ci/action/compare/v1.3.3...v1.3.4)

---
updated-dependencies:
- dependency-name: autofix-ci/action
  dependency-version: 1.3.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 11:39:54 -04:00
dependabot[bot]
7799d08133 chore(deps): bump rustls-webpki from 0.103.8 to 0.103.13 (#4689)
Bumps [rustls-webpki](https://github.com/rustls/webpki) from 0.103.8 to 0.103.13.
- [Release notes](https://github.com/rustls/webpki/releases)
- [Commits](https://github.com/rustls/webpki/compare/v/0.103.8...v/0.103.13)

---
updated-dependencies:
- dependency-name: rustls-webpki
  dependency-version: 0.103.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 11:39:42 -04:00
dependabot[bot]
0aadd5fa60 chore(deps): bump actix-http from 3.11.2 to 3.12.1 (#4690)
Bumps [actix-http](https://github.com/actix/actix-web) from 3.11.2 to 3.12.1.
- [Release notes](https://github.com/actix/actix-web/releases)
- [Changelog](https://github.com/actix/actix-web/blob/main/CHANGES.md)
- [Commits](https://github.com/actix/actix-web/compare/http-v3.11.2...http-v3.12.1)

---
updated-dependencies:
- dependency-name: actix-http
  dependency-version: 3.12.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-01 11:39:29 -04:00
ruburi
0473679290 chore: update outdated Trunk links (#4687) 2026-04-23 15:49:32 -04:00
Greg Johnston
a7bb7144ef chore: clippy (#4685) 2026-04-17 23:04:20 -04:00
Greg Johnston
fbc9ed631f chore: publish patch versions v0.8.18 2026-04-16 13:11:03 -04:00
Greg Johnston
88e2d535cc chore: pull in latest wasm_split_helpers version (fixes breakage from https://github.com/rust-lang/rust/pull/149868) (#4684) 2026-04-16 13:07:20 -04:00