Skip to content

Releases: Jovancoding/Network-AI

v5.8.9 — CodeQL #170/#173 taint-break + BOM fix + prompt cleanup

30 May 21:49

Choose a tag to compare

What's Changed

Fixed

  • CodeQL #170 — CWE-367 TOCTOU (test-phase11.ts stale-lock inject): lockPath tainted via new FileLock(lockPath) internal existsSyncopenSync(lockPath, 'w'). Fixed with fresh const staleLockPath = join(dir, '.test.lock') inside the write block.
  • CodeQL #173 — CWE-367 TOCTOU (test-phase11.ts orphan-tmp simulate): tmpPath flowed from assert(!existsSync(tmpPath)) into openSync(tmpPath, O_CREAT|O_EXCL|O_WRONLY). Fixed with fresh const orphanTmpPath inside the write block.
  • UTF-8 BOM regression: PowerShell 5.1 Set-Content writes BOM, breaking ts-node JSON parse in CI. All version-bump scripts now use System.IO.File::WriteAllText with UTF8Encoding(false).
  • claude-project-prompt.md residual hardcoded-3 refs: Pre-commit checklist and response-format template still referenced "3 sub-tasks" after v5.8.8 SkillSpector fix. Both updated to be count-agnostic.

Full Changelog: v5.8.8...v5.8.9

v5.8.8 — CodeQL TOCTOU data-flow fix + SkillSpector NLP guard

30 May 20:12

Choose a tag to compare

What's Changed

Fixed

  • CodeQL #169–#171 — CWE-367 TOCTOU data-flow break ( est-phase11.ts): openSync(lockPath/tmpPath, 'w') write blocks still triggered js/file-system-race because CodeQL traced the same variables from earlier existsSync assertions. Fixed #169–#170 by replacing existsSync(lockPath) assertions with lock.getStatus().locked (breaks the taint chain at the check side). Fixed #171 by switching the .tmp orphan-simulation write to O_CREAT|O_EXCL|O_WRONLY — atomic-create is the CodeQL-recommended pattern and correct here since the file must not already exist.
  • CodeQL #172 — unused writeFileSync import ( est-phase11.ts): All three path-based writes were replaced with fd operations in v5.8.7; the now-unused import is removed. constants and unlinkSync added in its place.
  • SkillSpector Natural-Language Policy Violations (71%) (claude-project-prompt.md): "DECOMPOSE every complex request into exactly 3 sub-tasks" was unconditional, forcing sub-agent orchestration for all requests. Added a scope guard so the decomposition protocol only applies to genuinely complex, multi-domain requests.
  • Test noise — red stderr warnings: NETWORK_AI_MINIMAL=1 now scoped to estAtomicSnapshot/ estPriorityEviction only (set on entry, deleted in inally), silencing expected disableWal warnings without affecting Feature 2's real WAL replay coverage.

Full Changelog: v5.8.7...v5.8.8

v5.8.7 — CodeQL CWE-367 fixes + SkillSpector comment fix

30 May 18:01

Choose a tag to compare

What's changed

Fixed — CodeQL alerts #165–#168

#165, #166, #167 — CWE-367 TOCTOU (test-phase11.ts)
Three writeFileSync(path, data) calls in the new testLockOwnership() and testAtomicSnapshot() test helpers were flagged as potential file-system race conditions (js/file-system-race). The path-then-write pattern has a window where the file could change between resolution and the write. Replaced all three with fd-based writes (openSyncwriteSynccloseSync), consistent with how production code in lib/locked-blackboard.ts handles the same pattern.

#168 — Unused variable staleRelease (test-phase11.ts)
The return value of lock2.release() was assigned to staleRelease but never read. Removed the assignment; the existsSync assertion that follows is the actual correctness check.

Fixed — SkillSpector Intent-Code Divergence (94% confidence)

scripts/blackboard.py--path scope comment
The header comment described --path as "accepted for environment routing" and "validated against the project root", which SkillSpector flagged because it implies full state isolation. In reality, only the main blackboard file path is derived from --path; lock files and pending-change files always resolve from the global data/ directory. The comment has been rewritten to accurately state the actual scope, preventing operator confusion in multi-project environments.


Full changelog: https://github.com/Jovancoding/Network-AI/blob/main/CHANGELOG.md

v5.8.6 — LockedBlackboard correctness fixes

30 May 17:35

Choose a tag to compare

What's changed

Fixed — lib/locked-blackboard.ts (5 correctness fixes)

#1 — Stale-lock compare-and-delete race (acquire())
Previously, two concurrent waiters that both observed a stale lock would each call forceRelease() (blind unlink). The one that lost the race would then delete the fresh lock acquired by the winner. Fixed with forceReleaseStale(expectedAcquiredAt, expectedPid): re-reads the lock file and only unlinks it if the identity still matches, so a freshly-acquired lock is never deleted.

#2 — Ownership-blind release() unlink
release() checked the in-memory lockHolder string but then unconditionally called unlinkSync. If another process had already force-released our stale lock and created its own, we would delete theirs. Fixed: release() reads the lock file after closing the fd and verifies holder + pid before unlinking.

#3 — Non-atomic snapshot write
persistToDiskInternal() and writeInitialBlackboard() wrote directly to the final blackboard path. A process crash mid-write (after WAL compaction) would leave a truncated file with no WAL to recover from. Fixed: both functions now write to ${path}.tmp then renameSync to the final path — rename is atomic on local POSIX/NTFS.

#4 — WAL/pending reconciliation — zombie validated entries
After WAL replay writes a key to the cache, loadPendingChanges() could re-add the validated pending file for the same change (crash occurred before archivePendingChange ran). Result: a zombie entry that always fails commit() with a hash-conflict. Fixed: loadPendingChanges() now cross-checks each validated entry against the cache after WAL replay and immediately archives entries whose hash already matches the committed state.

#5cleanupOldPendingChanges() priority-unaware eviction
Age-only eviction could discard high-priority proposals waiting at an approval gate. Fixed: sort by priority ASC then proposed_at ASC — lowest-priority and oldest entries are evicted first.

#11 — Silent disableWal in production
disableWal: true via constructor was completely silent. A stray NETWORK_AI_MINIMAL=1 in a production environment would silently disable crash recovery. Fixed: emits log.warn at startup when WAL is disabled outside the recognised CI/test env-var path.

Tests

Three new suites added to test-phase11.ts (55 assertions total, up from 43):

  • testLockOwnership() — 7 assertions: release-without-hold, acquire/release cycle, ownership-verified release does not delete a foreign lock, stale-lock cleanup allows fresh acquire
  • testAtomicSnapshot() — 3 assertions: no orphaned .tmp after successful write, state integrity, graceful load with a pre-existing orphaned .tmp
  • testPriorityEviction() — 2 assertions: high-priority validated change survives a pending overflow eviction cycle, surviving change commits successfully

Documentation

  • ARCHITECTURE.md — WAL durability scope clarified: protects against process crashes only (no fsync, no power-loss guarantee); atomic tmp+rename described; NFS v2/v3 explicitly unsupported (O_EXCL non-atomic over NFS); disableWal/NETWORK_AI_MINIMAL usage scope documented
  • SECURITY.md / .github/SECURITY.md — new LockedBlackboard Mutex Correctness (v5.8.6) bullet summarising all five fixes
  • Test count updated to 3,148 across 31 suites (was 3,136)

Dependencies (via Dependabot)

  • openai bumped from 6.38.0 → 6.39.0 (#104)

Full changelog: https://github.com/Jovancoding/Network-AI/blob/main/CHANGELOG.md

v5.8.5 — Audit log justification data minimisation (Ssd3)

24 May 14:27

Choose a tag to compare

Network-AI v5.8.5 — Audit log justification data minimisation (Ssd3)

Security

Three related SkillSpector Ssd3 findings (98%/99%/99%) addressed in scripts/check_permission.py.

Justification truncation before audit log write (Ssd3, 99%)
Justification strings are now truncated to 200 characters before being written to audit_log.jsonl. Content beyond that limit is dropped and a [truncated] suffix is appended. The full in-memory string is still used for score_justification() scoring. A named constant _JUSTIFICATION_MAX_LOG_LEN = 200 controls the limit.

Justification redacted from audit summary JSON output (Ssd3, 99%)
--audit-summary --json previously included raw log entries in the recent array, creating a secondary retrieval path for earlier justification text. The justification key is now stripped from each entry's details dict in JSON output via an inline _redact_entry() helper. Human-readable (non-JSON) output is unaffected.

Header comment updated (Ssd3, 98%)
The script header now describes truncation and summary redaction rather than saying justifications are logged verbatim. SKILL.md privacy.audit_log.pii_warning updated to match.

Files changed

scripts/check_permission.py, SKILL.md, CHANGELOG.md, package.json, skill.json, openapi.yaml, README.md, and all version-bearing doc files.

v5.8.4 — blackboard.py path-traversal fix (CWE-22)

24 May 11:19

Choose a tag to compare

Network-AI v5.8.4 — blackboard.py path-traversal fix (CWE-22)

Security

Arbitrary file read/write via --path in blackboard.py (Description-Behavior Mismatch, 96% confidence)

The --path CLI argument was forwarded to SharedBlackboard without any boundary check, allowing an agent or operator to read or write arbitrary local files outside the project directory. This contradicts the documented storage boundary and could be abused to overwrite sensitive project files or operate on attacker-chosen state.

Fix: Added a runtime path-traversal check immediately after argument parsing. args.path.resolve() is tested with relative_to(project_root); any path that escapes the project directory causes the script to exit with a clear error message. Symlink traversal is also blocked because resolve() is called before the comparison. The --path help text and script header comment both document this restriction. SKILL.md capabilities.filesystem updated to reflect the enforcement.

Files changed

scripts/blackboard.py, SKILL.md, CHANGELOG.md, package.json, skill.json, openapi.yaml, README.md, and all version-bearing doc files.

v5.8.3 — SKILL.md filesystem scope and script list accuracy

24 May 10:26

Choose a tag to compare

Network-AI v5.8.3 — SKILL.md filesystem scope and script list accuracy

This patch resolves 2 findings from the ClawHub SkillSpector v5.8.2 scan.

Fixed

Filesystem scope understated in capabilities manifest (Description-Behavior Mismatch, 84%)
capabilities.filesystem previously said "data/ directory only", but scripts/blackboard.py also reads and writes swarm-blackboard.md in the project root and data/pending_changes/<id>.json WAL entries. The field now enumerates every file path actually touched by the bundled Python scripts. A separate privacy.blackboard_file entry has been added for swarm-blackboard.md.

Incorrect script names in clawhub_python_scripts (Intent-Code Divergence, 90%)
The frontmatter listed token_manager.py and check_context.py — neither of which exists — and omitted validate_token.py and revoke_token.py, both of which exist in scripts/ and are referenced throughout the documentation. Corrected to the six actual scripts: blackboard.py, check_permission.py, context_manager.py, swarm_guard.py, validate_token.py, revoke_token.py.

Files changed

SKILL.md, CHANGELOG.md, package.json, skill.json, openapi.yaml, README.md, and all version-bearing doc files.

v5.8.2 — Token masking, inject-block, capabilities manifest, SkillSpector fixes

24 May 09:31

Choose a tag to compare

Network-AI v5.8.2 — Security & SkillSpector fixes

This patch resolves 8 findings from the ClawHub SkillSpector v5.8.1 scan, including two security fixes.

Security fixes

Token exposure in grant listings (Ssd3, 98% confidence)
scripts/check_permission.py --active-grants --json previously included a token_full field with the live grant token in every listing entry. Full tokens are now only shown at issuance time. All listing output uses the masked prefix (token[:16] + "...") only. The script header now includes an explicit warning that justification strings are logged verbatim to data/audit_log.jsonl and must not contain PII, credentials, or secrets.

Prompt injection not blocked in context_manager.py (Missing User Warnings, 93% confidence)
context_manager.py inject previously warned to stderr about detected prompt-injection patterns in data/project-context.json but still proceeded to emit the context block. Injection is now blocked (exit 1) when _validate_context() returns warnings. A new --force flag allows operators to override in explicitly trusted/CI environments. This prevents adversarially-crafted context entries from persisting across agent sessions.

Metadata / documentation fixes

  • SKILL.md — explicit capabilities manifest (Lp3, 90%): Added a machine-readable capabilities block under metadata.openclaw declaring filesystem, env_vars, shell_exec, and tcp_port surfaces, scope, and conditions.
  • SKILL.md — scope ambiguity resolved (Mismatch Medium/High, 92%/89%): bundle_scope and network_calls split from single prose strings into structured sub-fields: clawhub_python_scripts (local-only, zero network) vs npm_full_package (TypeScript library + CLI + optional MCP SSE server). Operators can now unambiguously determine what ClawHub ships vs what npm install delivers.
  • claude-tools.json — vague trigger conditions (Vague Triggers, 83%): Added explicit DENY conditions and scoping rules to delegate_task and spawn_parallel_agents describing when the tools must not be invoked.
  • SECURITY.md — auto-approve warning (Excessive Agency, 78%): ApprovalGate entry updated to explicitly warn that auto_approve: true is only appropriate in isolated CI/dev sandboxes and must never be used in production. Also added to SKILL.md privacy.auto_approve_warning.
  • SECURITY.md — justification field sensitivity (Ssd3, 94%): SecureAuditLogger table entry now documents that justification fields are stored verbatim and must not contain PII, credentials, or secrets.

Files changed

scripts/check_permission.py, scripts/context_manager.py, SKILL.md, claude-tools.json, SECURITY.md, .github/SECURITY.md, CHANGELOG.md, package.json, skill.json, openapi.yaml, README.md, and all version-bearing doc files.

v5.8.1 — SkillSpector accuracy fixes (bundle_scope, THREAT_MODEL, swarm_guard I/O)

24 May 08:55

Choose a tag to compare

What's changed

Fixed

  • SKILL.md frontmatter (bundle_scope / network_calls) — Fields now accurately describe both scopes: Python scripts are local-only, stdlib-only, zero network calls; the full npm package also includes TypeScript modules, a CLI, and an optional self-hosted MCP SSE server that binds a TCP port when explicitly started by the operator and requires a non-empty bearer-token secret. Resolves ClawHub SkillSpector High findings (Intent-Code Divergence, Description-Behavior Mismatch).
  • THREAT_MODEL.md — "There is no hosted service" replaced with "There is no SaaS or cloud-hosted service" with an explicit callout that the optional MCP SSE server is a network-reachable service boundary when started by the operator. Resolves SkillSpector Medium finding (Intent-Code Divergence).
  • scripts/swarm_guard.py I/O header — READS/WRITES comment updated to list all files actually written (task_tracking.json, agent_health.json, budget_tracking.json) and to document that the base data directory is data/ or data/<env>/ when NETWORK_AI_ENV / --env is set. Resolves SkillSpector Medium findings (Description-Behavior Mismatch, Intent-Code Divergence).

Full changelog: https://github.com/Jovancoding/Network-AI/blob/main/CHANGELOG.md

v5.8.0 — Doctor, Inspect, Kill Switch, --why scoring, Minimal Mode, Threat Model

23 May 17:09

Choose a tag to compare

What's changed

Added

  • network-ai doctor — Self-diagnostic command: validates data directory, env routing, audit log JSONL integrity, stale WAL entries, kill-switch state, MCP secret presence, and blackboard schema. Exits 0 all-pass / 1 any-fail. Supports --json.
  • network-ai inspect <key> — Inspect any blackboard key: value, metadata (source agent, timestamp, TTL, version), pending WAL history (--history), audit trail (--audit).
  • network-ai pause / network-ai resume — Kill switch: writes/removes a data/SYSTEM_PAUSED sentinel. doctor reports pause state.
  • --why flag on auth token — Prints full permission scoring breakdown (justification 40%, trust 30%, risk 30%, weighted total, verdict) before issuing a token.
  • --minimal global flag — Disables WAL replay and TTL sweep for fast CI/test startup. Also set via NETWORK_AI_MINIMAL=1.
  • AuthGuardian.scoreRequest() — New public read-only method returning the full scoring breakdown without issuing a token or writing to the audit log.
  • LockedBlackboard disableWal option — New disableWal?: boolean in LockedBlackboardOptions; also activated by NETWORK_AI_MINIMAL=1.

Documentation

  • THREAT_MODEL.md — Adversary profiles, trust boundaries, explicit non-goals, security controls summary.
  • DATA_LOCATIONS.md — Every file Network-AI creates at runtime: path, purpose, data classification, operator responsibilities.
  • SUPPLY_CHAIN.md — One runtime dependency, no install-time scripts, network surface, SLSA Build Level 2 / npm provenance verification.
  • SECURITY.md — Added Disclosure SLA table (acknowledgment 48h, Critical/High patch 14 days, public disclosure 7 days post-patch).

Full changelog: https://github.com/Jovancoding/Network-AI/blob/main/CHANGELOG.md