
    i                        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/ubuntu/.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} n# t          $ r Y dS w xY w| |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.
    r   )_HERMES_PROVIDER_ENV_BLOCKLISTF)tools.environments.localr   	Exception)r   r   s     r   _is_hermes_provider_credentialr   0   sJ    KKKKKKK   uu111s   	 
	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   loggerwarningr   adddebug)r   r   s     r   register_env_passthroughr$   F   s       = =zz|| 	)$// 	NNA    4   5t<<<<= =    frozenset[str]c                    t           t           S t                      } 	 ddlm}  |            }t	          |dd          }t          |t                    rU|D ]R}t          |t                    r;|                                r'| 	                    |                                           Sn2# 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_passthroughz4Could not read tools.env_passthrough from config: %s)r   r   hermes_cli.configr(   r   
isinstancelistr   r   r"   r   r    r#   	frozenset)resultr(   cfgpassthroughitemes         r   _load_config_passthroughr4   g   s    &""uuF	P555555oc:/@AAk4(( 	-# - -dC(( -TZZ\\ -JJtzz||,,, P P PKQOOOOOOOOP $F++s   BB* *
C4CC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   r4   )r5   s    r   is_env_passthroughr7   }   s*     <>>!!t/1111r%   c                 V    t          t                                t                      z  S )zGReturn the union of skill-registered and config-based passthrough vars.)r.   r   r4    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   clearr9   r%   r   clear_env_passthroughr=      s    NNr%   )r	   r
   )r   r   r	   r   )r   r   r	   r   )r	   r&   )r5   r   r	   r   )r	   r   )__doc__
__future__r   loggingcontextvarsr   typingr   r+   r   	getLogger__name__r    r   __annotations__r   r   r   r$   r4   r7   r:   r=   r9   r%   r   <module>rF      sG    & # " " " " "  " " " " " "       % % % % % %		8	$	$ /9j9L.M.M  M M M M    .2  1 1 1 12 2 2 2,= = = =B   ,2 2 2 2B B B B
     r%   