mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-25 17:18:11 +00:00
fix(kanban): harden delegated-child mutation boundary
This commit is contained in:
parent
47bbc12e18
commit
a7dcf9787b
11 changed files with 555 additions and 7 deletions
|
|
@ -135,7 +135,10 @@ def _truncate_stdout_text(stdout_text: str) -> Tuple[str, Dict[str, Any]]:
|
|||
# Environment variable scrubbing rules (shared between the local + remote
|
||||
# backends). Secret-substring block is applied first; anything left must
|
||||
# match a safe prefix, the operational HERMES_ allowlist, or (on Windows) an
|
||||
# OS-essential name.
|
||||
# OS-essential name. Delegate-task child context is also an exact-name
|
||||
# operational marker: without it, a sandbox script that spawns/imports Hermes
|
||||
# code can lose the DB-layer Kanban mutation guard while still inheriting
|
||||
# HERMES_HOME.
|
||||
#
|
||||
# NB: the broad "HERMES_" prefix was deliberately removed (#27303) — it leaked
|
||||
# HERMES_*-named config that lacks a secret substring (e.g. HERMES_BASE_URL,
|
||||
|
|
@ -166,6 +169,7 @@ _HERMES_CHILD_ALLOWED = frozenset({
|
|||
"HERMES_PROFILE",
|
||||
"HERMES_CONFIG",
|
||||
"HERMES_ENV",
|
||||
"HERMES_DELEGATED_CHILD_CONTEXT",
|
||||
})
|
||||
|
||||
# Windows-only: a handful of variables are required by the OS/CRT itself.
|
||||
|
|
@ -261,6 +265,22 @@ def _scrub_child_env(source_env, is_passthrough=None, is_windows=None):
|
|||
len(_dropped_hermes),
|
||||
", ".join(sorted(_dropped_hermes)),
|
||||
)
|
||||
|
||||
# delegate_task children are marked with a ContextVar, not os.environ, while
|
||||
# the execute_code sandbox crosses a process boundary. Bridge that context
|
||||
# into the child env and strip dispatcher-owned Kanban variables after the
|
||||
# normal secret/passthrough scrub so an explicit passthrough cannot re-grant
|
||||
# a delegated child the parent's board mutation capability.
|
||||
try:
|
||||
from agent.delegation_context import (
|
||||
is_delegated_child_process_context,
|
||||
scrub_kanban_env,
|
||||
)
|
||||
|
||||
if is_delegated_child_process_context():
|
||||
scrubbed = scrub_kanban_env(scrubbed)
|
||||
except Exception:
|
||||
pass
|
||||
return scrubbed
|
||||
|
||||
|
||||
|
|
@ -1736,6 +1756,8 @@ def _is_usable_python(python_path: str) -> bool:
|
|||
Cached so we don't fork a subprocess on every execute_code call.
|
||||
"""
|
||||
try:
|
||||
from agent.delegation_context import delegated_child_subprocess_env
|
||||
|
||||
result = subprocess.run(
|
||||
[python_path, "-c",
|
||||
"import sys; sys.exit(0 if sys.version_info >= (3, 8) else 1)"],
|
||||
|
|
@ -1743,6 +1765,7 @@ def _is_usable_python(python_path: str) -> bool:
|
|||
capture_output=True,
|
||||
creationflags=subprocess.CREATE_NO_WINDOW if _IS_WINDOWS else 0,
|
||||
stdin=subprocess.DEVNULL,
|
||||
env=delegated_child_subprocess_env(),
|
||||
)
|
||||
return result.returncode == 0
|
||||
except (OSError, subprocess.TimeoutExpired, subprocess.SubprocessError):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue