Commit e100c5a
authored
fix(files): bound YAML expansion and buffered reads on the file-serve path (#7319)
* fix(files): bound YAML expansion and buffered reads on the file-serve path
Two unbounded resource paths reachable from the anonymous public share routes.
YAML alias expansion: the page compiler parsed sim: fence payloads with no
ceiling on what the parsed value expands to. Aliases are shared references, so
`columns: &c [...]` plus a row list of aliases to it renders N^2 cells from ~13N
source bytes — 25 KB of source cost 3.6s of CPU and 38 MB of HTML per request.
The expansion guard already in the file parser is now a shared primitive taking
caller-supplied limits, and the compiler charges every fence and the frontmatter
to one per-compile budget so splitting across blocks buys no extra rendering.
Buffered reads: the Files-module serve path already capped reads at
MAX_BUFFERED_TRANSFER_BYTES via fetchWorkspaceFileBuffer, but five sibling paths
serving the same objects did not, including both unauthenticated share routes.
A workspace object is admitted at 5 GB, so a share link was the one way to make
an anonymous request hold gigabytes resident in the shared process.
* fix(files): check transformed bytes against the ceiling and bound the guard's own walk
Review round 1.
Bounding the source read did not bound the response: every branch that replaces
the source — a compiled document artifact fetched separately, a page with its
images inlined, a transcoded image derivative — could turn a source under the
ceiling into a response over it, on the anonymous share route included. The check
now sits where those branches converge rather than on the page branch alone.
The local read enforced its ceiling on a size measured before the read, so it
described the file only as of the stat. It now reads through the same bounded
stream reader the S3/Blob/GCS downloads use.
The expansion guard held one stack frame per pending node, so proving a wide
document too large allocated in proportion to the width it was rejecting. It now
holds one frame per level of nesting and consumes each container through a lazy
generator, bounding its own working set by depth. A double serializes to up to 24
characters, so numbers are charged their serialized length rather than the flat
16-byte allowance they could outgrow.
* fix(files): route the raw serve branch through the same response ceiling
The `raw=1` branch returned before the check, so the ceiling held for the
branches that transform bytes but not for the one that returns them unchanged.
Those bytes are already bounded by the read that produced them, so this changes
no behavior — it makes the guarantee hold for everything the resolver returns
rather than for every branch someone remembered to cover.
* fix(files): bound the artifact and local reads at the read, not at the response
Review round 2.
The response-level ceiling rejected an oversized compiled artifact only after the
whole thing was resident, which is the allocation it exists to prevent. The
artifact read is bounded at its own funnel instead, and a size breach is rethrown
rather than folded into the "not built yet" null — that answer tells callers to
retry, which an oversized artifact would never stop doing. The cached image
derivative is bounded the same way, but keeps swallowing the breach, because a
miss there re-transcodes from an already-bounded source.
The local storage branch enforced its ceiling with stat-then-read, so it described
the file only as of the stat. It now reads through the same bounded-stream reader
the cloud branches use — this is the anonymous share path on a self-hosted
deployment, and the route helper was already fixed while the storage service it
sits next to was not.
The default js-yaml schema turns a timestamp into a Date, which serializes to a
26-character quoted string; charging it the 16-byte flat allowance let a document
of them exceed the byte cap.
* fix(files): bound the shared artifact reads at the widest consumer ceiling
Review round 3.
The previous round bounded the compiled-artifact and cached-derivative reads at
the rendered-document ceiling, which is half what the serving routes will return.
That made the bound a policy rather than a backstop: an artifact between the two
figures was refused even though the route accepts a response that size, and a
derivative in that band read as a cache miss on every preview and re-transcoded
the original each time.
Both funnels now bound at the widest ceiling any of their consumers allows. A
consumer that permits less still enforces its own limit on what it got back — the
workspace download path continues to hold artifacts to the rendered-document
ceiling.1 parent 616d5e9 commit e100c5a
19 files changed
Lines changed: 1107 additions & 194 deletions
File tree
- apps/sim
- app/api/files
- public/[token]
- content
- inline
- serve/[...path]
- lib
- copilot/tools/server/files
- file-parsers
- uploads
- contexts/copilot
- core
- server
- workspace-files
Lines changed: 37 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
| |||
78 | 80 | | |
79 | 81 | | |
80 | 82 | | |
81 | | - | |
| 83 | + | |
82 | 84 | | |
83 | 85 | | |
84 | 86 | | |
| 87 | + | |
| 88 | + | |
85 | 89 | | |
86 | 90 | | |
87 | 91 | | |
| 92 | + | |
88 | 93 | | |
89 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
90 | 126 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| 16 | + | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
| |||
69 | 71 | | |
70 | 72 | | |
71 | 73 | | |
72 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
73 | 82 | | |
74 | 83 | | |
75 | 84 | | |
| |||
116 | 125 | | |
117 | 126 | | |
118 | 127 | | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
119 | 134 | | |
120 | 135 | | |
121 | 136 | | |
| |||
Lines changed: 35 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
| |||
122 | 124 | | |
123 | 125 | | |
124 | 126 | | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
125 | 160 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
23 | 35 | | |
24 | 36 | | |
25 | 37 | | |
| |||
72 | 84 | | |
73 | 85 | | |
74 | 86 | | |
75 | | - | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
76 | 102 | | |
77 | 103 | | |
78 | 104 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
28 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
29 | 34 | | |
30 | 35 | | |
31 | 36 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
32 | 34 | | |
| |||
52 | 54 | | |
53 | 55 | | |
54 | 56 | | |
| 57 | + | |
55 | 58 | | |
56 | 59 | | |
57 | 60 | | |
| |||
119 | 122 | | |
120 | 123 | | |
121 | 124 | | |
| 125 | + | |
122 | 126 | | |
123 | 127 | | |
124 | 128 | | |
| |||
162 | 166 | | |
163 | 167 | | |
164 | 168 | | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
165 | 172 | | |
166 | 173 | | |
167 | 174 | | |
| |||
181 | 188 | | |
182 | 189 | | |
183 | 190 | | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
184 | 267 | | |
185 | 268 | | |
186 | 269 | | |
| |||
232 | 315 | | |
233 | 316 | | |
234 | 317 | | |
| 318 | + | |
235 | 319 | | |
236 | 320 | | |
237 | 321 | | |
| |||
318 | 402 | | |
319 | 403 | | |
320 | 404 | | |
| 405 | + | |
321 | 406 | | |
322 | 407 | | |
323 | 408 | | |
| |||
0 commit comments