streamlit-nightly 1.53.2.dev20260202__py3-none-any.whl → 1.53.2.dev20260203__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. streamlit/commands/logo.py +6 -10
  2. streamlit/components/v2/component_path_utils.py +17 -29
  3. streamlit/config.py +4 -2
  4. streamlit/path_security.py +98 -0
  5. streamlit/runtime/app_session.py +9 -1
  6. streamlit/static/index.html +1 -1
  7. streamlit/static/manifest.json +312 -312
  8. streamlit/static/static/js/{ErrorOutline.esm.CLuz0rSD.js → ErrorOutline.esm.C9uHPmIj.js} +1 -1
  9. streamlit/static/static/js/{FileDownload.esm.CO68LcnZ.js → FileDownload.esm.D-YPxF3t.js} +1 -1
  10. streamlit/static/static/js/{FileHelper.DAXgY6Ug.js → FileHelper.DQSH0zYW.js} +1 -1
  11. streamlit/static/static/js/{FormClearHelper.zxJ53Nym.js → FormClearHelper.DQoXcOWo.js} +1 -1
  12. streamlit/static/static/js/{InputInstructions.CCbg8esE.js → InputInstructions.C7VMyGT7.js} +1 -1
  13. streamlit/static/static/js/{Particles.BJw0A-zv.js → Particles.BdQSRZde.js} +1 -1
  14. streamlit/static/static/js/{ProgressBar.BrrHeAEh.js → ProgressBar.DNF_pWKr.js} +1 -1
  15. streamlit/static/static/js/{StreamlitSyntaxHighlighter.DvPLy3zk.js → StreamlitSyntaxHighlighter.Cys9Bt18.js} +2 -2
  16. streamlit/static/static/js/{TableChart.esm.BawvAi5p.js → TableChart.esm.B9SMgSK4.js} +1 -1
  17. streamlit/static/static/js/{Toolbar.CbpscbNb.js → Toolbar.BXfC9Z-W.js} +1 -1
  18. streamlit/static/static/js/{WidgetLabelHelpIconInline.DA4S2HFP.js → WidgetLabelHelpIconInline.gkreC55g.js} +1 -1
  19. streamlit/static/static/js/{base-input.BKKl2eBF.js → base-input.iB32RS3w.js} +4 -4
  20. streamlit/static/static/js/{checkbox.CB43AKV4.js → checkbox.Bqz68SYq.js} +1 -1
  21. streamlit/static/static/js/{createDownloadLinkElement.jVwF96ey.js → createDownloadLinkElement.YxVC9Qur.js} +1 -1
  22. streamlit/static/static/js/{data-grid-overlay-editor.CxQizSv7.js → data-grid-overlay-editor.sBsdk5Xg.js} +1 -1
  23. streamlit/static/static/js/{downloader.CKlIgsy5.js → downloader.Bzxqt3AW.js} +1 -1
  24. streamlit/static/static/js/{embed.BhRb_2n8.js → embed.CDzakah3.js} +1 -1
  25. streamlit/static/static/js/{es6.DPyfPmWm.js → es6.CxCc4bfn.js} +2 -2
  26. streamlit/static/static/js/{formatNumber.DtfMnnPx.js → formatNumber.L8T7D36k.js} +1 -1
  27. streamlit/static/static/js/{iconPosition.DkZAlu_k.js → iconPosition.C47DkA-1.js} +1 -1
  28. streamlit/static/static/js/{iframeResizer.contentWindow.l5sQWLra.js → iframeResizer.contentWindow.uEFLXEg3.js} +1 -1
  29. streamlit/static/static/js/{index.DDr-BLbJ.js → index.B3zULhHv.js} +1 -1
  30. streamlit/static/static/js/{index.LjqoQCm5.js → index.B60AZFRh.js} +1 -1
  31. streamlit/static/static/js/{index.BzO83wKm.js → index.BG4RxMOI.js} +1 -1
  32. streamlit/static/static/js/{index.y5HxPwg9.js → index.BHyzKS4e.js} +20 -20
  33. streamlit/static/static/js/{index.Bc_FQ4Wb.js → index.BVTW_o-a.js} +1 -1
  34. streamlit/static/static/js/{index.BUlT_mOL.js → index.BV_YgIHe.js} +1 -1
  35. streamlit/static/static/js/{index.WIMtx3m0.js → index.B_LfkwqU.js} +1 -1
  36. streamlit/static/static/js/{index.DiBeetOH.js → index.Ba8L-ulI.js} +1 -1
  37. streamlit/static/static/js/{index.CsEZTo6L.js → index.Bh5BZaHG.js} +1 -1
  38. streamlit/static/static/js/{index.DmWUXdjc.js → index.Bnwh8oZr.js} +16 -16
  39. streamlit/static/static/js/{index.CAoX2tlo.js → index.BrZtYm2A.js} +1 -1
  40. streamlit/static/static/js/{index.Y9wPTZIf.js → index.BsrhCS7f.js} +1 -1
  41. streamlit/static/static/js/{index.465nmxtO.js → index.BuJPJSD7.js} +1 -1
  42. streamlit/static/static/js/{index.BAK0CG1Q.js → index.BvHsyiyy.js} +1 -1
  43. streamlit/static/static/js/{index.DzdPUxsx.js → index.BwTkGOAy.js} +1 -1
  44. streamlit/static/static/js/{index.yHLCvUGh.js → index.BwvxzVOo.js} +1 -1
  45. streamlit/static/static/js/{index.Ck64OQhV.js → index.BzdcdLDK.js} +1 -1
  46. streamlit/static/static/js/{index.CiS4giQ2.js → index.C1d2QjTR.js} +1 -1
  47. streamlit/static/static/js/{index.CaU3Uv_L.js → index.C1uZrWog.js} +1 -1
  48. streamlit/static/static/js/{index.FioS1Y9m.js → index.C5-TpWis.js} +1 -1
  49. streamlit/static/static/js/{index.rvbQETlC.js → index.C6dhwBSe.js} +1 -1
  50. streamlit/static/static/js/{index.e6Ry6-Ft.js → index.CAbQaUvi.js} +1 -1
  51. streamlit/static/static/js/{index.Dac9Jib-.js → index.CAbafj7s.js} +1 -1
  52. streamlit/static/static/js/{index.CL_icBXS.js → index.CCLteRW6.js} +1 -1
  53. streamlit/static/static/js/{index.OizPL4jg.js → index.CQ713nQM.js} +1 -1
  54. streamlit/static/static/js/index.CcBYyLfq.js +2 -0
  55. streamlit/static/static/js/{index.DKoJr0Se.js → index.CjBDVb1a.js} +1 -1
  56. streamlit/static/static/js/{index.BLD3tJ2C.js → index.Ck0ZkOfK.js} +1 -1
  57. streamlit/static/static/js/{index.Ccye_uLl.js → index.CzwJzgQs.js} +1 -1
  58. streamlit/static/static/js/{index.CL7it7tU.js → index.D-9VyyiA.js} +1 -1
  59. streamlit/static/static/js/{index.b_f-McZ5.js → index.D2R3Co5f.js} +1 -1
  60. streamlit/static/static/js/{index.L9pOjBEn.js → index.D7L9gHlE.js} +2 -2
  61. streamlit/static/static/js/{index.YutgmD9x.js → index.DEKnCsY-.js} +2 -2
  62. streamlit/static/static/js/{index.CmbqbRMZ.js → index.DHrByikW.js} +1 -1
  63. streamlit/static/static/js/{index.DZOGT9vX.js → index.DN_oudQl.js} +1 -1
  64. streamlit/static/static/js/{index.DjuMEZ6m.js → index.DO55kRo5.js} +1 -1
  65. streamlit/static/static/js/{index.6J1N4is3.js → index.D_cvtSlg.js} +1 -1
  66. streamlit/static/static/js/{index.AZ9T4EqJ.js → index.DgqmsDCJ.js} +1 -1
  67. streamlit/static/static/js/{index.CsIENsKH.js → index.DjgdCvlK.js} +1 -1
  68. streamlit/static/static/js/{index.y0h42OXL.js → index.DqhZqWYB.js} +1 -1
  69. streamlit/static/static/js/{index.CBbYMKZp.js → index.Dtbj_oyb.js} +1 -1
  70. streamlit/static/static/js/{index.Cwg8nWw5.js → index.QXukCzoh.js} +1 -1
  71. streamlit/static/static/js/{index.DR6V0uBJ.js → index.XJY9qZ6a.js} +1 -1
  72. streamlit/static/static/js/{index.D83azq2w.js → index.aZRhdEuX.js} +1 -1
  73. streamlit/static/static/js/{index.DpSc4e1j.js → index.fUsWkW8E.js} +1 -1
  74. streamlit/static/static/js/index.h2N-W51I.js +11 -0
  75. streamlit/static/static/js/{index.hnu9U-5g.js → index.iUHLeAvv.js} +1 -1
  76. streamlit/static/static/js/{index.BpCj2-sQ.js → index.kBgXO7Vv.js} +1 -1
  77. streamlit/static/static/js/{index.Q2t_iBn0.js → index.kEL0HsUR.js} +1 -1
  78. streamlit/static/static/js/{input.CAtwSQ27.js → input.BCHJn1Cw.js} +1 -1
  79. streamlit/static/static/js/{main.VeMVx6VI.js → main.23ZP6f1E.js} +1 -1
  80. streamlit/static/static/js/{memory.CxS_lIUn.js → memory.D8f8Q4mO.js} +1 -1
  81. streamlit/static/static/js/{number-overlay-editor.CoqRgZW_.js → number-overlay-editor.ZWvSpjJ5.js} +1 -1
  82. streamlit/static/static/js/{pandasStylerUtils.DGWgd5sM.js → pandasStylerUtils.DlZ2GBs_.js} +1 -1
  83. streamlit/static/static/js/{sandbox.2mSqEau0.js → sandbox.BH6D3KL9.js} +1 -1
  84. streamlit/static/static/js/{sprintfjs.CsoVVZ9k.js → sprintfjs.CtrdaGLQ.js} +1 -1
  85. streamlit/static/static/js/{styled-components.BShfh7J8.js → styled-components.iD1HRMLc.js} +1 -1
  86. streamlit/static/static/js/{throttle.Fq1DQK4p.js → throttle.DR7d9vp_.js} +1 -1
  87. streamlit/static/static/js/{timepicker.DmyY-qtn.js → timepicker.Bd34xjcG.js} +4 -4
  88. streamlit/static/static/js/{toConsumableArray.Dvd9AIqV.js → toConsumableArray.BDTTq1c5.js} +2 -2
  89. streamlit/static/static/js/uniqueId.Bd_Iuzvc.js +1 -0
  90. streamlit/static/static/js/useBasicWidgetState.BXKaD8DQ.js +1 -0
  91. streamlit/static/static/js/{useIntlLocale.kdIj0ego.js → useIntlLocale.CysOvegI.js} +1 -1
  92. streamlit/static/static/js/{useTextInputAutoExpand.DkuG1C1S.js → useTextInputAutoExpand.CVd5Hf2S.js} +1 -1
  93. streamlit/static/static/js/{useUpdateUiValue.-UI_JsjT.js → useUpdateUiValue.CIUgfO8X.js} +1 -1
  94. streamlit/static/static/js/{useWaveformController.C5PTwL6I.js → useWaveformController.CDLqlnLv.js} +1 -1
  95. streamlit/static/static/js/{withCalculatedWidth.BREyS0pJ.js → withCalculatedWidth.Ce1Zblb2.js} +1 -1
  96. streamlit/static/static/js/{withFullScreenWrapper.DYDiEOrW.js → withFullScreenWrapper.DBm7N75M.js} +1 -1
  97. streamlit/web/server/app_static_file_handler.py +9 -0
  98. streamlit/web/server/bidi_component_request_handler.py +4 -4
  99. streamlit/web/server/component_file_utils.py +14 -6
  100. streamlit/web/server/component_request_handler.py +2 -2
  101. streamlit/web/server/starlette/starlette_app.py +7 -1
  102. streamlit/web/server/starlette/starlette_path_security_middleware.py +97 -0
  103. streamlit/web/server/starlette/starlette_routes.py +6 -3
  104. streamlit/web/server/starlette/starlette_static_routes.py +14 -4
  105. {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/METADATA +1 -1
  106. {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/RECORD +109 -107
  107. streamlit/static/static/js/index.C_19KWNs.js +0 -2
  108. streamlit/static/static/js/index.DL_ywOgf.js +0 -11
  109. streamlit/static/static/js/uniqueId.CCajdEK8.js +0 -1
  110. streamlit/static/static/js/useBasicWidgetState.COLQ5AFB.js +0 -1
  111. {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/WHEEL +0 -0
  112. {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/entry_points.txt +0 -0
  113. {streamlit_nightly-1.53.2.dev20260202.dist-info → streamlit_nightly-1.53.2.dev20260203.dist-info}/top_level.txt +0 -0
@@ -108,13 +108,13 @@ def logo(
108
108
 
109
109
  Parameters
110
110
  ----------
111
- image: Anything supported by st.image (except list), emoji, or icon
111
+ image: Anything supported by st.image (except list) or str
112
112
  The image to display in the upper-left corner of your app and its
113
113
  sidebar. If ``icon_image`` is also provided, then Streamlit will only
114
114
  display ``image`` in the sidebar.
115
115
 
116
- In addition to any of the types supported by |st.image|_ (except list),
117
- the following strings are valid:
116
+ ``image`` can be any of the types supported by |st.image|_ except
117
+ a list. Additionally, the following strings are valid:
118
118
 
119
119
  - A single-character emoji. For example, you can set ``image="🏠"``
120
120
  or ``image="🚀"``. Emoji short codes are not supported.
@@ -146,19 +146,15 @@ def logo(
146
146
  The external URL to open when a user clicks on the logo. The URL must
147
147
  start with "\http://" or "\https://". If ``link`` is ``None`` (default),
148
148
  the logo will not include a hyperlink.
149
- icon_image: Anything supported by st.image (except list), emoji, icon, or None
149
+ icon_image: Anything supported by st.image (except list), str, or None
150
150
  An optional, typically smaller image to replace ``image`` in the
151
- upper-left corner when the sidebar is closed. If ``icon_image`` is
151
+ upper-left corner when the sidebar is closed. This can be any of the
152
+ types allowed for the ``image`` parameter. If ``icon_image`` is
152
153
  ``None`` (default), Streamlit will always display ``image`` in the
153
154
  upper-left corner, regardless of whether the sidebar is open or closed.
154
155
  Otherwise, Streamlit will render ``icon_image`` in the upper-left
155
156
  corner of the app when the sidebar is closed.
156
157
 
157
- In addition to any of the types supported by ``st.image`` (except list),
158
- this also accepts single-character emojis (e.g., ``"🏠"``) and Material
159
- icons (e.g., ``":material/home:"``). See the ``image`` parameter for
160
- more details on these formats.
161
-
162
158
  Streamlit scales the image to a max height set by ``size`` and a max
163
159
  width to fit within the sidebar. If the sidebar is closed, the max
164
160
  width is retained from when it was last open.
@@ -22,12 +22,12 @@ outside of a declared package root.
22
22
 
23
23
  from __future__ import annotations
24
24
 
25
- import os
26
25
  from pathlib import Path
27
26
  from typing import Final
28
27
 
29
28
  from streamlit.errors import StreamlitComponentRegistryError
30
29
  from streamlit.logger import get_logger
30
+ from streamlit.path_security import is_unsafe_path_pattern
31
31
 
32
32
  _LOGGER: Final = get_logger(__name__)
33
33
 
@@ -132,7 +132,12 @@ class ComponentPathUtils:
132
132
 
133
133
  @staticmethod
134
134
  def _assert_relative_no_traversal(path: str, *, label: str) -> None:
135
- """Raise if ``path`` is absolute or contains ``..`` segments.
135
+ """Raise if ``path`` is absolute, contains traversal, or has unsafe patterns.
136
+
137
+ This method uses the shared ``is_unsafe_path_pattern`` function to ensure
138
+ consistent security checks across the codebase. The shared function also
139
+ checks for additional patterns like null bytes, forward-slash UNC paths,
140
+ and drive-relative paths (e.g., ``C:foo``).
136
141
 
137
142
  Parameters
138
143
  ----------
@@ -141,34 +146,17 @@ class ComponentPathUtils:
141
146
  label : str
142
147
  Human-readable label used in error messages (e.g., "component paths").
143
148
  """
144
- # Absolute path checks (POSIX, Windows drive-letter, UNC)
145
- is_windows_drive_abs = (
146
- len(path) >= 3
147
- and path[0].isalpha()
148
- and path[1] == ":"
149
- and path[2] in {"/", "\\"}
150
- )
151
- is_unc_abs = path.startswith("\\\\")
152
-
153
- # Consider rooted backslash paths "\\dir" as absolute on Windows-like inputs
154
- is_rooted_backslash = path.startswith("\\") and not is_unc_abs
155
-
156
- if (
157
- os.path.isabs(path)
158
- or is_windows_drive_abs
159
- or is_unc_abs
160
- or is_rooted_backslash
161
- ):
162
- raise StreamlitComponentRegistryError(
163
- f"Absolute paths are not allowed in {label}: {path}"
164
- )
165
-
166
- # Segment-based traversal detection to avoid false positives (e.g. "file..js")
167
- normalized = path.replace("\\", "/")
168
- segments = [seg for seg in normalized.split("/") if seg != ""]
169
- if any(seg == ".." for seg in segments):
149
+ if is_unsafe_path_pattern(path):
150
+ # Determine appropriate error message based on pattern.
151
+ # Use segment-based check to avoid false positives like "file..js"
152
+ normalized = path.replace("\\", "/")
153
+ segments = [seg for seg in normalized.split("/") if seg]
154
+ if ".." in segments:
155
+ raise StreamlitComponentRegistryError(
156
+ f"Path traversal attempts are not allowed in {label}: {path}"
157
+ )
170
158
  raise StreamlitComponentRegistryError(
171
- f"Path traversal attempts are not allowed in {label}: {path}"
159
+ f"Unsafe paths are not allowed in {label}: {path}"
172
160
  )
173
161
 
174
162
  @staticmethod
streamlit/config.py CHANGED
@@ -621,8 +621,10 @@ _create_option(
621
621
  "client.showErrorLinks",
622
622
  description="""
623
623
  Controls whether to show external help links (Google, ChatGPT) in
624
- error displays. Can be "auto" (shows on localhost only), true (always
625
- show), or false (never show).
624
+ error displays. The following values are valid:
625
+ - "auto" (default): Links are shown only on localhost.
626
+ - True: Links are shown on all domains.
627
+ - False: Links are never shown.
626
628
  """,
627
629
  default_val="auto",
628
630
  type_=str,
@@ -0,0 +1,98 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Shared path security utilities for preventing path traversal and SSRF attacks.
16
+
17
+ This module provides a centralized implementation for path validation that is
18
+ used by multiple parts of the codebase. Having a single implementation ensures
19
+ consistent security checks and avoids divergent behavior between components.
20
+
21
+ Security Context
22
+ ----------------
23
+ These checks are designed to run BEFORE any filesystem operations (like
24
+ ``os.path.realpath()``) to prevent Windows from triggering SMB connections
25
+ to attacker-controlled servers when resolving UNC paths. This prevents
26
+ SSRF attacks and NTLM hash disclosure.
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import os
32
+ import string
33
+
34
+
35
+ def is_unsafe_path_pattern(path: str) -> bool:
36
+ r"""Return True if path contains UNC, absolute, drive, or traversal patterns.
37
+
38
+ This function checks for dangerous path patterns that could lead to:
39
+ - SSRF attacks via Windows UNC path resolution
40
+ - NTLM hash disclosure via SMB connections
41
+ - Path traversal outside intended directories
42
+ - Path truncation via null bytes
43
+
44
+ IMPORTANT: This check must run BEFORE any ``os.path.realpath()`` calls
45
+ to prevent Windows from triggering SMB connections to attacker-controlled
46
+ servers.
47
+
48
+ Parameters
49
+ ----------
50
+ path : str
51
+ The path string to validate.
52
+
53
+ Returns
54
+ -------
55
+ bool
56
+ True if the path contains unsafe patterns, False if it appears safe
57
+ for further processing.
58
+
59
+ Examples
60
+ --------
61
+ >>> is_unsafe_path_pattern("subdir/file.js")
62
+ False
63
+ >>> is_unsafe_path_pattern("\\\\server\\share")
64
+ True
65
+ >>> is_unsafe_path_pattern("../../../etc/passwd")
66
+ True
67
+ >>> is_unsafe_path_pattern("C:\\Windows\\system32")
68
+ True
69
+ """
70
+ # Null bytes can be used for path truncation attacks
71
+ if "\x00" in path:
72
+ return True
73
+
74
+ # UNC paths (Windows network shares, including \\?\ and \\.\ prefixes)
75
+ if path.startswith(("\\\\", "//")):
76
+ return True
77
+
78
+ # Windows drive paths (e.g. C:\, D:foo) - on Windows, os.path.realpath() on a
79
+ # drive path can trigger SMB connections if the drive is mapped to a network share.
80
+ # This enables SSRF attacks and NTLM hash disclosure. We reject all drive-qualified
81
+ # paths including drive-relative paths like "C:foo" which resolve against the current
82
+ # directory of that drive. Checked on all platforms for defense-in-depth and
83
+ # testability (CI runs on Linux).
84
+ if len(path) >= 2 and path[0] in string.ascii_letters and path[1] == ":":
85
+ return True
86
+
87
+ # Rooted backslash or forward slash (absolute paths)
88
+ if path.startswith(("\\", "/")):
89
+ return True
90
+
91
+ # Also check os.path.isabs for platform-specific absolute path detection
92
+ if os.path.isabs(path):
93
+ return True
94
+
95
+ # Path traversal - check segments after normalizing separators
96
+ normalized = path.replace("\\", "/")
97
+ segments = [seg for seg in normalized.split("/") if seg]
98
+ return ".." in segments
@@ -1009,13 +1009,21 @@ def _get_toolbar_mode() -> Config.ToolbarMode.ValueType:
1009
1009
 
1010
1010
  def _get_show_error_links() -> Config.ShowErrorLinks.ValueType:
1011
1011
  config_key = "client.showErrorLinks"
1012
+ config_value = config.get_option(config_key)
1013
+
1014
+ # Handle boolean values (from st.set_option or programmatic setting)
1015
+ if config_value is True:
1016
+ return Config.ShowErrorLinks.SHOW_ERROR_LINKS_TRUE
1017
+ if config_value is False:
1018
+ return Config.ShowErrorLinks.SHOW_ERROR_LINKS_FALSE
1019
+
1020
+ # Handle string values (from config.toml or command-line)
1012
1021
  allowed_values = ["auto", "true", "false"]
1013
1022
  value_to_enum = {
1014
1023
  "auto": Config.ShowErrorLinks.SHOW_ERROR_LINKS_AUTO,
1015
1024
  "true": Config.ShowErrorLinks.SHOW_ERROR_LINKS_TRUE,
1016
1025
  "false": Config.ShowErrorLinks.SHOW_ERROR_LINKS_FALSE,
1017
1026
  }
1018
- config_value = config.get_option(config_key)
1019
1027
  if config_value not in allowed_values:
1020
1028
  raise ValueError(
1021
1029
  f"Config {config_key!r} expects to have one of "
@@ -37,7 +37,7 @@
37
37
  <script>
38
38
  window.prerenderReady = false
39
39
  </script>
40
- <script type="module" crossorigin src="./static/js/index.y5HxPwg9.js"></script>
40
+ <script type="module" crossorigin src="./static/js/index.BHyzKS4e.js"></script>
41
41
  <link rel="stylesheet" crossorigin href="./static/css/index.C8MrxwGF.css">
42
42
  </head>
43
43
  <body>