
    (Gj                        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ZdS )#ua  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.
    )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/rurouni/.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   0   s    (	
 	
 	
 	
 	
 	
 	
 	
 	
    N		
 	
 	
 ttttt "!$'' 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.
    zenv 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       = =zz|| 	)$// 	NNA    4   5t<<<<= =    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_passthroughzenv 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    &""uuFP555555oc:/@AAk4(( 	!# ! !!$,, DJJLL zz|| 2$77 
NN/    

4     P P PKQ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 )zCheck 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'   c                 F    t                                                       dS )z9Reset the skill-scoped allowlist (e.g. on session reset).N)r   clearr:   r'   r   clear_env_passthroughr>      s    NNr'   )r	   r
   )r   r   r	   r   )r   r    r	   r!   )r	   r(   )r6   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;   r>   r:   r'   r   <module>rG      sI    & # " " " " "  " " " " " "       % % % % % %		8	$	$ /9j9L.M.M  M M M M    .2  1 1 1 1(2 (2 (2 (2V= = = =B% % % %P2 2 2 2B B B B
     r'   