Commit 6a5be34
fix: add module blocklist for YAML agent config code references
Merge #5821
Fixes #5822
## Summary
This PR adds a module blocklist to prevent importing dangerous standard library modules via YAML agent configurations. It is a defense-in-depth hardening that complements the existing **args** key block from the CVE-2026-4810 fix.
## Problem
The CVE-2026-4810 fix blocked the `args` key in YAML configs to prevent passing arguments to constructors. However, the following functions still call `importlib.import_module()` with **no restriction** on which modules can be imported:
- `resolve_code_reference()` — used for callbacks, schemas, model_code
- `resolve_fully_qualified_name()` — used for agent class resolution
- `_resolve_tools()` — used for user-defined tool resolution
- `_resolve_agent_code_reference()` — used for agent code references
### Example malicious YAML (currently accepted):
```yaml
name: evil_agent
model: gemini-2.0-flash
instruction: harmless
before_agent_callbacks:
- name: os.system
```
## Solution
### 1. Module blocklist with 36 dangerous stdlib modules
Added `_BLOCKED_MODULES` frozenset organized by category:
| Category | Modules |
|---|---|
| Process / OS execution | `os`, `subprocess`, `sys`, `builtins`, `importlib`, `shutil`, `signal`, `multiprocessing`, `threading` |
| Dynamic code evaluation | `code`, `codeop`, `compileall`, `runpy` |
| Native / unsafe extensions | `ctypes` |
| Network access | `socket`, `http`, `urllib`, `ftplib`, `smtplib`, `poplib`, `imaplib`, `nntplib`, `telnetlib`, `xmlrpc`, `asyncio` |
| Filesystem / serialisation | `tempfile`, `pathlib`, `shelve`, `pickle`, `marshal` |
| Interactive / side-effect | `webbrowser`, `antigravity`, `pty`, `commands`, `pdb`, `profile` |
### 2. Validation at ALL import sites
Added `_validate_module_reference()` that checks the top-level module against the blocklist **before** `importlib.import_module()` is called.
| Import Site | File | Gated? |
|---|---|---|
| `resolve_fully_qualified_name()` | `config_agent_utils.py` | ✅ |
| `_resolve_agent_code_reference()` | `config_agent_utils.py` | ✅ |
| `resolve_code_reference()` | `config_agent_utils.py` | ✅ |
| `_resolve_tools()` user-defined | `llm_agent.py` | ✅ **New** |
| `_resolve_tools()` built-in | `llm_agent.py` | N/A (hardcoded `google.adk.tools`) |
### 3. Enabled by default
`_ENFORCE_DENYLIST = True` — the blocklist is **active by default**, with `_set_enforce_denylist(False)` available as an escape hatch for operators who need custom modules.
## Files Changed
- **`src/google/adk/agents/config_agent_utils.py`** (+83) — `_BLOCKED_MODULES`, `_validate_module_reference()`, validation calls at 3 import sites, `_ENFORCE_DENYLIST = True`
- **`src/google/adk/agents/llm_agent.py`** (+3) — Validation gate in `_resolve_tools()` for user-defined tools
- **`tests/unittests/agents/test_agent_config.py`** (+115) — 8 new security test functions
## Testing
### All 52 tests pass (0 failures):
```
====================== 52 passed, 311 warnings in 3.89s =======================
```
### New security test coverage:
| Test | What it verifies |
|---|---|
| `test_resolve_code_reference_blocks_os_when_enforced` | `os.system` blocked via `resolve_code_reference` |
| `test_resolve_fully_qualified_name_blocks_subprocess_when_enforced` | `subprocess.Popen` blocked (verifies wrapped cause) |
| `test_allowed_module_passes_when_enforced` | `google.adk.*` modules pass through (no false positives) |
| `test_resolve_agent_code_reference_blocks_when_enforced` | 3 modules blocked via `_resolve_agent_code_reference` |
| `test_resolve_tools_blocks_dangerous_modules` | 4 modules blocked via `_resolve_tools` |
| `test_resolve_tools_allows_builtin_adk_tools` | `google_search` (built-in, no dot) passes through |
| `test_newly_blocked_network_modules_are_rejected` | 8 new network modules verified blocked |
| `test_denylist_can_be_disabled` | `_set_enforce_denylist(False)` escape hatch works |
All existing tests remain unchanged and passing. Zero risk of regression.
Co-authored-by: George Weale <gweale@google.com>
COPYBARA_INTEGRATE_REVIEW=#5821 from Ashutosh0x:security/restrict-module-imports-config-agent df75a3b
PiperOrigin-RevId: 9376813891 parent a912306 commit 6a5be34
3 files changed
Lines changed: 203 additions & 0 deletions
File tree
- src/google/adk/agents
- tests/unittests/agents
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 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 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
108 | 188 | | |
109 | 189 | | |
110 | 190 | | |
111 | 191 | | |
| 192 | + | |
112 | 193 | | |
113 | 194 | | |
114 | 195 | | |
| |||
170 | 251 | | |
171 | 252 | | |
172 | 253 | | |
| 254 | + | |
173 | 255 | | |
174 | 256 | | |
175 | 257 | | |
| |||
199 | 281 | | |
200 | 282 | | |
201 | 283 | | |
| 284 | + | |
202 | 285 | | |
203 | 286 | | |
204 | 287 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1102 | 1102 | | |
1103 | 1103 | | |
1104 | 1104 | | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
1105 | 1108 | | |
1106 | 1109 | | |
1107 | 1110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
486 | 486 | | |
487 | 487 | | |
488 | 488 | | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
0 commit comments