network-ai 5.8.4 → 5.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -564,4 +564,4 @@ Run these before declaring the integration production-ready:
564
564
 
565
565
  ---
566
566
 
567
- *Network-AI v5.8.4 · MIT License · https://github.com/Jovancoding/Network-AI*
567
+ *Network-AI v5.8.5 · MIT License · https://github.com/Jovancoding/Network-AI*
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![Website](https://img.shields.io/badge/website-network--ai.org-4b9df2?style=flat&logo=web&logoColor=white)](https://network-ai.org/)
6
6
  [![CI](https://github.com/Jovancoding/Network-AI/actions/workflows/ci.yml/badge.svg)](https://github.com/Jovancoding/Network-AI/actions/workflows/ci.yml)
7
7
  [![CodeQL](https://github.com/Jovancoding/Network-AI/actions/workflows/codeql.yml/badge.svg)](https://github.com/Jovancoding/Network-AI/actions/workflows/codeql.yml)
8
- [![Release](https://img.shields.io/badge/release-v5.8.4-blue.svg)](https://github.com/Jovancoding/Network-AI/releases)
8
+ [![Release](https://img.shields.io/badge/release-v5.8.5-blue.svg)](https://github.com/Jovancoding/Network-AI/releases)
9
9
  [![npm](https://img.shields.io/npm/dw/network-ai.svg?label=npm%20downloads)](https://www.npmjs.com/package/network-ai)
10
10
  [![Tests](https://img.shields.io/badge/tests-3136%20passing-brightgreen.svg)](#testing)
11
11
  [![Adapters](https://img.shields.io/badge/frameworks-29%20supported-blueviolet.svg)](#adapter-system)
package/SKILL.md CHANGED
@@ -30,7 +30,7 @@ metadata:
30
30
  path: data/audit_log.jsonl
31
31
  scope: local-only
32
32
  description: "Local append-only JSONL file recording operation metadata. No data leaves the machine."
33
- pii_warning: "Do not include PII, secrets, or credentials in justification fields. Log entries persist on disk. Grant tokens are masked to a short prefix in all listing outputs; full tokens appear only at issuance time."
33
+ pii_warning: "Justification strings are truncated to 200 characters before being written to the audit log. Audit summary output (--audit-summary --json) omits justification text from returned entries. Do not include PII, credentials, or secrets in justification fields the truncated text still persists on disk. Grant tokens are masked to a short prefix in all listing outputs; full tokens appear only at issuance time."
34
34
  data_directory:
35
35
  path: data/
36
36
  scope: local-only
@@ -754,7 +754,7 @@ The following findings are drawn from the **MAESTRO Agent Security Threat** fram
754
754
 
755
755
  | Control | How Network-AI addresses it |
756
756
  |---|---|
757
- | **Exact version pinning** | npm `package.json` uses exact `"version": "5.8.4"` — no semver range specifiers; `clawhub install network-ai` pins to a specific published version |
757
+ | **Exact version pinning** | npm `package.json` uses exact `"version": "5.8.5"` — no semver range specifiers; `clawhub install network-ai` pins to a specific published version |
758
758
  | **Zero transitive dependency drift** | All bundled Python scripts use Python stdlib only — `pip install` is never required; there are no third-party packages to drift, be compromised upstream, or introduce CVEs |
759
759
  | **Signed, tagged releases** | Every release is committed with a signed Git tag (`v5.7.x`); commit hash is verifiable against CHANGELOG.md; GitHub releases link tag → diff → changelog entry |
760
760
  | **Supply chain monitoring** | npm package continuously scored by Socket.dev (score A); any new dependency or permission change triggers an alert |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "network-ai",
3
- "version": "5.8.4",
3
+ "version": "5.8.5",
4
4
  "description": "AI agent orchestration framework for TypeScript/Node.js - 29 adapters (LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, OpenClaw, A2A, Codex, MiniMax, NemoClaw, APS, Copilot, LangGraph, Anthropic Computer Use, OpenAI Agents SDK, Vertex AI, Pydantic AI, Browser Agent, Hermes, Orchestrator, RLM + streaming variants). Built-in CLI, security, swarm intelligence, real-time streaming, and agentic workflow patterns.",
5
5
  "homepage": "https://network-ai.org",
6
6
  "main": "dist/index.js",
@@ -8,11 +8,13 @@
8
8
  # Imports used: argparse, json, re, sys, uuid, hmac, hashlib, datetime, pathlib, typing
9
9
  # No imports of: requests, socket, subprocess, urllib, http, ssl, ftplib, smtplib
10
10
  #
11
- # SECURITY: Justification strings supplied via --justification are logged verbatim
12
- # to data/audit_log.jsonl. Do NOT include PII, credentials, secret names, API keys,
13
- # or other sensitive business data in justification fields. Treat justifications as
14
- # permanently visible log entries. Grant tokens are only shown at issuance time;
15
- # listing commands (--active-grants) always mask tokens to a short prefix.
11
+ # SECURITY: Justification strings supplied via --justification are truncated to
12
+ # _JUSTIFICATION_MAX_LOG_LEN characters before being written to audit_log.jsonl.
13
+ # Do NOT include PII, credentials, secret names, API keys, or sensitive business
14
+ # data in justification fields. Audit summary output (--audit-summary --json)
15
+ # omits justification text entirely from returned entries. Grant tokens are only
16
+ # shown at issuance time; listing commands (--active-grants) always mask tokens
17
+ # to a short prefix.
16
18
  """
17
19
  AuthGuardian Permission Checker
18
20
 
@@ -88,6 +90,11 @@ DEFAULT_TRUST_LEVELS = {
88
90
  # receives a reduced trust score (0.3) and triggers an advisory warning.
89
91
  KNOWN_AGENTS: set[str] = set(DEFAULT_TRUST_LEVELS.keys())
90
92
 
93
+ # Maximum characters of a justification string stored in the audit log.
94
+ # Content beyond this limit is dropped before writing to prevent unbounded
95
+ # sensitive-data retention (SkillSpector Ssd3).
96
+ _JUSTIFICATION_MAX_LOG_LEN: int = 200
97
+
91
98
  # Resource types that require --confirm-high-risk before a grant is issued
92
99
  HIGH_RISK_RESOURCES: set[str] = {"PAYMENTS", "DATABASE"}
93
100
 
@@ -369,11 +376,17 @@ def evaluate_permission(
369
376
  # Warn if agent_id is not in the pre-registered known-agents list
370
377
  unknown_agent = agent_id not in KNOWN_AGENTS
371
378
 
372
- # Log the request
379
+ # Log the request — justification is truncated before writing to limit
380
+ # sensitive-data retention in audit_log.jsonl.
381
+ _justification_log = (
382
+ justification[:_JUSTIFICATION_MAX_LOG_LEN] + " [truncated]"
383
+ if len(justification) > _JUSTIFICATION_MAX_LOG_LEN
384
+ else justification
385
+ )
373
386
  log_audit("permission_request", {
374
387
  "agent_id": agent_id,
375
388
  "resource_type": resource_type,
376
- "justification": justification,
389
+ "justification": _justification_log,
377
390
  "scope": scope,
378
391
  "unknown_agent": unknown_agent,
379
392
  })
@@ -675,6 +688,13 @@ def audit_summary(last_n: int = 20, as_json: bool = False) -> int:
675
688
  last_ts = entries[-1].get("timestamp", "unknown")
676
689
 
677
690
  if as_json:
691
+ # Omit justification text from summary output to avoid re-exposing
692
+ # sensitive content that was logged earlier (SkillSpector Ssd3).
693
+ def _redact_entry(e: dict[str, Any]) -> dict[str, Any]:
694
+ if "details" not in e or "justification" not in e["details"]:
695
+ return e
696
+ return {**e, "details": {k: v for k, v in e["details"].items() if k != "justification"}}
697
+
678
698
  output: dict[str, Any] = {
679
699
  "total_entries": len(entries),
680
700
  "total_requests": total_requests,
@@ -683,7 +703,7 @@ def audit_summary(last_n: int = 20, as_json: bool = False) -> int:
683
703
  "time_range": {"first": first_ts, "last": last_ts},
684
704
  "by_agent": by_agent,
685
705
  "by_resource": by_resource,
686
- "recent": recent[-last_n:],
706
+ "recent": [_redact_entry(e) for e in recent[-last_n:]],
687
707
  }
688
708
  print(json.dumps(output, indent=2))
689
709
  else: