§
    øžyj2$  ã                  óÖ   — U d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	  ej
        e¦  «        Z ed¦  «        Zded	<   d d„Zdaded<   d!d„Zd"d„Zd#d„Zd$d„Zd#d„Z	 d%d&d„Zd'd„ZdS )(uú  Environment variable passthrough registry.

Skills that declare ``required_environment_variables`` in their frontmatter
need those vars available in sandboxed execution environments (execute_code,
terminal).  By default both sandboxes strip secrets from the child process
environment for security.  This module provides a session-scoped allowlist
so skill-declared vars (and user-configured overrides) pass through.

Two sources feed the allowlist:

1. **Skill declarations** â€” when a skill is loaded via ``skill_view``, its
   ``required_environment_variables`` are registered here automatically.
2. **User config** â€” ``terminal.env_passthrough`` in config.yaml lets users
   explicitly allowlist vars for non-skill use cases.

Both ``code_execution_tool.py`` and ``tools/environments/local.py`` consult
:func:`is_env_passthrough` before stripping a variable.
When profile multiplexing is active, their forwarded values are resolved
through the current profile's secret scope rather than the process environment.
é    )ÚannotationsN)Ú
ContextVar)ÚIterable)Úcfg_getÚ_allowed_env_varszContextVar[set[str]]Ú_allowed_env_vars_varÚreturnúset[str]c                 óª   — 	 t                                ¦   «         S # t          $ r- t          ¦   «         } t                                | ¦  «         | cY S w xY w)zGGet or create the allowed env vars set for the current context/session.)r   ÚgetÚLookupErrorÚset)Úvals    ú;/home/ragecks/.hermes/hermes-agent/tools/env_passthrough.pyÚ_get_allowedr   $   sZ   € ðÝ$×(Ò(Ñ*Ô*Ð*øÝð ð ð Ý™œˆÝ×!Ò! #Ñ&Ô&Ð&Øˆ
ˆ
ˆ
ðøøøs   ‚ ›4AÁAzfrozenset[str] | NoneÚ_config_passthroughÚnameÚstrÚboolc                ó    — 	 ddl m}m} n4# t          $ r'}t                               d| |¦  «         Y d}~dS d}~ww xY w || ¦  «        rdS | |v S )uÙ  True if ``name`` is a Hermes-managed provider credential (API key,
    token, or similar) per ``_HERMES_PROVIDER_ENV_BLOCKLIST``.

    Skill-declared ``required_environment_variables`` frontmatter must
    not be able to override this list â€” that was the bypass in
    GHSA-rhgp-j443-p4rf where a malicious skill registered
    ``ANTHROPIC_TOKEN`` / ``OPENAI_API_KEY`` as passthrough and received
    the credential in the ``execute_code`` child process, defeating the
    sandbox's scrubbing guarantee.

    Non-Hermes API keys (TENOR_API_KEY, NOTION_TOKEN, etc.) are NOT
    in the blocklist and remain legitimately registerable â€” skills that
    wrap third-party APIs still work.

    Fail closed: if the authoritative blocklist cannot be imported (partial
    install, import-time error, etc.) we treat the name as a protected
    provider credential and refuse passthrough, rather than fall open and
    let a skill tunnel a Hermes credential into the execute_code child.
    r   )Ú_HERMES_PROVIDER_ENV_BLOCKLISTÚ_is_hermes_internal_secretz}env passthrough: provider credential blocklist import failed; failing closed and refusing passthrough registration for %r: %sNT)Útools.environments.localr   r   Ú	ExceptionÚloggerÚwarning)r   r   r   Úes       r   Ú_is_hermes_provider_credentialr   2   s¬   € ð(ð	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øõ ð ð ð Ý�ŠðNàØñ		
ô 	
ð 	
ð ˆtˆtˆtˆtˆtøøøøðøøøð "Ð! $Ñ'Ô'ð ØˆtØÐ1Ð1Ð1s   ‚ ‹
<•7·<Ú	var_namesúIterable[str]ÚNonec                ó  — | D ]€}|                      ¦   «         }|sŒt          |¦  «        rt                               d|¦  «         ŒDt	          ¦   «                              |¦  «         t                               d|¦  «         Œ�dS )uä  Register environment variable names as allowed in sandboxed environments.

    Typically called when a skill declares ``required_environment_variables``.

    Variables that are Hermes-managed provider credentials (from
    ``_HERMES_PROVIDER_ENV_BLOCKLIST``) are rejected here to preserve
    the ``execute_code`` sandbox's credential-scrubbing guarantee per
    GHSA-rhgp-j443-p4rf. A skill that needs to talk to a Hermes-managed
    provider should do so via the agent's main-process tools (web_search,
    web_extract, etc.) where the credential remains safely in the main
    process.

    Non-Hermes third-party API keys (TENOR_API_KEY, NOTION_TOKEN, etc.)
    pass through normally â€” they were never in the sandbox scrub list.
    zÓenv passthrough: refusing to register Hermes provider credential %r (blocked by _HERMES_PROVIDER_ENV_BLOCKLIST). Skills must not override the execute_code sandbox's credential scrubbing; see GHSA-rhgp-j443-p4rf.zenv passthrough: registered %sN)Ústripr   r   r   r   ÚaddÚdebug)r   r   s     r   Úregister_env_passthroughr&   ]   s›   € ð  ð =ð =ˆØ�zŠz‰|Œ|ˆØð 	ØÝ)¨$Ñ/Ô/ð 	Ý�NŠNðAð ñô ð ð Ý‰Œ×Ò˜4Ñ Ô Ð Ý�ŠÐ5°tÑ<Ô<Ð<Ð<ð=ð =ó    úfrozenset[str]c                 ó@  — t           �t           S t          ¦   «         } 	 ddlm}  |¦   «         }t	          |dd¦  «        }t          |t          ¦  «        rƒ|D ]€}t          |t          ¦  «        r|                     ¦   «         sŒ,|                     ¦   «         }t          |¦  «        rt                               d|¦  «         Œk|                      |¦  «         Œ�n2# t          $ r%}t                               d|¦  «         Y d}~nd}~ww xY wt          | ¦  «        a t           S )z9Load ``tools.env_passthrough`` from config.yaml (cached).Nr   )Úread_raw_configÚterminalÚenv_passthroughzôenv passthrough: refusing to register Hermes provider credential %r from config.yaml (blocked by _HERMES_PROVIDER_ENV_BLOCKLIST). Operator configuration must not override the execute_code sandbox's credential scrubbing; see GHSA-rhgp-j443-p4rf.z4Could not read tools.env_passthrough from config: %s)r   r   Úhermes_cli.configr*   r   Ú
isinstanceÚlistr   r#   r   r   r   r$   r   r%   Ú	frozenset)Úresultr*   ÚcfgÚpassthroughÚitemr   r   s          r   Ú_load_config_passthroughr5   ~   sL  € õ Ð&Ý"Ð"å‘u”u€FðPØ5Ð5Ð5Ð5Ð5Ð5ØˆoÑÔˆÝ˜c :Ð/@ÑAÔAˆÝ�k¥4Ñ(Ô(ð 	!Ø#ð !ð !�Ý! $­Ñ,Ô,ð °D·J²J±L´Lð ØØ—z’z‘|”|�õ 2°$Ñ7Ô7ð 
Ý—N’Nð/ð ñô ð ð Ø—
’
˜4Ñ Ô Ð Ð øøÝð Pð Pð PÝ�ŠÐKÈQÑOÔOÐOÐOÐOÐOÐOÐOøøøøðPøøøõ $ FÑ+Ô+ÐÝÐs   žB9C Ã
DÃ"DÄDÚvar_namec                óF   — | t          ¦   «         v rdS | t          ¦   «         v S )zÄCheck whether *var_name* is allowed to pass through to sandboxes.

    Returns ``True`` if the variable was registered by a skill or listed in
    the user's ``tools.env_passthrough`` config.
    T)r   r5   )r6   s    r   Úis_env_passthroughr8   ¦   s*   € ð •<‘>”>Ð!Ð!ØˆtØÕ/Ñ1Ô1Ð1Ð1r'   c                 óV   — t          t          ¦   «         ¦  «        t          ¦   «         z  S )zGReturn the union of skill-registered and config-based passthrough vars.)r0   r   r5   © r'   r   Úget_all_passthroughr;   ±   s    € å•\‘^”^Ñ$Ô$Õ'?Ñ'AÔ'AÑAÐAr'   Úfallbackú
str | Nonec                ó¢   — ddl m}m}m}m}  || ¦  «        r|�|S  |¦   «         } |¦   «         }|€|r || ¦  «        S |S  || |rdn|¦  «        S )a¢  Resolve an allowlisted variable without crossing profile boundaries.

    ``fallback`` is the value the caller would have forwarded before profile
    secret scopes existed (typically a snapshot of ``os.environ`` or the
    current profile's ``.env``).  An active multiplex scope is authoritative:
    a missing key returns ``None`` and never falls back to the process-global
    environment.  An unscoped read while multiplexing is active raises the
    fail-closed ``UnscopedSecretError`` from :mod:`agent.secret_scope`.

    Outside multiplexing, an installed scope keeps the existing overlay
    semantics and an unscoped caller keeps its already-resolved fallback.
    r   )Ú_is_global_envÚcurrent_secret_scopeÚ
get_secretÚis_multiplex_activeN)Úagent.secret_scoper?   r@   rA   rB   )r   r<   r?   r@   rA   rB   ÚscopeÚmultiplex_actives           r   Úresolve_passthrough_valuerF   ¶   s·   € ð ð ð ð ð ð ð ð ð ð ð ð ð €~�dÑÔð  Ð 4Øˆà Ð Ñ"Ô"€EØ*Ð*Ñ,Ô,ÐØ€}Øð 	$Ø�:˜dÑ#Ô#Ð#ØˆØˆ:�dÐ$4ÐB˜D˜D¸(ÑCÔCÐCr'   c                 óF   — t          ¦   «                              ¦   «          dS )z9Reset the skill-scoped allowlist (e.g. on session reset).N)r   Úclearr:   r'   r   Úclear_env_passthroughrI   Ý   s   € å�N„N×ÒÑÔÐÐÐr'   )r	   r
   )r   r   r	   r   )r   r    r	   r!   )r	   r(   )r6   r   r	   r   )N)r   r   r<   r=   r	   r=   )r	   r!   )Ú__doc__Ú
__future__r   ÚloggingÚcontextvarsr   Útypingr   r-   r   Ú	getLoggerÚ__name__r   r   Ú__annotations__r   r   r   r&   r5   r8   r;   rF   rI   r:   r'   r   ú<module>rR      sm  ððð ð ð* #Ð "Ð "Ð "Ð "Ð "à €€€Ø "Ð "Ð "Ð "Ð "Ð "Ø Ð Ð Ð Ð Ð Ø %Ð %Ð %Ð %Ð %Ð %à	ˆÔ	˜8Ñ	$Ô	$€ð /9¨jÐ9LÑ.MÔ.MÐ Ð MÐ MÐ MÑ Mðð ð ð ð .2Ð Ð 1Ð 1Ð 1Ñ 1ð(2ð (2ð (2ð (2ðV=ð =ð =ð =ðB%ð %ð %ð %ðP2ð 2ð 2ð 2ðBð Bð Bð Bð  ð$Dð $Dð $Dð $Dð $DðNð ð ð ð ð r'   