github.com / NousResearch
NousResearch/ hermes-agent
Python·10235 files·commit 9cce872·scanned 4d ago·cached ✓
15/100
LOW RISK
Minor findings consistent with the project type. Nothing reachable from install hooks.
score capped at 15 — 235,934+ stars — findings likely false positives
verdict accurate?
235,934 stars
Crypto/Web3 project
24% file coverage
Partial architecture graph
Desktop app detected
threat-state: lowlive
FINDINGS ░▒▓
criticalRust process Command usagestd::process::Command can execute arbitrary shell commands. Malware uses it to drop payloads, exfiltrate data, or establish persistence.apps/bootstrap-installer/src-tauri/src/bootstrap.rs
let output = std::process::Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(install_root)+8criticalRust process Command usagestd::process::Command can execute arbitrary shell commands. Malware uses it to drop payloads, exfiltrate data, or establish persistence.apps/bootstrap-installer/src-tauri/src/paths.rs
// executable before the update handoff reaches LaunchServices/Gatekeeper.
let _ = Command::new("/usr/bin/xattr")
.args(["-cr"])
.arg(path)+8criticalRust process Command usagestd::process::Command can execute arbitrary shell commands. Malware uses it to drop payloads, exfiltrate data, or establish persistence.apps/bootstrap-installer/src-tauri/src/powershell.rs
// see `windows_powershell_exe`.
let mut cmd = Command::new(windows_powershell_exe());
cmd.arg("-NoProfile");
cmd.arg("-ExecutionPolicy").arg("Bypass");+8warningRust unsafe blockunsafe blocks bypass Rust's memory safety guarantees. Malware uses them for raw pointer manipulation, shellcode injection, or calling dangerous foreign functions.apps/bootstrap-installer/src-tauri/src/update.rs
unsafe {
let handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
if handle.is_null() {+3criticaleval() usage detectedeval() executes arbitrary code and is commonly used in malware to run obfuscated payloads fetched from remote servers.apps/desktop/scripts/perf/lib/cdp.mjs
/** Evaluate an expression in the page and return its value (awaits promises). */
async eval(expression) {
const r = await this.send('Runtime.evaluate', { expression, returnByValue: true, awai...+8criticalFunction() constructor detectednew Function() is equivalent to eval() and can execute arbitrary code strings.apps/desktop/src/lib/preview-act/act-in-page.test.ts
const injected = new Function('return ' + actEngineSource())() as typeof actInPage
const holder: PreviewActHolder = {}
+5criticalFunction() constructor detectednew Function() is equivalent to eval() and can execute arbitrary code strings.apps/desktop/src/lib/preview-act/watch-in-page.test.ts
const injected = new Function('return (' + watchInPage.toString() + ')')() as typeof watchInPage
expect(() => injected(document, { aimed: target }, 'aim', 'Clicking Save')).not.toThrow()+5criticalFunction() constructor detectednew Function() is equivalent to eval() and can execute arbitrary code strings.apps/desktop/src/plugins/hermes-bots/tests/bot-open-focus-identity.test.mjs
}
const release = new Function('$openBotChat', `${body}; return releaseStaleOpenBotChat`)($openBotChat)
// compressed chat: claim carries registry 'reg-1' and tip 'tip-9'+5warningPython subprocess / os.system usageos.system() or subprocess with shell=True / suspicious commands can execute arbitrary shell commands. Plain pip/package installs are usually benign.optional-skills/creative/kanban-video-orchestrator/scripts/monitor.py
try:
out = subprocess.run(
["hermes", "kanban", "list", "--tenant", tenant, "--json"],
capture_output=True, text=True, encoding='utf-8', errors='replace', check=Fal...+4criticalPython dynamic code executioneval(), exec() or compile() on untrusted input can execute arbitrary code. Common in Python malware for running obfuscated payloads.optional-skills/security/godmode/scripts/auto_jailbreak.py
Usage in execute_code:
exec(open(os.path.expanduser(
os.path.join(os.environ.get("HERMES_HOME", os.path.expanduser("~/.hermes")), "skills/red-teaming/godmode/scripts/auto_jailbreak.py")
...+7criticalPython dynamic code executioneval(), exec() or compile() on untrusted input can execute arbitrary code. Common in Python malware for running obfuscated payloads.optional-skills/security/godmode/scripts/godmode_race.py
Usage in execute_code:
exec(open(os.path.join(os.environ.get("HERMES_HOME", os.path.expanduser("~/.hermes")), "skills/red-teaming/godmode/scripts/godmode_race.py")).read())
result = race_...+7criticalPython dynamic code executioneval(), exec() or compile() on untrusted input can execute arbitrary code. Common in Python malware for running obfuscated payloads.optional-skills/security/godmode/scripts/load_godmode.py
Usage in execute_code:
exec(open(os.path.expanduser(
os.path.join(os.environ.get("HERMES_HOME", os.path.expanduser("~/.hermes")), "skills/red-teaming/godmode/scripts/load_godmode.py")
...+7warningPython subprocess / os.system usageos.system() or subprocess with shell=True / suspicious commands can execute arbitrary shell commands. Plain pip/package installs are usually benign.scripts/check-windows-footguns.py
"else:\n"
" subprocess.run(['powershell', '-NoProfile', '-Command',\n"
" 'Get-CimInstance Win32_Process | ...'])"
),+4warningPython subprocess / os.system usageos.system() or subprocess with shell=True / suspicious commands can execute arbitrary shell commands. Plain pip/package installs are usually benign.scripts/ci/lockfile_diff.py
"""Contents of ``path`` at ``ref``, or None if it doesn't exist there."""
proc = subprocess.run(
["git", "show", f"{ref}:{path}"],
capture_output=True,+4criticalRemote script piped into a shellA shell script downloads remote content and executes it directly (e.g. `curl … | bash`). The payload is never stored or reviewable and can change server-side — a classic malware/backdoor install pattern.scripts/dev-sandbox.sh
set +e
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- "$@"
install_status=$?
if [ "$install_status" -eq 0 ] && [ -f /work/promote-main ]; then+10criticalchild_process / exec usageExecuting shell commands can be used to download and run malware, exfiltrate data, or modify system files.apps/desktop/electron/bootstrap-runner.ts
((args, cwd) =>
execFileSync('git', args, {
cwd,
encoding: 'utf8',+8criticalchild_process / exec usageExecuting shell commands can be used to download and run malware, exfiltrate data, or modify system files.apps/desktop/electron/update-handoff-marker.test.ts
return spawnSync('/bin/bash', [POSIX_SCRIPT, '--daemonized', '--install-root', installRoot, '--self-test-marker'], {
env,
encoding: 'utf8'+8warningHardcoded IP address in network callFetching data from hardcoded IP addresses instead of domain names is suspicious and may indicate C2 communication.apps/desktop/src/components/boot-failure-overlay.test.tsx
remoteTokenSet: true,
remoteUrl: 'http://100.116.104.53:9191',
cloudOrg: ''
}+5warningHardcoded IP address in network callFetching data from hardcoded IP addresses instead of domain names is suspicious and may indicate C2 communication.apps/desktop/src/lib/remote-url.test.ts
it('prepends http:// to scheme-less host:port input', () => {
expect(coerceRemoteUrlScheme('100.64.0.1:9119')).toBe('http://100.64.0.1:9119')
expect(coerceRemoteUrlScheme('mini.tailnet-1234....+5warningHardcoded IP address in network callFetching data from hardcoded IP addresses instead of domain names is suspicious and may indicate C2 communication.agent/model_metadata.py
# block, so without an explicit check Ollama reached over Tailscale (e.g.
# `http://100.77.243.5:11434`) wouldn't be treated as local and its stream
# read / stale timeouts wouldn't get auto-bumped. B...+5warningSSH/credential path accessAccessing .ssh, .aws/credentials, or .env files to steal authentication credentials.apps/desktop/src/app/settings/ssh-host-selection.test.ts
enrichSelectedSshHost(selected, 'mac-box', {
identityFile: '~/.ssh/id_ed25519',
port: 22,
user: 'hermes'+5criticalBrowser credential store accessAccessing Chrome, Firefox, Edge, or Brave profile directories to steal cookies, passwords, and session tokens.optional-skills/security/unbroker/scripts/cdp.py
r"Chromium\Application\chrome.exe",
r"BraveSoftware\Brave-Browser\Application\brave.exe",
r"Microsoft\Edge\Application\msedge.exe",
]+10warningSSH/credential path accessAccessing .ssh, .aws/credentials, or .env files to steal authentication credentials.acp_adapter/edit_approval.py
SENSITIVE_AUTO_APPROVE_NAMES = {".env", ".env.local", ".env.production", "id_rsa", "id_ed25519"}
AUTO_APPROVE_ASK = "ask"
AUTO_APPROVE_WORKSPACE = "workspace_session"+5warningSSH/credential path accessAccessing .ssh, .aws/credentials, or .env files to steal authentication credentials.agent/context_references.py
_NEEDS_QUOTING = re.compile(r"""[\s()\[\]{}<>"'`]""")
_SENSITIVE_HOME_DIRS = (".ssh", ".aws", ".gnupg", ".kube", ".docker", ".azure", ".config/gh")
_SENSITIVE_HERMES_DIRS = (Path("skills") / ".hub",)
...+5warningExtremely long lines (>1000 chars)Very long lines in source files (not minified bundles) can hide malicious code.apps/desktop/src/components/ui/tool-icon.tsx+4
warningFlattened or dead control flowDetected switch(true), dead if branches, or deeply nested ternaries — patterns used by obfuscators to hide execution order.apps/desktop/src/app/session/hooks/use-message-stream/index.ts+3
warningFlattened or dead control flowDetected switch(true), dead if branches, or deeply nested ternaries — patterns used by obfuscators to hide execution order.apps/desktop/src/app/session/hooks/use-prompt-actions/index.ts+3
warningFlattened or dead control flowDetected switch(true), dead if branches, or deeply nested ternaries — patterns used by obfuscators to hide execution order.apps/desktop/src/app/session/hooks/use-session-actions/index.ts+3
warningHigh-entropy string literalsFound 4 long strings with high Shannon entropy. This is common in obfuscated payloads that hide URLs, keys, or bytecode.apps/bootstrap-installer/src/components/button.tsx+3
warningHigh-entropy string literalsFound 3 long strings with high Shannon entropy. This is common in obfuscated payloads that hide URLs, keys, or bytecode.apps/desktop/scripts/before-pack.mjs+3
warningHigh-entropy string literalsFound 3 long strings with high Shannon entropy. This is common in obfuscated payloads that hide URLs, keys, or bytecode.apps/desktop/scripts/diag-drag-churn.mjs+3
warningLarge base64-encoded blobA 92-character base64 blob was found. May hide a remote payload or encoded executable code.apps/desktop/src/lib/image-resize.test.ts
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8...+3
warningLarge base64-encoded blobA 376-character base64 blob was found. May hide a remote payload or encoded executable code.apps/desktop/e2e/image-attachment-resume.spec.ts
iVBORw0KGgoAAAANSUhEUgAAAKAAAABkCAIAAACO1KzYAAAA30lEQVR42u3d...+3
infoSuspicious file in repoVery large source file (554KB) — could contain obfuscated payloadapps/desktop/electron/main.ts+2
infoSuspicious file in repoVery large source file (580KB) — could contain obfuscated payloadapps/desktop/src/plugins/hermes-bots/plugin.js+2
infoSuspicious file in repoVery large source file (986KB) — could contain obfuscated payloadcli.py+2
Scores are heuristics. A “safe” verdict means no known-malicious patterns were found — clever malware can look boring. Wrong verdict? Flag it above; confirmed false positives become regression tests.
2476 files scanned @ 9cce872 | 8/25/2026 | heuristic scan — always review manually
risk by category
code execution25
network & exfiltration25
file system access20
obfuscation15
supply chain15
owasp / injection0
telemetry
files 2476/10235rules hit 38engine v5commit 9cce872
github
NousResearch/hermes-agent
The agent that grows with you
235934
47602
403d
10235 files
2476 scanned(24%)
9cce872
architecture░▒▓
entry (2) flagged (528) pkg (876)
1406 nodes · 4269 edgesscroll to zoom · click node to jump to finding