
    `gjH                        d Z ddlmZ dZdZdZdZdZdZd	d
 dddd ddgdddddgdddd dddddgddd d!gd"dd#d$d%gd&dd'd( d)edd*d+ d,d-gd.d/d0d1d2d3d4d5d6d3d7d8ed3d9d:d;d3d<d=d>d3d?d@dAd3dBdCed3dDdEed3dFdGdHd3dIdJed3dKdLdMgdNddOdPgdQddRdSdTd3dUdVed3dWdXed3dYdZed3gZ	 G d[ d\e      Z
i d	e
j                  de
j                  de
j                  de
j                  de
j                  d e
j                   d#e
j"                  d'e
j$                  d*e
j&                  d0e
j(                  d4e
j*                  d7e
j,                  d9e
j.                  d<e
j0                  d?e
j2                  dBe
j4                  dDe
j6                  e
j8                  e
j:                  e
j<                  e
j>                  e
j@                  e
jB                  e
jD                  e
jF                  d]Z$ e%e$      e	D  ch c]  } | d^   	 c} k(  s9J d_ e%d` e	D               e%e$      z
   da e%e$       e%db e	D              z
          dc Z&ydc c} w )eu  
Regex-based security pattern definitions for the security-guidance plugin.

Pure data + one pure helper. No env-var reads, no I/O — kept side-effect-free
so it can be imported in isolation.

Forked verbatim from Anthropic's claude-plugins-official repository
(plugins/security-guidance/hooks/patterns.py) under the Apache License 2.0:

    https://github.com/anthropics/claude-plugins-official

  Copyright (c) Anthropic, PBC. and the security-guidance contributors
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

Modifications by NousResearch for the Hermes Agent plugin port:
  - none to the pattern data itself; this file is byte-for-byte the upstream
    patterns.py at commit 0bde168 (2026-05-26). Hermes-side wiring lives in
    __init__.py.
    )IntEnum)
z.jsz.jsxz.tsz.tsxz.mjsz.cjsz.mtsz.ctsz.vuez.svelte)z.pyz.pyiz.ipynb)z.mdz.mdxz.txtz.rstz.json.yaml.ymlu  ⚠️ Security Warning: Loading pickle data (or equivalents: cPickle, cloudpickle, dill, marshal, shelve, joblib, pandas.read_pickle, numpy with allow_pickle=True) from untrusted sources allows arbitrary code execution.

For simple data, prefer JSON or msgspec. For typed objects, prefer a schema-validated deserializer (msgspec.Struct, pydantic, marshmallow) that constructs only declared types.

If this is safe or is explicitly needed, briefly document that in a comment before continuing.u  ⚠️ Security Warning: yaml.load() / yaml.unsafe_load() execute arbitrary Python via !!python/object tags.

Use yaml.safe_load() if the file only contains simple data structures (dicts, lists, strings, numbers). If you need typed objects, parse with safe_load and validate the result against a schema (pydantic, msgspec, marshmallow) — never use a custom Loader that constructs arbitrary types.u  ⚠️ Security Warning: torch.load() defaults to weights_only=False, which unpickles arbitrary Python objects and allows arbitrary code execution.

If the file only contains tensors and simple data structures, pass weights_only=True (or set TORCH_FORCE_WEIGHTS_ONLY_LOAD=1).github_actions_workflowc                 V    d| v xr$ | j                  d      xs | j                  d      S )Nz.github/workflows/r   r   )endswith)paths    U/root/.hermes/venv/lib/python3.12/site-packages/plugins/security-guidance/patterns.py<lambda>r   8   s.    #74#? $>]]6"<dmmG&<     uJ  ⚠️ Security Warning: You are editing a GitHub Actions workflow file. Be aware of these security risks:

1. **Command Injection**: Never use untrusted input (like issue titles, PR descriptions, commit messages) directly in run: commands without proper escaping
2. **Use environment variables**: Instead of ${{ github.event.issue.title }}, use env: with proper quoting
3. **Review the guide**: https://github.blog/security/vulnerability-research/how-to-catch-github-actions-workflow-injections-before-attackers-do/

Example of UNSAFE pattern to avoid:
run: echo "${{ github.event.issue.title }}"

Example of SAFE pattern:
env:
  TITLE: ${{ github.event.issue.title }}
run: echo "$TITLE"

Other risky inputs to be careful with:
- github.event.issue.body
- github.event.pull_request.title
- github.event.pull_request.body
- github.event.comment.body
- github.event.review.body
- github.event.review_comment.body
- github.event.pages.*.page_name
- github.event.commits.*.message
- github.event.head_commit.message
- github.event.head_commit.author.email
- github.event.head_commit.author.name
- github.event.commits.*.author.email
- github.event.commits.*.author.name
- github.event.pull_request.head.ref
- github.event.pull_request.head.label
- github.event.pull_request.head.repo.default_branch
- github.event.client_payload.* (repository_dispatch events — attacker can set any field)

4. **Ref injection**: Never use untrusted input in `ref:` parameters of `actions/checkout`. For `client_payload.pr_number`, validate it matches `^[0-9]+$` before using in `ref: refs/pull/${{ ... }}/head`
- github.head_ref)ruleName
path_checkreminderchild_process_execc                 ,    | j                  t              S N)r   _JS_EXTSps    r
   r   r   b       H!5 r   zchild_process.execz	execSync(z(?<![a-zA-Z0-9_\.])exec\(u  ⚠️ Security Warning: Using child_process.exec() can lead to command injection vulnerabilities.

exec() runs the command string through a shell, so any user input interpolated into it can inject arbitrary commands. Prefer child_process.execFile() (or spawn()) with an argument array instead of building a shell string.

Instead of:
  exec(`command ${userInput}`)

Use:
  import { execFile } from 'node:child_process'
  execFile('command', [userInput], callback)

Why execFile/spawn with an argument array is safer:
- No shell is involved, so shell metacharacters in arguments are not interpreted
- Arguments are passed directly to the program rather than interpolated into a command string

Only use exec() if you absolutely need shell features and the input is guaranteed to be safe.)r   path_filter
substringsregexr   new_function_injectionznew Functionu  ⚠️ Security Warning: Using new Function() with string interpolation is a CODE INJECTION vulnerability. If any variable is concatenated or interpolated into the function body string, an attacker controlling that variable can execute arbitrary code. Use safe alternatives: for property access use obj[key] or array.reduce((o, k) => o[k], root); for computation use a safe expression parser. NEVER interpolate untrusted strings into new Function() bodies.)r   r   r   eval_injectionc                 .    | j                  t               S r   )r   	_DOC_EXTSr   s    r
   r   r      s    QZZ	%:!: r   z(?<![a-zA-Z0-9_\.])eval\(u  ⚠️ Security Warning: eval() executes arbitrary code and is a major security risk. Use JSON.parse() for data, ast.literal_eval() for Python literals, or a safe expression parser. If this is safe or is explicitly needed, briefly document that in a comment before continuing.)r   r   r   r   react_dangerously_set_htmldangerouslySetInnerHTMLu   ⚠️ Security Warning: dangerouslySetInnerHTML can lead to XSS vulnerabilities if used with untrusted content. Ensure all content is properly sanitized using an HTML sanitizer library like DOMPurify, or use safe alternatives.document_write_xsszdocument.writeu   ⚠️ Security Warning: document.write() can be exploited for XSS attacks and has performance issues. Use DOM manipulation methods like createElement() and appendChild() instead.innerHTML_xssz.innerHTML =z.innerHTML=u   ⚠️ Security Warning: Setting innerHTML with untrusted content can lead to XSS vulnerabilities. Use textContent for plain text or safe DOM methods for HTML content. If you need HTML support, consider using an HTML sanitizer library such as DOMPurify.pickle_deserializationc                 ,    | j                  t              S r   r   _PY_EXTSr   s    r
   r   r      r   r   zI(?<![a-zA-Z0-9_])pickle\.(loads?|Unpickler)\b|(?<![a-zA-Z0-9_])pkl_load\(os_system_injectionc                 ,    | j                  t              S r   r$   r   s    r
   r   r      r   r   z\bos\.system\s*\(zfrom os import systemu   ⚠️ Security Warning: os.system() runs a shell and is a command-injection sink. Use subprocess.run([...]) with a list of arguments instead. If this is safe or is explicitly needed, briefly document that in a comment before continuing.)r   r   r   r   r   python_subprocess_shellzJsubprocess\.(?:run|call|Popen|check_output|check_call)\(.*shell\s*=\s*Trueu  ⚠️ Security Warning: Using subprocess with shell=True enables command injection.

UNSAFE:
  subprocess.run(f"ls {user_input}", shell=True)
  subprocess.call("grep " + pattern, shell=True)

SAFE - pass arguments as a list without shell:
  subprocess.run(["ls", user_input])
  subprocess.call(["grep", pattern])

When arguments are passed as a list without shell=True, special characters cannot be interpreted as shell metacharacters.)r   r   r   go_exec_shell_injectionz1exec\.Command\(\s*"(?:sh|bash|/bin/sh|/bin/bash)"u  ⚠️ Security Warning: Using exec.Command with a shell interpreter (sh/bash) enables command injection.

UNSAFE:
  exec.Command("sh", "-c", "ping -c 1 " + host)
  exec.Command("bash", "-c", fmt.Sprintf("df -h %s", path))

SAFE - pass arguments directly without a shell:
  exec.Command("ping", "-c", "1", host)
  exec.Command("df", "-h", path)

When arguments are passed directly (not through a shell), special characters in user input cannot be interpreted as shell metacharacters. This prevents command injection entirely.

Additionally, validate user inputs:
- For hostnames/IPs: use net.ParseIP() or a hostname regex
- For file paths: use filepath.Clean() and verify the result is within an allowed directory
- For numeric values: parse to int/float firstunsafe_yaml_loadz'\byaml\.load\s*\((?![^)\n]{0,80}\bSafe)node_createcipher_no_ivz)\bcrypto\.(createCipher|createDecipher)\bu   ⚠️ Security Warning: Use crypto.createCipheriv() / createDecipheriv(). createCipher was removed in Node 22 and derives the key insecurely (no IV, MD5-based KDF).aes_ecb_modezC\bAES\.MODE_ECB\b|\bmodes\.ECB\s*\(|[\x22\x27]aes-\d+-ecb[\x22\x27]u   ⚠️ Security Warning: Use AES-GCM or AES-CBC with HMAC. ECB mode leaks plaintext structure (identical blocks encrypt to identical ciphertext).tls_verification_disabledz\bverify\s*=\s*False\b|rejectUnauthorized\s*:\s*false|InsecureSkipVerify\s*:\s*true|NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*[\x22\x27]?0|ssl\._create_unverified_context|check_hostname\s*=\s*Falseu   ⚠️ Security Warning: Don't disable TLS verification. This allows MITM attacks. For self-signed dev certs, add the CA to your trust store or use a properly-issued cert.marshal_loadsz\bmarshal\.loads?\s*\(shelve_openz\bshelve\.open\s*\(xml_unsafe_parsez\b(xml\.etree\.ElementTree|ElementTree|ET)\.(parse|fromstring|XML)\s*\(|\bminidom\.(parse|parseString)\s*\(|\bxml\.sax\.(parse|make_parser)\bu   ⚠️ Security Warning: Use defusedxml.ElementTree. Python's stdlib XML parsers are vulnerable to XXE (external entity) and billion-laughs attacks by default.pickle_variants_loadz/\b(cPickle|cloudpickle|dill)\.(load|loads)\s*\(outerHTML_xssz.outerHTML =z.outerHTML=u   ⚠️ Security Warning: Use textContent or sanitize with DOMPurify. outerHTML assignment is an XSS sink equivalent to innerHTML.insertAdjacentHTML_xssz.insertAdjacentHTML(up   ⚠️ Security Warning: Use insertAdjacentText() or sanitize with DOMPurify. insertAdjacentHTML is an XSS sink.script_src_without_sriz{<script\s+(?![^>]{0,400}integrity\s*=)[^>]{0,200}src\s*=\s*[\x22\x27](?:https?:)?//[^\x22\x27]{1,300}[\x22\x27][^>]{0,100}>u   ⚠️ Security Warning: Add integrity="sha384-..." crossorigin="anonymous" to external script tags. Loading scripts without Subresource Integrity exposes you to CDN compromise.torch_unsafe_loadzK(?:\btorch\.load|\.torch_load)\s*\((?![^)\n]{0,200}weights_only\s*=\s*True)yaml_unsafe_load_variantsz/(?:\byaml\.unsafe_load|\.yaml_unsafe_load)\s*\(pickle_wrapper_loadz\bjoblib\.load\s*\(|\b(?:pd|pandas)\.read_pickle\s*\(|\.cloudpickle_load\s*\(|\b(?:np|numpy)\.load\s*\([^)\n]{0,200}allow_pickle\s*=\s*Truec                   t    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZy)RuleIdaf  
    Stable numeric IDs for SECURITY_PATTERNS rules, emitted via the PostToolUse
    metrics field so telemetry can attribute pattern-warning events to
    specific checks. The metrics schema only allows bool|number values (no
    strings), so rule names can't be sent directly.

    Values are frozen: do not renumber existing entries. Append new ones.
                            	   
                                                N)__name__
__module____qualname____doc__GITHUB_ACTIONS_WORKFLOWCHILD_PROCESS_EXECNEW_FUNCTION_INJECTIONEVAL_INJECTIONREACT_DANGEROUSLY_SET_HTMLDOCUMENT_WRITE_XSSINNERHTML_XSSPICKLE_DESERIALIZATIONOS_SYSTEM_INJECTIONPYTHON_SUBPROCESS_SHELLGO_EXEC_SHELL_INJECTIONUNSAFE_YAML_LOADNODE_CREATECIPHER_NO_IVAES_ECB_MODETLS_VERIFICATION_DISABLEDMARSHAL_LOADSSHELVE_OPENXML_UNSAFE_PARSEPICKLE_VARIANTS_LOADOUTERHTML_XSSINSERTADJACENTHTML_XSSSCRIPT_SRC_WITHOUT_SRITORCH_UNSAFE_LOADYAML_UNSAFE_LOAD_VARIANTSPICKLE_WRAPPER_LOAD r   r
   r9   r9     s      N!"M   L "MKM "r   r9   )r0   r1   r2   r3   r4   r5   r6   r7   r   z8RuleId enum out of sync with SECURITY_PATTERNS: missing=c              #   &   K   | ]	  }|d      ywr   Nrp   .0r   s     r
   	<genexpr>ru   c  s     <Q1Z=<   z, extra=c              #   &   K   | ]	  }|d      ywrr   rp   rs   s     r
   ru   ru   d  s     (R1:(Rrv   c                 H    d}| D ]  }|t         v s|dt         |   z  z  } |S )zPack a set of rule names into a bitmask. Bit N set means RuleId(N) matched.
    User-defined patterns (rule_name starting with "user:") have no static
    RuleId and are excluded from the mask.r   r:   )_RULE_NAME_TO_ID)
rule_namesmasknames      r
   rule_names_to_maskr}   h  s=     D 0##A)$///D0 Kr   N)'rV   enumr   r   r%   r    _UNSAFE_DESERIALIZATION_REMINDER_UNSAFE_YAML_LOAD_REMINDER_UNSAFE_TORCH_LOAD_REMINDERSECURITY_PATTERNSr9   rW   rX   rY   rZ   r[   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   ry   setr}   r   s   0r
   <module>r      sg  :  ]$E	$b  d B  .>"	'R ) 6+[9-a2 -%& e % ;- k 101 z )'( J $%}5 T - 6]4 *5%./ D .^
}& .E2	, ';. .= | #W h 0 S B $*4 "'4 ' b v +C4 $%}5 X --. G -
 H ( `/ 0 D. * `4Ag T!W !Hv==&33 f;; f++	
 !&"C"C &33 V)) f;; 655 v== v== // v== F''  !A!A  V))!" 6%%#$ //"77))$;;$;;11!'!A!A!553 < 8I J1: JJ <*;<<sCS?TTU V!"S(R@Q(R%RRSUJ !Ks   :I