fix: Critical stability improvements from 2026-02-14 audit#19
fix: Critical stability improvements from 2026-02-14 audit#19Peyton-Spencer merged 2 commits intomainfrom
Conversation
📝 WalkthroughWalkthroughThese changes enhance memory management, transaction safety, and security. The WhatsAppChannel now explicitly manages event handler lifecycle with cleanup on reconnects. Database operations gain atomic transaction wrapping. Input validation prevents path traversal attacks, and unhandled rejection logging improves error observability. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In @.github/workflows/upstream-sync.yml:
- Around line 23-55: The workflow uses hard-coded repo names (e.g., the git
remote add lines and gh api calls referencing qwibitai/nanoclaw and
cosmin/microclaw); change them to use reusable variables or workflow inputs (for
example inputs upstream_repo and microclaw_repo or env vars REPO_UPSTREAM and
REPO_MICROCLAW) and update the commands in the steps Add upstream remotes, Check
for new upstream PRs, Check for upstream issues in microclaw, and Create summary
to interpolate those variables instead of literal names; also ensure GH_TOKEN
remains set in the steps that call gh api and propagate the new variables into
the env for those steps so the commands (git remote add, git fetch, gh api)
continue to work.
- Around line 47-55: The workflow writes multiple lines to the same summary file
using repeated unquoted redirects which triggers SC2086/SC2129; update the run
step that appends to GITHUB_STEP_SUMMARY so all echo/gh outputs are grouped
inside a single brace group (e.g. { ... }) redirected once, and quote the
variable as "$GITHUB_STEP_SUMMARY" everywhere to avoid word-splitting; locate
the block that references GITHUB_STEP_SUMMARY and replace the repeated >>
$GITHUB_STEP_SUMMARY redirects with a single redirect of the grouped commands to
"$GITHUB_STEP_SUMMARY".
In `@scripts/upstream-tracker.sh`:
- Around line 7-31: The script currently hardcodes NANOCLAW_REPO, MICROCLAW_REPO
and FORK_REPO; change it so those identifiers are read from environment
variables or command-line args (e.g., use NANOCLAW_REPO, MICROCLAW_REPO,
FORK_REPO env vars with sensible defaults) and validate they are set before
performing git/gh calls; update references to these symbols (NANOCLAW_REPO,
MICROCLAW_REPO, FORK_REPO and any echo lines that embed them) to use the env/arg
values and exit with a clear error if required vars are missing.
In `@src/channels/whatsapp.ts`:
- Around line 44-45: The reaction handler is calling the async translateJid
without awaiting it, passing a Promise to onReaction; update the reaction
handler to await translateJid(...) (the same way messageHandler does) so
onReaction receives a resolved string, and ensure any surrounding code in the
reactionHandler handles async/await (e.g., mark the handler callback async or
await before calling this.reactionHandler). Reference: translateJid, onReaction,
reactionHandler.
🧹 Nitpick comments (1)
src/group-helpers.ts (1)
39-49: PreferMAIN_GROUP_FOLDERinstead of the'main'literal.
Keeps the helper aligned if the configured main folder ever changes.♻️ Proposed refactor
-import type { RegisteredGroup } from './types.js'; +import type { RegisteredGroup } from './types.js'; +import { MAIN_GROUP_FOLDER } from './config.js'; @@ -export function findMainGroupJid(registeredGroups: Record<string, RegisteredGroup>): string | undefined { - return Object.entries(registeredGroups).find(([, g]) => g.folder === 'main')?.[0]; +export function findMainGroupJid(registeredGroups: Record<string, RegisteredGroup>): string | undefined { + return Object.entries(registeredGroups).find(([, g]) => g.folder === MAIN_GROUP_FOLDER)?.[0]; } @@ export function isMainGroup(folder: string): boolean { - return folder === 'main'; + return folder === MAIN_GROUP_FOLDER; }
| NANOCLAW_REPO="qwibitai/nanoclaw" | ||
| MICROCLAW_REPO="cosmin/microclaw" | ||
| FORK_REPO="omniaura/nanoclaw" | ||
|
|
||
| echo "🔍 Fetching upstream changes..." | ||
| git fetch upstream --quiet || echo "⚠️ Failed to fetch from upstream" | ||
| git fetch microclaw --quiet || echo "⚠️ Failed to fetch from microclaw" | ||
|
|
||
| echo "" | ||
| echo "📋 Recent Upstream PRs (qwibitai/nanoclaw):" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
|
|
||
| gh api "repos/${NANOCLAW_REPO}/pulls" --jq '.[] | select(.state=="open") | "#\(.number) - \(.title)\n Created: \(.created_at) | Comments: \(.comments)"' | head -30 | ||
|
|
||
| echo "" | ||
| echo "📋 Recent MicroClaw Issues (cosmin/microclaw):" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
|
|
||
| gh api "repos/${MICROCLAW_REPO}/issues" --jq '.[] | select(.state=="open" and (.title | contains("Upstream"))) | "#\(.number) - \(.title)\n Created: \(.created_at) | Comments: \(.comments)"' | head -20 | ||
|
|
||
| echo "" | ||
| echo "✅ Upstream tracking complete!" | ||
| echo "" | ||
| echo "💡 To create a tracking issue on ${FORK_REPO}:" | ||
| echo " gh issue create --title \"[Upstream PR #X] Feature name\" --body \"Link: https://github.com/${NANOCLAW_REPO}/pull/X\"" |
There was a problem hiding this comment.
Avoid hard-coded repo identifiers in source.
These org/repo values are user-specific; please externalize them (env/args) so the script remains generic and compliant.
🔧 Proposed fix (read from env)
-NANOCLAW_REPO="qwibitai/nanoclaw"
-MICROCLAW_REPO="cosmin/microclaw"
-FORK_REPO="omniaura/nanoclaw"
+NANOCLAW_REPO="${NANOCLAW_REPO:?Set NANOCLAW_REPO (owner/repo)}"
+MICROCLAW_REPO="${MICROCLAW_REPO:?Set MICROCLAW_REPO (owner/repo)}"
+FORK_REPO="${FORK_REPO:?Set FORK_REPO (owner/repo)}"As per coding guidelines: "NEVER edit checked-in templates or source files with user-specific content like project names, directory paths, personal preferences, or org-specific details".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| NANOCLAW_REPO="qwibitai/nanoclaw" | |
| MICROCLAW_REPO="cosmin/microclaw" | |
| FORK_REPO="omniaura/nanoclaw" | |
| echo "🔍 Fetching upstream changes..." | |
| git fetch upstream --quiet || echo "⚠️ Failed to fetch from upstream" | |
| git fetch microclaw --quiet || echo "⚠️ Failed to fetch from microclaw" | |
| echo "" | |
| echo "📋 Recent Upstream PRs (qwibitai/nanoclaw):" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| gh api "repos/${NANOCLAW_REPO}/pulls" --jq '.[] | select(.state=="open") | "#\(.number) - \(.title)\n Created: \(.created_at) | Comments: \(.comments)"' | head -30 | |
| echo "" | |
| echo "📋 Recent MicroClaw Issues (cosmin/microclaw):" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| gh api "repos/${MICROCLAW_REPO}/issues" --jq '.[] | select(.state=="open" and (.title | contains("Upstream"))) | "#\(.number) - \(.title)\n Created: \(.created_at) | Comments: \(.comments)"' | head -20 | |
| echo "" | |
| echo "✅ Upstream tracking complete!" | |
| echo "" | |
| echo "💡 To create a tracking issue on ${FORK_REPO}:" | |
| echo " gh issue create --title \"[Upstream PR #X] Feature name\" --body \"Link: https://github.com/${NANOCLAW_REPO}/pull/X\"" | |
| NANOCLAW_REPO="${NANOCLAW_REPO:?Set NANOCLAW_REPO (owner/repo)}" | |
| MICROCLAW_REPO="${MICROCLAW_REPO:?Set MICROCLAW_REPO (owner/repo)}" | |
| FORK_REPO="${FORK_REPO:?Set FORK_REPO (owner/repo)}" | |
| echo "🔍 Fetching upstream changes..." | |
| git fetch upstream --quiet || echo "⚠️ Failed to fetch from upstream" | |
| git fetch microclaw --quiet || echo "⚠️ Failed to fetch from microclaw" | |
| echo "" | |
| echo "📋 Recent Upstream PRs (qwibitai/nanoclaw):" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| gh api "repos/${NANOCLAW_REPO}/pulls" --jq '.[] | select(.state=="open") | "#\(.number) - \(.title)\n Created: \(.created_at) | Comments: \(.comments)"' | head -30 | |
| echo "" | |
| echo "📋 Recent MicroClaw Issues (cosmin/microclaw):" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| gh api "repos/${MICROCLAW_REPO}/issues" --jq '.[] | select(.state=="open" and (.title | contains("Upstream"))) | "#\(.number) - \(.title)\n Created: \(.created_at) | Comments: \(.comments)"' | head -20 | |
| echo "" | |
| echo "✅ Upstream tracking complete!" | |
| echo "" | |
| echo "💡 To create a tracking issue on ${FORK_REPO}:" | |
| echo " gh issue create --title \"[Upstream PR `#X`] Feature name\" --body \"Link: https://github.com/${NANOCLAW_REPO}/pull/X\"" |
🤖 Prompt for AI Agents
In `@scripts/upstream-tracker.sh` around lines 7 - 31, The script currently
hardcodes NANOCLAW_REPO, MICROCLAW_REPO and FORK_REPO; change it so those
identifiers are read from environment variables or command-line args (e.g., use
NANOCLAW_REPO, MICROCLAW_REPO, FORK_REPO env vars with sensible defaults) and
validate they are set before performing git/gh calls; update references to these
symbols (NANOCLAW_REPO, MICROCLAW_REPO, FORK_REPO and any echo lines that embed
them) to use the env/arg values and exit with a clear error if required vars are
missing.
nicktallen
left a comment
There was a problem hiding this comment.
✅ Approved - Critical stability fixes
Addresses 4 critical issues from stability audit.
CRITICAL Fixes:
- Unhandled promise rejection handler - prevents process crashes
- WhatsApp event listener memory leak - fixes OOM on reconnect
- Path traversal validation - security hardening
- Database transactions - prevents corrupted state
Code Quality:
• Proper event handler cleanup in WhatsApp channel
• Input validation for group folder names
• Path traversal detection with safety checks
• Transaction support for atomic DB operations
• Helper utilities for group resolution (DRY)
Impact:
• Prevents production crashes from unhandled rejections
• Fixes memory leak that causes OOM
• Hardens security against path traversal attacks
• Prevents race conditions in DB updates
These are important production stability improvements. The implementation is solid - proper cleanup, validation, and error handling throughout. Ready to merge.
omarzanji
left a comment
There was a problem hiding this comment.
Good critical fixes, but this PR contains commits from PR #16 (group-helpers.ts, upstream-sync.yml). Please rebase on main after PR #16 is merged to remove duplicate commits. The stability fixes themselves (unhandled rejection handler, WhatsApp memory leak, path traversal validation, DB transactions) are all excellent and critical.
10cc998 to
6fbde45
Compare
Implements three critical stability fixes identified in the audit:
1. **Unhandled Promise Rejection Handler (CRITICAL)**
- Add process.on('unhandledRejection') to prevent crashes
- Logs rejections instead of exiting to maintain service uptime
- Prevents complete service outage from uncaught promise errors
2. **WhatsApp Event Listener Memory Leak (CRITICAL)**
- Store event handlers and remove them before reconnection
- Prevents exponential handler accumulation on reconnects
- Fixes memory leak leading to eventual OOM crashes
3. **Group Folder Path Traversal (MEDIUM)**
- Validate folder names with regex (alphanumeric + _ -)
- Verify resolved paths stay within groups directory
- Prevents malicious group registration from writing to arbitrary paths
Impact:
- Prevents process crashes from unhandled rejections
- Fixes production memory leak in WhatsApp channel
- Hardens security against path traversal attacks
Related:
- Audit report: nanoclaw-stability-audit-2026-02-14.md
- Issues #1, #4, #16 from stability audit
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…omment Database improvements from stability audit: 1. **Transaction Support for deleteTask (MEDIUM)** - Wrap DELETE operations in explicit transaction - Ensures both child and parent deletions succeed atomically - Prevents partial deletion leaving orphaned task_run_logs 2. **SQL Injection Safety Documentation (HIGH)** - Add security comment to updateTask explaining safety assumptions - Document that field names are hardcoded (not user-controlled) - Warn future maintainers about SQL injection risks if logic changes Impact: - Prevents database corruption from partial task deletions - Documents security assumptions for future code reviewers - Hardens codebase against accidental SQL injection introduction Related: - Audit report: nanoclaw-stability-audit-2026-02-14.md - Issues #3, #12 from stability audit Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
6fbde45 to
0f32a4b
Compare
Summary
Implements 4 critical stability fixes from comprehensive audit (2026-02-14).
Changes
Files Changed
src/index.ts- Rejection handler + path validationsrc/channels/whatsapp.ts- Event listener cleanupsrc/db.ts- Transaction support + SQL safety docsAudit Findings Addressed
Testing
Full audit report:
nanoclaw-stability-audit-2026-02-14.md(25 issues identified)Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com
Summary by CodeRabbit