Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0791efe
fix(security): add SSRF protection to vision_tools and web_tools (har…
teknium1 Mar 23, 2026
ad5f973
fix(vision): make SSRF redirect guard async for httpx.AsyncClient
teknium1 Mar 23, 2026
f9c2565
fix(config): log warning instead of silently swallowing config.yaml e…
teknium1 Mar 23, 2026
73a88a0
fix(security): prevent shell injection in _expand_path via ~user path…
teknium1 Mar 23, 2026
4ff73fb
feat(config): support ${ENV_VAR} substitution in config.yaml (#2684)
teknium1 Mar 23, 2026
48b5bc6
fix(gateway): prevent stale memory overwrites by flush agent (#2670)
teknium1 Mar 23, 2026
8416bc2
chore: release v0.4.0 (v2026.3.23)
teknium1 Mar 24, 2026
6e97a3b
docs: revise v0.4.0 changelog — fix feature attribution, reorder sect…
teknium1 Mar 24, 2026
1345e93
fix: add macOS Homebrew paths to browser and terminal PATH resolution
teknium1 Mar 24, 2026
87e2626
feat(cli, agent): add tool generation callback for streaming updates
teknium1 Mar 24, 2026
4313b8a
fix(cli): ensure single closure of streaming boxes during tool genera…
teknium1 Mar 24, 2026
2f1c4fb
fix(auth): preserve 'custom' provider instead of silently remapping t…
teknium1 Mar 24, 2026
b641ee8
feat(model): /model command overhaul — Phases 2, 3, 5
teknium1 Mar 24, 2026
18cbd18
fix: remove litellm/typer/platformdirs from hermes-agent deps (supply…
teknium1 Mar 24, 2026
ce39f9c
fix(gateway): detect virtualenv path instead of hardcoding venv/ (#2797)
teknium1 Mar 24, 2026
2e52427
refactor(model): extract shared switch_model() from CLI and gateway h…
teknium1 Mar 24, 2026
a312ee7
fix(agent): ensure first delta is fired during reasoning updates
teknium1 Mar 24, 2026
773d3bb
docs: update all docs for /model command overhaul and custom provider…
teknium1 Mar 24, 2026
98b5570
fix: make browser command timeout configurable via config.yaml (#2801)
teknium1 Mar 24, 2026
2233f76
fix(tools): handle 402 insufficient credits error in vision tool (#2802)
teknium1 Mar 24, 2026
02b38b9
refactor: remove mini-swe-agent dependency — inline Docker/Modal back…
teknium1 Mar 24, 2026
ee3f3e7
docs: fix stale and incorrect documentation across 18 files
teknium1 Mar 24, 2026
677b11d
fix: reject relative cwd paths for container terminal backends
teknium1 Mar 24, 2026
e2c81c6
docs: add missing skills, CLI commands, and messaging env vars
teknium1 Mar 24, 2026
ad1bf16
chore: remove all remaining mini-swe-agent references
teknium1 Mar 24, 2026
745859b
feat: env var passthrough for skills and user config (#2807)
teknium1 Mar 24, 2026
c9b7605
chore: pin all dependency version ranges (supply chain hardening) (#2…
teknium1 Mar 24, 2026
177e432
refactor: update mini_swe_runner to use Hermes built-in backends
teknium1 Mar 24, 2026
624e4a8
chore: regenerate uv.lock with hashes, use lockfile in setup (#2812)
teknium1 Mar 24, 2026
ac5b8a4
ci: add supply chain audit workflow for PR scanning (#2816)
teknium1 Mar 24, 2026
ebcb81b
docs: document 9 previously undocumented features
teknium1 Mar 24, 2026
9718334
docs: fix api-server response storage — SQLite, not in-memory (#2819)
teknium1 Mar 24, 2026
2de7481
chore: sync with NousResearch/hermes-agent upstream (31 commits, v0.4.0)
lws803 Mar 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions .github/workflows/supply-chain-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
name: Supply Chain Audit

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
pull-requests: write
contents: read

jobs:
scan:
name: Scan PR for supply chain risks
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Scan diff for suspicious patterns
id: scan
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail

BASE="${{ github.event.pull_request.base.sha }}"
HEAD="${{ github.event.pull_request.head.sha }}"

# Get the full diff (added lines only)
DIFF=$(git diff "$BASE".."$HEAD" -- . ':!uv.lock' ':!*.lock' ':!package-lock.json' ':!yarn.lock' || true)

FINDINGS=""
CRITICAL=false

# --- .pth files (auto-execute on Python startup) ---
PTH_FILES=$(git diff --name-only "$BASE".."$HEAD" | grep '\.pth$' || true)
if [ -n "$PTH_FILES" ]; then
CRITICAL=true
FINDINGS="${FINDINGS}
### 🚨 CRITICAL: .pth file added or modified
Python \`.pth\` files in \`site-packages/\` execute automatically when the interpreter starts — no import required. This is the exact mechanism used in the [litellm supply chain attack](https://github.com/BerriAI/litellm/issues/24512).

**Files:**
\`\`\`
${PTH_FILES}
\`\`\`
"
fi

# --- base64 + exec/eval combo (the litellm attack pattern) ---
B64_EXEC_HITS=$(echo "$DIFF" | grep -n '^\+' | grep -iE 'base64\.(b64decode|decodebytes|urlsafe_b64decode)' | grep -iE 'exec\(|eval\(' | head -10 || true)
if [ -n "$B64_EXEC_HITS" ]; then
CRITICAL=true
FINDINGS="${FINDINGS}
### 🚨 CRITICAL: base64 decode + exec/eval combo
This is the exact pattern used in the [litellm supply chain attack](https://github.com/BerriAI/litellm/issues/24512) — base64-decoded strings passed to exec/eval to hide credential-stealing payloads.

**Matches:**
\`\`\`
${B64_EXEC_HITS}
\`\`\`
"
fi

# --- base64 decode/encode (alone — legitimate uses exist) ---
B64_HITS=$(echo "$DIFF" | grep -n '^\+' | grep -iE 'base64\.(b64decode|b64encode|decodebytes|encodebytes|urlsafe_b64decode)|atob\(|btoa\(|Buffer\.from\(.*base64' | head -20 || true)
if [ -n "$B64_HITS" ]; then
FINDINGS="${FINDINGS}
### ⚠️ WARNING: base64 encoding/decoding detected
Base64 has legitimate uses (images, JWT, etc.) but is also commonly used to obfuscate malicious payloads. Verify the usage is appropriate.

**Matches (first 20):**
\`\`\`
${B64_HITS}
\`\`\`
"
fi

# --- exec/eval with string arguments ---
EXEC_HITS=$(echo "$DIFF" | grep -n '^\+' | grep -E '(exec|eval)\s*\(' | grep -v '^\+\s*#' | grep -v 'test_\|mock\|assert\|# ' | head -20 || true)
if [ -n "$EXEC_HITS" ]; then
FINDINGS="${FINDINGS}
### ⚠️ WARNING: exec() or eval() usage
Dynamic code execution can hide malicious behavior, especially when combined with base64 or network fetches.

**Matches (first 20):**
\`\`\`
${EXEC_HITS}
\`\`\`
"
fi

# --- subprocess with encoded/obfuscated commands ---
PROC_HITS=$(echo "$DIFF" | grep -n '^\+' | grep -E 'subprocess\.(Popen|call|run)\s*\(' | grep -iE 'base64|decode|encode|\\x|chr\(' | head -10 || true)
if [ -n "$PROC_HITS" ]; then
CRITICAL=true
FINDINGS="${FINDINGS}
### 🚨 CRITICAL: subprocess with encoded/obfuscated command
Subprocess calls with encoded arguments are a strong indicator of payload execution.

**Matches:**
\`\`\`
${PROC_HITS}
\`\`\`
"
fi

# --- Network calls to non-standard domains ---
EXFIL_HITS=$(echo "$DIFF" | grep -n '^\+' | grep -iE 'requests\.(post|put)\(|httpx\.(post|put)\(|urllib\.request\.urlopen' | grep -v '^\+\s*#' | grep -v 'test_\|mock\|assert' | head -10 || true)
if [ -n "$EXFIL_HITS" ]; then
FINDINGS="${FINDINGS}
### ⚠️ WARNING: Outbound network calls (POST/PUT)
Outbound POST/PUT requests in new code could be data exfiltration. Verify the destination URLs are legitimate.

**Matches (first 10):**
\`\`\`
${EXFIL_HITS}
\`\`\`
"
fi

# --- setup.py / setup.cfg install hooks ---
SETUP_HITS=$(git diff --name-only "$BASE".."$HEAD" | grep -E '(setup\.py|setup\.cfg|__init__\.pth|sitecustomize\.py|usercustomize\.py)$' || true)
if [ -n "$SETUP_HITS" ]; then
FINDINGS="${FINDINGS}
### ⚠️ WARNING: Install hook files modified
These files can execute code during package installation or interpreter startup.

**Files:**
\`\`\`
${SETUP_HITS}
\`\`\`
"
fi

# --- Compile/marshal/pickle (code object injection) ---
MARSHAL_HITS=$(echo "$DIFF" | grep -n '^\+' | grep -iE 'marshal\.loads|pickle\.loads|compile\(' | grep -v '^\+\s*#' | grep -v 'test_\|re\.compile\|ast\.compile' | head -10 || true)
if [ -n "$MARSHAL_HITS" ]; then
FINDINGS="${FINDINGS}
### ⚠️ WARNING: marshal/pickle/compile usage
These can deserialize or construct executable code objects.

**Matches:**
\`\`\`
${MARSHAL_HITS}
\`\`\`
"
fi

# --- Output results ---
if [ -n "$FINDINGS" ]; then
echo "found=true" >> "$GITHUB_OUTPUT"
if [ "$CRITICAL" = true ]; then
echo "critical=true" >> "$GITHUB_OUTPUT"
else
echo "critical=false" >> "$GITHUB_OUTPUT"
fi
# Write findings to a file (multiline env vars are fragile)
echo "$FINDINGS" > /tmp/findings.md
else
echo "found=false" >> "$GITHUB_OUTPUT"
echo "critical=false" >> "$GITHUB_OUTPUT"
fi

- name: Post warning comment
if: steps.scan.outputs.found == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
SEVERITY="⚠️ Supply Chain Risk Detected"
if [ "${{ steps.scan.outputs.critical }}" = "true" ]; then
SEVERITY="🚨 CRITICAL Supply Chain Risk Detected"
fi

BODY="## ${SEVERITY}

This PR contains patterns commonly associated with supply chain attacks. This does **not** mean the PR is malicious — but these patterns require careful human review before merging.

$(cat /tmp/findings.md)

---
*Automated scan triggered by [supply-chain-audit](/.github/workflows/supply-chain-audit.yml). If this is a false positive, a maintainer can approve after manual review.*"

gh pr comment "${{ github.event.pull_request.number }}" --body "$BODY"

- name: Fail on critical findings
if: steps.scan.outputs.critical == 'true'
run: |
echo "::error::CRITICAL supply chain risk patterns detected in this PR. See the PR comment for details."
exit 1
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "mini-swe-agent"]
path = mini-swe-agent
url = https://github.com/SWE-agent/mini-swe-agent
[submodule "tinker-atropos"]
path = tinker-atropos
url = https://github.com/nousresearch/tinker-atropos
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ hermes-agent/
│ ├── tools_config.py # `hermes tools` — enable/disable tools per platform
│ ├── skills_hub.py # `/skills` slash command (search, browse, install)
│ ├── models.py # Model catalog, provider model lists
│ ├── model_switch.py # Shared /model switch pipeline (CLI + gateway)
│ └── auth.py # Provider credential resolution
├── tools/ # Tool implementations (one file per tool)
│ ├── registry.py # Central tool registry (schemas, handlers, dispatch)
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ export VIRTUAL_ENV="$(pwd)/venv"

# Install with all extras (messaging, cron, CLI menus, dev tools)
uv pip install -e ".[all,dev]"
uv pip install -e "./mini-swe-agent"
uv pip install -e "./tinker-atropos"

# Optional: RL training submodule
# git submodule update --init tinker-atropos && uv pip install -e "./tinker-atropos"

# Optional: browser tools
npm install
Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,14 @@ Quick start for contributors:
```bash
git clone https://github.com/lattice-pns/lattice-agent.git
cd hermes-agent
git submodule update --init mini-swe-agent # required terminal backend
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv venv --python 3.11
source venv/bin/activate
uv pip install -e ".[all,dev]"
uv pip install -e "./mini-swe-agent"
python -m pytest tests/ -q
```

> **RL Training (optional):** To work on the RL/Tinker-Atropos integration, also run:
>
> **RL Training (optional):** To work on the RL/Tinker-Atropos integration:
> ```bash
> git submodule update --init tinker-atropos
> uv pip install -e "./tinker-atropos"
Expand Down
Loading
Loading