Commit 605611b
authored
Fix GHSA-x6pr-233j-x5cw: warn before executing an FL-provisioned bundle config (#9078)
## Summary
Fixes GHSA-x6pr-233j-x5cw:
https://github.com/Project-MONAI/MONAI/security/advisories/GHSA-x6pr-233j-x5cw
Also closes GHSA-wvpx-5qmp-46g3:
https://github.com/Project-MONAI/MONAI/security/advisories/GHSA-wvpx-5qmp-46g3
`MonaiAlgo`/`MonaiAlgoStats` run a bundle whose entire app directory is
provisioned by the FL system. `initialize(extra)` resolves `bundle_root
= os.path.join(extra[APP_ROOT], self.bundle_root)` — `APP_ROOT` is
supplied by the aggregation server — then builds a `ConfigWorkflow` over
`<app_root>/configs/train.json` and runs its `initialize` expressions.
Because FL tasks are dispatched per round and executed with no human in
the loop, a malicious or compromised server gets silent code execution
on every participating client.
The `UserWarning` added in #9057 for GHSA-873f-pvrv-4x83 lives in
`create_workflow()`. This path never calls it — `MonaiAlgo` constructs
`ConfigWorkflow` directly — so nothing warned here at all.
### Design
Executing the config stays unblocked, for the same reason the
`trust_remote_code` flag was dropped from #9057: MONAI has no mechanism
to establish whether a bundle is trustworthy, so a flag mostly teaches
operators to set it once and forget about it. Both `initialize()`
methods now warn, naming the trust boundary (`extra[APP_ROOT]`) and the
absence of per-round human interaction.
The one behaviour change is narrowly scoped, and it targets the sink
with no functional role in FL. `ConfigWorkflow` defaults `logging_file`
to the bundle's own `configs/logging.conf` and passes it to
`logging.config.fileConfig`, which `eval()`s the INI's `class=`/`args=`
fields. That is code execution at construction time, before any config
is parsed, and it hides in a plain INI rather than the MONAI `$`-DSL —
easy to miss when reviewing a bundle. The FL client now treats
`extra[ExtraItems.LOGGING_FILE]` as `False` both when the key is absent
and when it is explicitly `None`, so a server-written `logging.conf` is
never applied. `None` needs the same treatment as absent because it was
the pre-PR default and `ConfigWorkflow` reads it as "fall back to the
bundle's own `configs/logging.conf`" — exactly the file this change
exists to keep away from `fileConfig`. An FL system that wants bundle
logging passes an explicit path, through the key that already exists for
it.
The `fileConfig` warning sits inside the branch that actually calls it,
not at the top of `__init__`. That keeps it truthful (nothing runs when
the file is absent or logging is disabled, both common) and avoids
double-warning callers who already got the `create_workflow()` warning,
which is about `_target_`/`$` rather than the INI.
### Changes
- `monai/fl/client/monai_algo.py`: warning in both `initialize()`
methods; `ExtraItems.LOGGING_FILE` treated as `False` when absent or
explicitly `None`; security notes on both class docstrings; both
`initialize()` docstrings rewritten for the new default (this also fixes
a `diable` typo).
- `monai/bundle/workflows.py`: `_warn_logging_file_execution()` called
immediately before each of the two `fileConfig` invocations;
`logging_file` docstring entries updated on `BundleWorkflow`,
`PythonicWorkflow` and `ConfigWorkflow`.
- `tests/fl/monai_algo/test_fl_monai_algo.py`:
`TestFLMonaiAlgoWarnsOnProvisionedConfig` — stages an app whose
`train.json` and `logging.conf` each drop a distinct marker, for both
`MonaiAlgo` and `MonaiAlgoStats`. Asserts the config still executes with
the advisory warning; that the server's `logging.conf` no longer does,
whether the key is absent or explicitly `None`; that an explicit path
opts back in; and that no `fileConfig` warning fires when nothing is
executed.
- `tests/bundle/test_bundle_workflow.py`:
`TestConfigWorkflowWarnsOnLoggingConf` — a bundle's default
`configs/logging.conf` warns and still applies; `logging_file=False`
neither warns nor applies it.
Both new test classes snapshot and restore the root logger, closing any
handler `fileConfig` installs. The suite runs in one process, so without
that they would leak a root handler and formatter into every test that
follows.
## Test plan
- [x] `python -m unittest tests.fl.monai_algo.test_fl_monai_algo` — 17
passed
- [x] `python -m unittest tests.fl.test_fl_monai_algo_stats` — 3 passed
- [x] `python -m unittest
tests.bundle.test_bundle_workflow.TestConfigWorkflowWarnsOnLoggingConf`
— 2 passed
- [x] `python -m unittest
tests.bundle.test_bundle_download.TestLoadWarnsOnConfigExecution` — 6
passed, no double-warn regression on the #9057 fix
- [x] Each new assertion checked against the unpatched code first — the
advisory's payload writes its marker via the bundle config and via
`logging.conf` before the change, and only via the bundle config after
it
- [x] Root logger verified identical before and after both new test
classes run
- [x] `black`, `isort`, `ruff` clean on the changed files
### Types of changes
- [ ] Non-breaking change (fix or new feature that would not break
existing functionality).
- [x] Breaking change (fix or new feature that would cause existing
functionality to change).
- [x] New tests added to cover the changes.
- [x] In-line docstrings updated.
The breaking-change box is for the `LOGGING_FILE` default only: an FL
deployment relying on the bundle shipping its own `logging.conf` now has
to pass the path explicitly. Everything else is additive.
---------
Signed-off-by: R. Garcia-Dias <rafaelagd@gmail.com>1 parent 7b9cb34 commit 605611b
4 files changed
Lines changed: 321 additions & 5 deletions
File tree
- monai
- bundle
- fl/client
- tests
- bundle
- fl/monai_algo
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
37 | 55 | | |
38 | 56 | | |
39 | 57 | | |
| |||
55 | 73 | | |
56 | 74 | | |
57 | 75 | | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
58 | 80 | | |
59 | 81 | | |
60 | 82 | | |
| |||
72 | 94 | | |
73 | 95 | | |
74 | 96 | | |
| 97 | + | |
75 | 98 | | |
76 | 99 | | |
77 | 100 | | |
| |||
273 | 296 | | |
274 | 297 | | |
275 | 298 | | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
276 | 303 | | |
277 | 304 | | |
278 | 305 | | |
| |||
375 | 402 | | |
376 | 403 | | |
377 | 404 | | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
378 | 409 | | |
379 | 410 | | |
380 | 411 | | |
| |||
444 | 475 | | |
445 | 476 | | |
446 | 477 | | |
| 478 | + | |
447 | 479 | | |
448 | 480 | | |
449 | 481 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
| |||
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
37 | 58 | | |
38 | 59 | | |
39 | 60 | | |
| |||
86 | 107 | | |
87 | 108 | | |
88 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
89 | 119 | | |
90 | 120 | | |
91 | 121 | | |
| |||
135 | 165 | | |
136 | 166 | | |
137 | 167 | | |
138 | | - | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
139 | 174 | | |
140 | 175 | | |
141 | 176 | | |
142 | 177 | | |
143 | 178 | | |
144 | | - | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
145 | 185 | | |
146 | 186 | | |
147 | 187 | | |
148 | 188 | | |
149 | 189 | | |
| 190 | + | |
150 | 191 | | |
151 | 192 | | |
152 | 193 | | |
| |||
313 | 354 | | |
314 | 355 | | |
315 | 356 | | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
316 | 366 | | |
317 | 367 | | |
318 | 368 | | |
| |||
416 | 466 | | |
417 | 467 | | |
418 | 468 | | |
419 | | - | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
420 | 475 | | |
421 | 476 | | |
422 | 477 | | |
423 | 478 | | |
424 | 479 | | |
425 | 480 | | |
426 | | - | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
427 | 487 | | |
428 | 488 | | |
429 | 489 | | |
430 | 490 | | |
431 | 491 | | |
| 492 | + | |
432 | 493 | | |
433 | 494 | | |
434 | 495 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
14 | 16 | | |
15 | 17 | | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| 21 | + | |
19 | 22 | | |
20 | 23 | | |
21 | 24 | | |
| |||
268 | 271 | | |
269 | 272 | | |
270 | 273 | | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
271 | 353 | | |
272 | 354 | | |
0 commit comments