+
    lHàjÔ%  ã                   ó  € R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt	 ^ RI
HtHtHt ]P                  ! R4      tR R ltR R ltR	 R
 ltRtRR R lltR R lt]! R4      t]P0                  ! R4      tR R ltR R ltR# )a–  Pre-gate floors for :mod:`tools.approval`: decisions that never reach a prompt.

Unconditional blocks (hardline, ``sudo -S`` password piping, the user's own
``approvals.deny`` globs) and the permanent command allowlist match. All of
them run BEFORE yolo / ``approvals.mode: off`` / cron approve-mode; the
allowlist runs after. Session state stays in ``tools.approval`` and is read
through it at call time.
N)Úapproval_context)Ú_MALFORMED_EXEC_DESCRIPTIONÚ_PARSER_LIMIT_DESCRIPTIONÚ_deny_command_variantsztools.approvalc                ó>   € V ^8„  d   QhR\         R\         R,          /# ©é   ÚcommandÚreturnN©Ústr)Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/tools/approval_floors.pyÚ__annotate__r      s   € ÷ ñ ¤3ð ¬3°­:ñ ó    c                ó  €  \         P                  ! 4       P                  R4      ;'       g    . pT Uu. uFC  p\	        T\
        4      '       g   K  TP                  4       '       g   K3  TP                  4       NKE  	  ppT'       g   R# \        T 4       FZ  pTP                  4       P                  4       pT F3  p\        P                  ! YVP                  4       4      '       g   K/  Tu u # 	  K\  	  R#   \         d     R# i ; iu upi )u™  Return the matching ``approvals.deny`` glob, or None. User-defined fnmatch
globs that block unconditionally â€” like the hardline floor, a match fires
BEFORE the yolo / mode=off bypass ("never let the agent run this, even under
yolo"). Case-insensitive, run over the same normalized/deobfuscated variants
the dangerous-pattern detector uses so quoting tricks (``r\m``,
``git st""atus``) can't sidestep a rule.ÚdenyN)Ú_ctxÚ_get_approval_configÚgetÚ	ExceptionÚ
isinstancer   Ústripr   ÚlowerÚfnmatchÚfnmatchcase)r	   Údeny_patternsÚpÚglobsÚcommand_variantÚ	candidateÚpatterns   &      r   Ú_match_user_deny_ruler"      sÆ   € ðÜ×1Ò1Ó3×7Ñ7¸Ó?×EÐEÀ2ˆñ !.ÓR¡˜1´¸A¼s×1CŒYÈÏÉÏ	ŒYˆQ�W‰WŽY¡€EÐRßÙÜ1°'Ö:ˆØ#×)Ñ)Ó+×1Ñ1Ó3ˆ	ÛˆGÜ×"Ò" 9¯m©m«o×>Ô>Ø”ó ñ ;ñ
 øô ô ÚðüâRs'   ‚*C4 ­C4 ´DÁDÁ)DÃ4DÄDc                ó0   € V ^8„  d   QhR\         R\        /# )r   r!   r
   ©r   Údict)r   s   "r   r   r   -   s   € ÷ mñ m¤Sð m¬Tñ mr   c                ó   € RRRRRRV  R2/# )z@Build the standard block result for an ``approvals.deny`` match.ÚapprovedFÚ	user_denyTÚmessagez:BLOCKED: this command matches the user-defined deny rule 'uË   ' (approvals.deny in config.yaml). It cannot be executed via the agent â€” not even with --yolo, /yolo, or approvals.mode=off. Do NOT retry or rephrase this command; the user has explicitly forbidden it.© )r!   s   &r   Ú_user_deny_block_resultr+   -   s/   € à˜˜{¨D°)ðØˆ9ð kð	kðmð mr   c                ó>   € V ^8„  d   QhR\         R\         R,          /# r   r   )r   s   "r   r   r   6   s   € ÷ #ñ #¤3ð #¬3°­:ñ #r   c                ó,  €  ^ RI Hp V! 4       R,          R,          pVP                  RRR7       \        P                  ! 4       R,
          pVP	                  R4       F]  p\
        P                  ! \        4      ;_uu_ 4        VP                  4       P                  V8  d   VP                  4        RRR4       K_  	  VR\        \        P                  ! 4       4       R	\        P                  ! 4       P                  R
,           R2,          pTP                  RV R2V ,           V P!                  R4      '       d   RMR,           RRR7       \#        V4      #   + '       g   i     EK  ; i  \$         d    \&        P)                  RRR7        R# i ; i)uß  Persist a parser-limit-blocked command as a runnable script. That block
fires on payload SIZE/shape, not the operation â€” usually a legitimate script
the model inlined. Saving it makes recovery one turn (`bash <file>`) instead
of two, and is strictly safer than the hint-only path: the file goes through
the normal execution pipeline (including the referenced-script content guard)
and nothing runs here. Returns the path, or None on any failure (hint falls
back to write_file).)Úget_hermes_homeÚcachezblocked-scriptsT)ÚparentsÚexist_okzblocked-*.shNzblocked-Ú-:Né   Nz.shz®#!/usr/bin/env bash
# Auto-saved by Hermes: this command exceeded the inline command
# parser limit and was blocked from direct execution. Review it,
# then run it via: bash Ú
Ú zutf-8Úreplace)ÚencodingÚerrorszfailed to save blocked payload)Úexc_infoi€:	 )Úhermes_constantsr.   ÚmkdirÚtimeÚglobÚ
contextlibÚsuppressÚOSErrorÚstatÚst_mtimeÚunlinkÚintÚuuidÚuuid4ÚhexÚ
write_textÚendswithr   r   ÚloggerÚdebug)r	   r.   Ú
script_dirÚcutoffÚoldÚpaths   &     r   Ú_save_blocked_payloadrP   6   sT  € ðÝ4Ù$Ó&¨Õ0Ð3DÕDˆ
Ø×Ñ °ÐÔ5ä—’“˜yÕ(ˆØ—?‘? >Ö2ˆCÜ×$Ò$¤W×-Õ-Ø—8‘8“:×&Ñ&¨Ô/Ø—J‘J”L÷ .Ñ-ñ 3ð ˜h¤s¬4¯9ª9«;Ó'7Ð&8¸¼$¿*º*»,×:JÑ:JÈ2Õ:NÐ9OÈsÐSÕSˆØ�‰ð'ð (, f¨Bð0ð 3:õ:ð DK×CSÑCSÐTX×CYÒCY¹RÐ_cõeð  Yð 	ô 	
ô �4‹yÐ÷# .×-Ñ-ûô$ ô Ü�‰Ð5ÀˆÔEÚðús+   ‚B E- Â0EÂ2B%E- ÅE*Å#
E- Å-"FÆFzˆ RECOVERY: this block fires on oversized/unparseable inline command payloads (heredocs, giant one-liners), not on the operation itself. c                ó<   € V ^8„  d   QhR\         R\         R\        /# )r   Údescriptionr	   r
   r$   )r   s   "r   r   r   b   s&   € ÷ Eñ E¬ð E´cð EÄ4ñ Er   c                óÚ   € RV  R2pV \         \        39   dN   V'       d   \        V4      MRpV'       d   V\        RV RV R2,           ,          pMV\        R,           ,          pRR	R
RRV/# )z5Build the standard block result for a hardline match.zBLOCKED (hardline): uò   . This command is on the unconditional blocklist and cannot be executed via the agent â€” not even with --yolo, /yolo, approvals.mode=off, or cron approve mode. If you genuinely need to run it, run it yourself in a terminal outside the agent.NzYour command was saved to u1    â€” review it, then run: terminal(command="bash z"). Do not retry inline.z”Write the script to a file with write_file, then run it: terminal(command="bash /path/script.sh") or "python3 /path/script.py". Do not retry inline.r'   FÚhardlineTr)   )r   r   rP   Ú_RECOVERY_PREFIX)rR   r	   r)   Úsaveds   &&  r   Ú_hardline_block_resultrW   b   s›   € ð ˜{˜mð ,Kð 	Kð ð Ô0Ô2MÐNÔNß29Ô% gÔ.¸tˆßØÔ'Ø,¨U¨GÐ3eÐfkÐelð m'ð 'õõ ‰Gð
 Ô'ðDõõ ˆGð
 ˜˜z¨4°¸GÐDÐDr   c                ó0   € V ^8„  d   QhR\         R\        /# )r   rR   r
   r$   )r   s   "r   r   r   }   s   € ÷ bñ b¬#ð b´$ñ br   c                ó   € RRRRV  R2/# )z5Build the standard block result for sudo stdin guard.r'   Fr)   z	BLOCKED: uÎ   . Do not pipe passwords to 'sudo -S' â€” this is a brute-force attack vector. Set SUDO_PASSWORD in your .env file if the agent needs passwordless sudo, or run the sudo command manually in your own terminal.r*   )rR   s   &r   Ú_sudo_stdin_block_resultrZ   }   s(   € à˜˜yØ
�K�=ð !`ð 	`ðbð br   z
;&|<>`$()z:(?:^|[ \t])(?:-[^-\s]*[ce]|--(?:command|eval))(?:[= \t]|$)c                ó0   € V ^8„  d   QhR\         R\        /# ©r   r	   r
   ©r   Úbool)r   s   "r   r   r   �   s   € ÷ )Tñ )T¬3ð )T´4ñ )Tr   c                ó>  € T ;'       g    Rp RpRp^ p\        V 4      pW48  dÎ   W,          pVR8X  d?   VR8w  d8   V^,           V8  d   W^,           ,          MRpV\        9   d   RpV^,          pKS  Ve(   WQ8X  d   RpMhVR8X  d
   VR9   d   R# V\        9   d   RpMJVR9   d   TpM@VR8X  d&   V^,           V8  d   W^,           ,          R	8X  d   R# MV\        9   d
   VR
9  d   R# V^,          pKÓ  Ve   R# T;'       d    \        \        P	                  V 4      4      # )aÚ  Return True when a command is too compound for the allowlist shortcut.
Quote-aware: metacharacters inside quotes or behind a backslash are literal
arguments (``cargo bench -- '^a(b|c)$'``), not shell syntax. Still
disqualifying: ``$`` or backtick inside DOUBLE quotes (expansion stays
active), and any quoted/escaped control character when the command also
carries a ``-c``/``-e``/``--command``/``--eval``-style option that would
hand the quoted text to another interpreter.r5   NFÚ\Ú'TÚ"Ú$Ú(z())Ú`rc   )ra   rb   )ÚlenÚ_SHELL_CONTROL_CHARSr^   Ú_REINTERPRETED_ARGUMENT_REÚsearch)r	   ÚquoteÚhas_reinterpretableÚiÚnÚchÚnxts   &      r   Ú_has_allowlist_shell_operatorrp   �   s  € ð �mˆm˜€GØ€EØÐØ	€AÜˆG‹€AØ
Œ%Ø�ZˆØ�Œ:˜% 3œ,Ø$%¨¥E¨A¤I�'˜a�%–.°2ˆCØÔ*Ô*Ø&*Ð#Ø��FˆAÙØÒØŒ{Ø‘Ø˜#” "¨
Ô"2ÙØÔ+Ô+Ø&*Ð#øØ�:ÔØ‰EØ�3ŒYð �1�u�qŒy˜W¨¥U�^¨sÔ2ÙøØÔ'Ô'¨B°d¬NÙØ	ˆQ�ŠàÒÙØ×SÐS¤4Ô(B×(IÑ(IÈ'Ó(RÓ#SÐSr   c                ó0   € V ^8„  d   QhR\         R\        /# r\   r]   )r   s   "r   r   r   ¼   s   € ÷ ñ ´#ð ¼$ñ r   c                óX  a€ ^ RI Hp T ;'       g    RP                  4       p V '       d   \        V 4      '       d   R# VP                  ;_uu_ 4        \        VP                  4       4      pRRR4       X Fž  o\        S\        4      '       d   SP                  4       MRoS'       g   K5  V S8X  gb   \        ;QJ d    V3R lR 4       F  '       g   K   RM	  RM! V3R lR 4       4      '       g   K~  \        P                  ! V S4      '       g   K�   R# 	  R#   + '       g   i     L¶; i)a  True when command_allowlist holds this exact command text or a matching
glob. Permanent approvals historically store dangerous-pattern keys such as
``recursive delete``; manual entries are command text, possibly with
shell-style wildcards like ``podman *``.)Úapprovalr5   FNc              3   ó,   <"  € T F	  qS9   x € K  	  R # 5i)Nr*   )Ú.0rn   r!   s   & €r   Ú	<genexpr>Ú7_command_matches_permanent_allowlist.<locals>.<genexpr>É   s   øé € Ð2QÉ5ÀR¸¶=Ë5ùs   ƒz*?[T)Útoolsrs   r   rp   Ú_lockÚtupleÚ_permanent_setr   r   Úanyr   r   )r	   Ú_aÚpatternsr!   s   &  @r   Ú$_command_matches_permanent_allowlistr   ¼   sÁ   ø€ õ
 %Ø�}ˆ}˜"×#Ñ#Ó%€GßÔ3°G×<Ò<ÙØ	��‹Ü˜×*Ñ*Ó,Ó-ˆ÷ 
ãˆÜ%/°¼×%=Ò%=�'—-‘-”/À2ˆß‰7˜ 7Ô*¯s«sÔ2QÉ5Ó2Q¯s¯sªsÔ2QÉ5Ó2Q×/QÔ/QÜ3:×3FÒ3FÀwÐPW×3XÔ3XÚñ	 ñ
 ÷ 
�ús   ÁDÄD)	)r5   )Ú__doc__r>   r   ÚloggingÚrer<   rE   rx   r   r   Útools.approval_detectionr   r   r   Ú	getLoggerrJ   r"   r+   rP   rU   rW   rZ   Ú	frozensetrg   Úcompilerh   rp   r   r*   r   r   Ú<module>r‡      s‘   ðñó Û Û Û 	Û Û Ý *÷Tñ Tð 
×	Ò	Ð+Ó	,€õõ,mõ#ðNSð ÷Eõ6bñ ! Ó1Ð àŸZšZÐ(eÓfÐ õ)T÷Xr   