clawmoat 0.7.0 → 1.0.0
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.
- package/.dockerignore +9 -0
- package/CHANGELOG.md +18 -0
- package/CONTRIBUTING.md +4 -2
- package/DEMO.md +87 -0
- package/Dockerfile +5 -18
- package/README.md +294 -8
- package/SECURITY.md +58 -10
- package/THREAT_MODEL.md +129 -0
- package/agent/README.md +131 -0
- package/agent/index.js +471 -0
- package/agent/install-service.sh +94 -0
- package/agent/openclaw-hook.js +453 -0
- package/agent/provider-setup.js +649 -0
- package/agent/setup.js +274 -0
- package/assets/BADGE-USAGE.md +20 -0
- package/assets/clawmoat-badge.svg +21 -0
- package/bin/clawmoat.js +468 -111
- package/docs/affiliates/dashboard.html +124 -0
- package/docs/affiliates/index.html +236 -0
- package/docs/agent-install.html +183 -0
- package/docs/ai-agent-security-scanner.html +10 -6
- package/docs/badge/index.html +149 -0
- package/docs/badge/scanning.svg +23 -0
- package/docs/blog/386-malicious-skills.html +262 -0
- package/docs/blog/40000-exposed-openclaw-instances.html +201 -0
- package/docs/blog/agent-trust-protocol.html +198 -0
- package/docs/blog/ai-agent-earns-commissions.html +230 -0
- package/docs/blog/bugmageddon-agent-firewall.html +174 -0
- package/docs/blog/calculator-math.html +180 -0
- package/docs/blog/clawmoat-vs-llamafirewall-nemo-guardrails.html +229 -0
- package/docs/blog/host-guardian-launch.html +18 -8
- package/docs/blog/ibm-experts-agent-runtime-protection.html +247 -0
- package/docs/blog/index.html +211 -9
- package/docs/blog/langchain-security-tutorial.html +18 -8
- package/docs/blog/mcp-30-cves-security-crisis.html +286 -0
- package/docs/blog/meta-researcher-rogue-agent.html +201 -0
- package/docs/blog/microsoft-openclaw-workstation-security.html +235 -0
- package/docs/blog/nist-ai-agent-standards-clawmoat.html +377 -0
- package/docs/blog/oasis-websocket-hijack.html +212 -0
- package/docs/blog/ollama-openclaw-security.html +160 -0
- package/docs/blog/openclaw-enterprise-readiness-claw10.html +199 -0
- package/docs/blog/openclaw-security-reckoning-2026.html +368 -0
- package/docs/blog/owasp-agentic-ai-top10.html +18 -8
- package/docs/blog/securing-ai-agents.html +18 -8
- package/docs/blog/supply-chain-agents.html +18 -8
- package/docs/business/index.html +525 -0
- package/docs/business/install.html +261 -0
- package/docs/checklist.html +174 -0
- package/docs/compare/index.html +122 -0
- package/docs/compare/lakera/index.html +62 -0
- package/docs/compare/llm-guard/index.html +49 -0
- package/docs/compare/snyk-agent-scan/index.html +63 -0
- package/docs/compare.html +10 -6
- package/docs/dashboard/index.html +520 -0
- package/docs/finance/index.html +220 -0
- package/docs/guides/business-deployment.html +770 -0
- package/docs/hall-of-fame.html +174 -0
- package/docs/index.html +447 -154
- package/docs/install.sh +557 -0
- package/docs/integrations/langchain.html +14 -6
- package/docs/integrations/openai.html +14 -6
- package/docs/integrations/openclaw.html +55 -7
- package/docs/plans/2026-03-26-threat-intel-api.md +255 -0
- package/docs/plans/2026-04-14-bugmageddon-marketing-pack.md +329 -0
- package/docs/plans/2026-04-14-clawmoat-v1-bugmageddon.md +248 -0
- package/docs/plans/2026-04-14-v1-release-update.md +91 -0
- package/docs/plans/2026-04-19-supabase-audit.md +68 -0
- package/docs/plans/2026-05-12-sales-push.md +303 -0
- package/docs/playground/index.html +893 -0
- package/docs/playground.html +4 -7
- package/docs/privacy-policy/index.html +122 -0
- package/docs/rfcs/defense-in-depth.md +467 -0
- package/docs/scan/index.html +358 -0
- package/docs/services/case-study.html +255 -0
- package/docs/services/downloads/install-openclaw.bat +45 -0
- package/docs/services/downloads/install-openclaw.command +38 -0
- package/docs/services/downloads/install-openclaw.sh +38 -0
- package/docs/services/get-started.html +165 -0
- package/docs/services/index.html +598 -0
- package/docs/services/multi-agent-security.html +284 -0
- package/docs/services/one-pager.html +99 -0
- package/docs/services/pitch-deck.html +229 -0
- package/docs/services/roi-calculator.html +258 -0
- package/docs/sitemap.xml +192 -2
- package/docs/support/index.html +135 -0
- package/docs/templates/customer-service/HEARTBEAT.md +61 -0
- package/docs/templates/customer-service/MEMORY.md +89 -0
- package/docs/templates/customer-service/SOUL.md +41 -0
- package/docs/templates/customer-service/USER.md +56 -0
- package/docs/templates/executive/HEARTBEAT.md +86 -0
- package/docs/templates/executive/MEMORY.md +92 -0
- package/docs/templates/executive/SOUL.md +44 -0
- package/docs/templates/executive/USER.md +62 -0
- package/docs/templates/finance/HEARTBEAT.md +58 -0
- package/docs/templates/finance/MEMORY.md +87 -0
- package/docs/templates/finance/SOUL.md +38 -0
- package/docs/templates/finance/USER.md +53 -0
- package/docs/templates/index.html +115 -0
- package/docs/templates/operations/HEARTBEAT.md +63 -0
- package/docs/templates/operations/MEMORY.md +68 -0
- package/docs/templates/operations/SOUL.md +38 -0
- package/docs/templates/operations/USER.md +49 -0
- package/docs/templates/sales/HEARTBEAT.md +55 -0
- package/docs/templates/sales/MEMORY.md +89 -0
- package/docs/templates/sales/SOUL.md +34 -0
- package/docs/templates/sales/USER.md +54 -0
- package/docs/terms-of-service/index.html +122 -0
- package/eslint.config.js +32 -0
- package/evals/README.md +29 -0
- package/evals/cases.json +390 -0
- package/evals/results.md +68 -0
- package/evals/run.js +180 -0
- package/examples/basic-usage.js +38 -0
- package/examples/demo-attack/demo.js +186 -0
- package/examples/python-quickstart/README.md +54 -0
- package/examples/python-quickstart/clawmoat_client.py +167 -0
- package/examples/video-demo/README.md +14 -0
- package/examples/video-demo/scene-a-normal.js +29 -0
- package/examples/video-demo/scene-b-attack-arrives.js +31 -0
- package/examples/video-demo/scene-c-hijack.js +44 -0
- package/examples/video-demo/scene-d-clawmoat.js +46 -0
- package/integrations/crewai/README.md +32 -0
- package/integrations/crewai/clawmoat_crewai/__init__.py +17 -0
- package/integrations/crewai/clawmoat_crewai/guard.py +103 -0
- package/integrations/crewai/pyproject.toml +21 -0
- package/integrations/langchain/README.md +91 -0
- package/integrations/langchain/clawmoat_langchain/__init__.py +17 -0
- package/integrations/langchain/clawmoat_langchain/callback.py +489 -0
- package/integrations/langchain/pyproject.toml +32 -0
- package/integrations/litellm/README.md +324 -0
- package/integrations/litellm/clawmoat_litellm/__init__.py +21 -0
- package/integrations/litellm/clawmoat_litellm/callback.py +329 -0
- package/integrations/litellm/clawmoat_litellm/proxy_middleware.py +224 -0
- package/integrations/litellm/pyproject.toml +74 -0
- package/integrations/openai-agents/README.md +392 -0
- package/integrations/openai-agents/clawmoat_openai_agents/__init__.py +20 -0
- package/integrations/openai-agents/clawmoat_openai_agents/guardrail.py +431 -0
- package/integrations/openai-agents/clawmoat_openai_agents/middleware.py +311 -0
- package/integrations/openai-agents/pyproject.toml +76 -0
- package/package.json +6 -5
- package/plugins/openclaw-adapter/PHASE1.md +439 -0
- package/plugins/openclaw-adapter/README.md +103 -0
- package/plugins/openclaw-adapter/SPEC.md +1644 -0
- package/plugins/openclaw-adapter/package.json +31 -0
- package/plugins/openclaw-adapter/src/index.test.ts +226 -0
- package/plugins/openclaw-adapter/src/index.ts +140 -0
- package/plugins/openclaw-adapter/tsconfig.json +14 -0
- package/server/data/threats.json +290 -0
- package/server/index.js +224 -10
- package/src/adapters/express.js +161 -0
- package/src/adapters/index.js +92 -0
- package/src/adapters/langchain.js +185 -0
- package/src/approval/index.js +456 -0
- package/src/ban-scanner.js +200 -0
- package/src/boundary-scanner.js +296 -0
- package/src/ci-scanner.js +279 -0
- package/src/code-scanner.js +245 -0
- package/src/enforce.js +166 -0
- package/src/finance/index.js +585 -0
- package/src/finance/mcp-firewall.js +486 -0
- package/src/formatters/json.js +80 -0
- package/src/formatters/sarif.js +388 -0
- package/src/guardian/alerts.js +34 -3
- package/src/guardian/gateway-monitor.js +590 -0
- package/src/guardian/index.js +41 -2
- package/src/index.js +105 -0
- package/src/integrations/agentmesh.js +501 -0
- package/src/language-detector.js +201 -0
- package/src/mcp-scanner.js +253 -0
- package/src/multimodal/index.js +579 -0
- package/src/obfuscation-scanner.js +457 -0
- package/src/policy-engine.js +402 -0
- package/src/scanners/dependency-attacks.js +128 -0
- package/src/scanners/prompt-injection.js +18 -0
- package/src/scanners/supply-chain.js +14 -0
- package/src/templates/default-config.yml +90 -0
- package/src/vuln-ops/exploitability.js +46 -0
- package/src/watch/live-monitor.js +720 -0
package/docs/install.sh
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ============================================================================
|
|
3
|
+
# ClawMoat Installer — Enterprise-Grade AI Agent Security
|
|
4
|
+
# https://clawmoat.com/business/install.html
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# curl -fsSL https://clawmoat.com/install.sh | bash
|
|
8
|
+
# curl -fsSL https://clawmoat.com/install.sh | bash -s -- --enterprise
|
|
9
|
+
#
|
|
10
|
+
# ⚠️ This script runs locally — no data is sent anywhere.
|
|
11
|
+
# It installs ClawMoat via npm and generates a local config.
|
|
12
|
+
# Source: https://github.com/ClawMoat/clawmoat
|
|
13
|
+
#
|
|
14
|
+
# Exit codes: 0 = success, 1 = error
|
|
15
|
+
# ============================================================================
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
# ─── Colors & Formatting ────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
RED='\033[0;31m'
|
|
22
|
+
GREEN='\033[0;32m'
|
|
23
|
+
YELLOW='\033[1;33m'
|
|
24
|
+
BLUE='\033[0;34m'
|
|
25
|
+
CYAN='\033[0;36m'
|
|
26
|
+
BOLD='\033[1m'
|
|
27
|
+
DIM='\033[2m'
|
|
28
|
+
RESET='\033[0m'
|
|
29
|
+
|
|
30
|
+
# Disable colors if not a terminal
|
|
31
|
+
if [ ! -t 1 ]; then
|
|
32
|
+
RED='' GREEN='' YELLOW='' BLUE='' CYAN='' BOLD='' DIM='' RESET=''
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
info() { echo -e "${BLUE}ℹ${RESET} $*"; }
|
|
38
|
+
success() { echo -e "${GREEN}✅${RESET} $*"; }
|
|
39
|
+
warn() { echo -e "${YELLOW}⚠️${RESET} $*"; }
|
|
40
|
+
error() { echo -e "${RED}❌${RESET} $*" >&2; }
|
|
41
|
+
step() { echo -e "\n${BOLD}${CYAN}▸ $*${RESET}"; }
|
|
42
|
+
divider() { echo -e "${DIM}────────────────────────────────────────────────────${RESET}"; }
|
|
43
|
+
|
|
44
|
+
# ─── Flags ───────────────────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
ENTERPRISE=false
|
|
47
|
+
DRY_RUN=false
|
|
48
|
+
CLAWMOAT_DIR="$HOME/.clawmoat"
|
|
49
|
+
CONFIG_FILE="$CLAWMOAT_DIR/config.json"
|
|
50
|
+
|
|
51
|
+
for arg in "$@"; do
|
|
52
|
+
case "$arg" in
|
|
53
|
+
--enterprise) ENTERPRISE=true ;;
|
|
54
|
+
--dry-run) DRY_RUN=true ;;
|
|
55
|
+
--help|-h)
|
|
56
|
+
echo "ClawMoat Installer"
|
|
57
|
+
echo ""
|
|
58
|
+
echo "Usage: bash install.sh [OPTIONS]"
|
|
59
|
+
echo ""
|
|
60
|
+
echo "Options:"
|
|
61
|
+
echo " --enterprise Enable FinanceGuard, McpFirewall, SOX templates"
|
|
62
|
+
echo " --dry-run Show what would be done without making changes"
|
|
63
|
+
echo " --help Show this help message"
|
|
64
|
+
exit 0
|
|
65
|
+
;;
|
|
66
|
+
*)
|
|
67
|
+
error "Unknown option: $arg"
|
|
68
|
+
exit 1
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
# ─── Banner ──────────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
echo ""
|
|
76
|
+
echo -e "${BOLD}🏰 ClawMoat Installer${RESET}"
|
|
77
|
+
echo -e "${DIM} Enterprise-Grade AI Agent Security${RESET}"
|
|
78
|
+
divider
|
|
79
|
+
echo ""
|
|
80
|
+
echo -e "${DIM}⚠️ This script runs locally — no data is sent anywhere.${RESET}"
|
|
81
|
+
echo -e "${DIM} All configuration stays on your machine at ~/.clawmoat/${RESET}"
|
|
82
|
+
echo ""
|
|
83
|
+
|
|
84
|
+
if $ENTERPRISE; then
|
|
85
|
+
info "Enterprise mode enabled"
|
|
86
|
+
fi
|
|
87
|
+
if $DRY_RUN; then
|
|
88
|
+
warn "Dry run — no changes will be made"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# ─── Step 1: Detect OS ──────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
step "Detecting operating system..."
|
|
94
|
+
|
|
95
|
+
OS="unknown"
|
|
96
|
+
ARCH="$(uname -m)"
|
|
97
|
+
|
|
98
|
+
case "$(uname -s)" in
|
|
99
|
+
Linux*)
|
|
100
|
+
if grep -qiE "microsoft|wsl" /proc/version 2>/dev/null; then
|
|
101
|
+
OS="wsl"
|
|
102
|
+
info "Detected: WSL (Windows Subsystem for Linux) — $ARCH"
|
|
103
|
+
else
|
|
104
|
+
OS="linux"
|
|
105
|
+
info "Detected: Linux — $ARCH"
|
|
106
|
+
fi
|
|
107
|
+
;;
|
|
108
|
+
Darwin*)
|
|
109
|
+
OS="macos"
|
|
110
|
+
info "Detected: macOS — $ARCH"
|
|
111
|
+
;;
|
|
112
|
+
*)
|
|
113
|
+
error "Unsupported operating system: $(uname -s)"
|
|
114
|
+
error "ClawMoat supports Linux, macOS, and WSL."
|
|
115
|
+
exit 1
|
|
116
|
+
;;
|
|
117
|
+
esac
|
|
118
|
+
|
|
119
|
+
# ─── Step 2: Check Node.js ──────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
step "Checking Node.js..."
|
|
122
|
+
|
|
123
|
+
NODE_OK=false
|
|
124
|
+
MIN_NODE_MAJOR=18
|
|
125
|
+
|
|
126
|
+
check_node_version() {
|
|
127
|
+
if command -v node &>/dev/null; then
|
|
128
|
+
NODE_VERSION="$(node -v 2>/dev/null | sed 's/^v//')"
|
|
129
|
+
NODE_MAJOR="${NODE_VERSION%%.*}"
|
|
130
|
+
if [ "$NODE_MAJOR" -ge "$MIN_NODE_MAJOR" ] 2>/dev/null; then
|
|
131
|
+
return 0
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
134
|
+
return 1
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if check_node_version; then
|
|
138
|
+
NODE_OK=true
|
|
139
|
+
success "Node.js v$NODE_VERSION found"
|
|
140
|
+
else
|
|
141
|
+
warn "Node.js v${MIN_NODE_MAJOR}+ is required but not found."
|
|
142
|
+
echo ""
|
|
143
|
+
|
|
144
|
+
if $DRY_RUN; then
|
|
145
|
+
info "Would install Node.js via nvm"
|
|
146
|
+
else
|
|
147
|
+
echo -e " ${BOLD}Install Node.js via nvm?${RESET} (recommended)"
|
|
148
|
+
echo -e " This installs nvm and Node.js LTS in your home directory."
|
|
149
|
+
echo ""
|
|
150
|
+
read -rp " Install? [Y/n] " INSTALL_NODE
|
|
151
|
+
INSTALL_NODE="${INSTALL_NODE:-Y}"
|
|
152
|
+
|
|
153
|
+
if [[ "$INSTALL_NODE" =~ ^[Yy]$ ]]; then
|
|
154
|
+
step "Installing nvm..."
|
|
155
|
+
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
|
|
156
|
+
|
|
157
|
+
if [ ! -d "$NVM_DIR" ]; then
|
|
158
|
+
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Source nvm
|
|
162
|
+
# shellcheck source=/dev/null
|
|
163
|
+
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
|
164
|
+
|
|
165
|
+
info "Installing Node.js LTS..."
|
|
166
|
+
nvm install --lts
|
|
167
|
+
nvm use --lts
|
|
168
|
+
|
|
169
|
+
if check_node_version; then
|
|
170
|
+
NODE_OK=true
|
|
171
|
+
success "Node.js v$NODE_VERSION installed"
|
|
172
|
+
else
|
|
173
|
+
error "Node.js installation failed. Please install manually:"
|
|
174
|
+
echo " https://nodejs.org/"
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
else
|
|
178
|
+
error "Node.js v${MIN_NODE_MAJOR}+ is required. Install it from https://nodejs.org/"
|
|
179
|
+
exit 1
|
|
180
|
+
fi
|
|
181
|
+
fi
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# ─── Step 3: Install ClawMoat ───────────────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
step "Installing ClawMoat..."
|
|
187
|
+
|
|
188
|
+
if $DRY_RUN; then
|
|
189
|
+
info "Would run: npm install -g clawmoat"
|
|
190
|
+
else
|
|
191
|
+
if command -v clawmoat &>/dev/null; then
|
|
192
|
+
CURRENT_VERSION="$(clawmoat --version 2>/dev/null || echo 'unknown')"
|
|
193
|
+
info "ClawMoat already installed (v$CURRENT_VERSION). Updating..."
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
npm install -g clawmoat 2>&1 | tail -3
|
|
197
|
+
success "ClawMoat installed: $(clawmoat --version 2>/dev/null || echo 'latest')"
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# ─── Step 4: Create directory structure ──────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
step "Setting up ~/.clawmoat/..."
|
|
203
|
+
|
|
204
|
+
DIRS=(
|
|
205
|
+
"$CLAWMOAT_DIR"
|
|
206
|
+
"$CLAWMOAT_DIR/audit"
|
|
207
|
+
"$CLAWMOAT_DIR/reports"
|
|
208
|
+
"$CLAWMOAT_DIR/templates"
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
if $ENTERPRISE; then
|
|
212
|
+
DIRS+=(
|
|
213
|
+
"$CLAWMOAT_DIR/finance"
|
|
214
|
+
"$CLAWMOAT_DIR/mcp-firewall"
|
|
215
|
+
"$CLAWMOAT_DIR/sox"
|
|
216
|
+
)
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
if $DRY_RUN; then
|
|
220
|
+
for d in "${DIRS[@]}"; do
|
|
221
|
+
info "Would create: $d"
|
|
222
|
+
done
|
|
223
|
+
else
|
|
224
|
+
for d in "${DIRS[@]}"; do
|
|
225
|
+
mkdir -p "$d"
|
|
226
|
+
done
|
|
227
|
+
success "Directory structure created"
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
# ─── Step 5: Generate hardened config ────────────────────────────────────────
|
|
231
|
+
|
|
232
|
+
step "Generating hardened security configuration..."
|
|
233
|
+
|
|
234
|
+
TIMESTAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
235
|
+
|
|
236
|
+
# Build the enterprise section if needed
|
|
237
|
+
ENTERPRISE_JSON=""
|
|
238
|
+
if $ENTERPRISE; then
|
|
239
|
+
ENTERPRISE_JSON=',
|
|
240
|
+
"enterprise": {
|
|
241
|
+
"financeGuard": {
|
|
242
|
+
"enabled": true,
|
|
243
|
+
"mode": "monitor",
|
|
244
|
+
"alertOnHighValue": true,
|
|
245
|
+
"thresholdUsd": 1000
|
|
246
|
+
},
|
|
247
|
+
"mcpFirewall": {
|
|
248
|
+
"enabled": true,
|
|
249
|
+
"mode": "read-only",
|
|
250
|
+
"allowedTools": [],
|
|
251
|
+
"blockedServers": [],
|
|
252
|
+
"logAllCalls": true
|
|
253
|
+
},
|
|
254
|
+
"soxCompliance": {
|
|
255
|
+
"enabled": true,
|
|
256
|
+
"auditRetentionDays": 2555,
|
|
257
|
+
"templateDir": "~/.clawmoat/sox",
|
|
258
|
+
"controlsFile": "~/.clawmoat/sox/controls.json",
|
|
259
|
+
"segregationOfDuties": true
|
|
260
|
+
}
|
|
261
|
+
}'
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
CONFIG_CONTENT='{
|
|
265
|
+
"_clawmoat": {
|
|
266
|
+
"version": "1.0.0",
|
|
267
|
+
"generatedAt": "'"$TIMESTAMP"'",
|
|
268
|
+
"generatedBy": "install.sh",
|
|
269
|
+
"os": "'"$OS"'"
|
|
270
|
+
},
|
|
271
|
+
"permissions": {
|
|
272
|
+
"tier": "worker",
|
|
273
|
+
"note": "Worker tier: read workspace, write workspace, no system changes. Upgrade to standard/full in config if needed."
|
|
274
|
+
},
|
|
275
|
+
"forbiddenZones": [
|
|
276
|
+
{ "path": "~/.ssh", "label": "SSH keys", "severity": "critical" },
|
|
277
|
+
{ "path": "~/.gnupg", "label": "GPG keys", "severity": "critical" },
|
|
278
|
+
{ "path": "~/.aws", "label": "AWS credentials", "severity": "critical" },
|
|
279
|
+
{ "path": "~/.gcloud", "label": "Google Cloud creds", "severity": "critical" },
|
|
280
|
+
{ "path": "~/.azure", "label": "Azure credentials", "severity": "critical" },
|
|
281
|
+
{ "path": "~/.kube", "label": "Kubernetes config", "severity": "critical" },
|
|
282
|
+
{ "path": "~/.docker", "label": "Docker credentials", "severity": "high" },
|
|
283
|
+
{ "path": "~/.npmrc", "label": "npm credentials", "severity": "high" },
|
|
284
|
+
{ "path": "~/.pypirc", "label": "PyPI credentials", "severity": "high" },
|
|
285
|
+
{ "path": "~/.netrc", "label": "Network credentials", "severity": "critical" },
|
|
286
|
+
{ "path": "~/.git-credentials", "label": "Git credentials", "severity": "critical" },
|
|
287
|
+
{ "path": "~/.config/gcloud", "label": "Google Cloud config", "severity": "high" },
|
|
288
|
+
{ "path": "~/.config/gh", "label": "GitHub CLI tokens", "severity": "high" },
|
|
289
|
+
{ "path": "~/.password-store", "label": "Password store", "severity": "critical" },
|
|
290
|
+
{ "path": "~/.1password", "label": "1Password data", "severity": "critical" },
|
|
291
|
+
{ "path": "/etc/shadow", "label": "System passwords", "severity": "critical" },
|
|
292
|
+
{ "path": "/etc/sudoers", "label": "Sudo configuration", "severity": "critical" }
|
|
293
|
+
],
|
|
294
|
+
"forbiddenPatterns": [
|
|
295
|
+
{ "pattern": "Cookies|Login Data|Web Data", "label": "Browser credentials", "severity": "critical" },
|
|
296
|
+
{ "pattern": ".keychain|.keychain-db", "label": "macOS Keychain", "severity": "critical" },
|
|
297
|
+
{ "pattern": "wallet.dat|seed.txt|mnemonic", "label": "Crypto wallet", "severity": "critical" },
|
|
298
|
+
{ "pattern": ".kdbx|KeePass", "label": "KeePass database", "severity": "critical" },
|
|
299
|
+
{ "pattern": ".env|.env.local|.env.prod", "label": "Environment secrets", "severity": "high" }
|
|
300
|
+
],
|
|
301
|
+
"network": {
|
|
302
|
+
"egressLogging": true,
|
|
303
|
+
"logFile": "~/.clawmoat/audit/network.log",
|
|
304
|
+
"allowedDomains": [],
|
|
305
|
+
"blockedDomains": [],
|
|
306
|
+
"alertOnUnknownEgress": true
|
|
307
|
+
},
|
|
308
|
+
"secretScanning": {
|
|
309
|
+
"enabled": true,
|
|
310
|
+
"scanOnFileAccess": true,
|
|
311
|
+
"patterns": ["AWS_ACCESS_KEY", "GITHUB_TOKEN", "PRIVATE_KEY", "password", "secret", "api_key"],
|
|
312
|
+
"alertOnDetection": true
|
|
313
|
+
},
|
|
314
|
+
"audit": {
|
|
315
|
+
"enabled": true,
|
|
316
|
+
"logDir": "~/.clawmoat/audit",
|
|
317
|
+
"retentionDays": 90,
|
|
318
|
+
"logFileAccess": true,
|
|
319
|
+
"logCommandExecution": true,
|
|
320
|
+
"logNetworkRequests": true,
|
|
321
|
+
"tamperProtection": true
|
|
322
|
+
},
|
|
323
|
+
"alerts": {
|
|
324
|
+
"webhookUrl": "",
|
|
325
|
+
"emailTo": "",
|
|
326
|
+
"slackChannel": "",
|
|
327
|
+
"note": "Configure at least one alert channel. Webhook receives JSON POST on security events."
|
|
328
|
+
}'"$ENTERPRISE_JSON"'
|
|
329
|
+
}'
|
|
330
|
+
|
|
331
|
+
if $DRY_RUN; then
|
|
332
|
+
info "Would write config to: $CONFIG_FILE"
|
|
333
|
+
echo -e "${DIM}$CONFIG_CONTENT${RESET}" | head -20
|
|
334
|
+
echo -e "${DIM} ... (truncated)${RESET}"
|
|
335
|
+
else
|
|
336
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
337
|
+
BACKUP="$CONFIG_FILE.backup.$(date +%s)"
|
|
338
|
+
cp "$CONFIG_FILE" "$BACKUP"
|
|
339
|
+
warn "Existing config backed up to: $BACKUP"
|
|
340
|
+
fi
|
|
341
|
+
|
|
342
|
+
echo "$CONFIG_CONTENT" > "$CONFIG_FILE"
|
|
343
|
+
chmod 600 "$CONFIG_FILE"
|
|
344
|
+
success "Config written to $CONFIG_FILE (mode 600)"
|
|
345
|
+
fi
|
|
346
|
+
|
|
347
|
+
# ─── Step 5b: Enterprise templates ──────────────────────────────────────────
|
|
348
|
+
|
|
349
|
+
if $ENTERPRISE && ! $DRY_RUN; then
|
|
350
|
+
step "Setting up enterprise templates..."
|
|
351
|
+
|
|
352
|
+
# SOX audit control template
|
|
353
|
+
cat > "$CLAWMOAT_DIR/sox/controls.json" << 'SOXEOF'
|
|
354
|
+
{
|
|
355
|
+
"framework": "SOX-AI-Agent",
|
|
356
|
+
"version": "1.0",
|
|
357
|
+
"controls": [
|
|
358
|
+
{
|
|
359
|
+
"id": "AC-01",
|
|
360
|
+
"name": "Agent Permission Tiers",
|
|
361
|
+
"description": "AI agents operate under least-privilege permission tiers",
|
|
362
|
+
"frequency": "continuous",
|
|
363
|
+
"evidence": "~/.clawmoat/audit/*.log"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"id": "AC-02",
|
|
367
|
+
"name": "Credential Zone Protection",
|
|
368
|
+
"description": "Forbidden zones prevent agent access to credentials",
|
|
369
|
+
"frequency": "continuous",
|
|
370
|
+
"evidence": "~/.clawmoat/config.json → forbiddenZones"
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"id": "AC-03",
|
|
374
|
+
"name": "Secret Detection",
|
|
375
|
+
"description": "Real-time scanning for leaked secrets in agent output",
|
|
376
|
+
"frequency": "continuous",
|
|
377
|
+
"evidence": "~/.clawmoat/audit/secrets.log"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"id": "AU-01",
|
|
381
|
+
"name": "Audit Trail Integrity",
|
|
382
|
+
"description": "Tamper-protected logging of all agent actions",
|
|
383
|
+
"frequency": "continuous",
|
|
384
|
+
"evidence": "~/.clawmoat/audit/"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"id": "NW-01",
|
|
388
|
+
"name": "Network Egress Monitoring",
|
|
389
|
+
"description": "All outbound network requests logged and reviewed",
|
|
390
|
+
"frequency": "continuous",
|
|
391
|
+
"evidence": "~/.clawmoat/audit/network.log"
|
|
392
|
+
}
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
SOXEOF
|
|
396
|
+
chmod 600 "$CLAWMOAT_DIR/sox/controls.json"
|
|
397
|
+
success "SOX audit templates created"
|
|
398
|
+
|
|
399
|
+
# MCP Firewall default config
|
|
400
|
+
cat > "$CLAWMOAT_DIR/mcp-firewall/config.json" << 'MCPEOF'
|
|
401
|
+
{
|
|
402
|
+
"mode": "read-only",
|
|
403
|
+
"logAllCalls": true,
|
|
404
|
+
"allowedTools": [],
|
|
405
|
+
"blockedServers": [],
|
|
406
|
+
"rateLimiting": {
|
|
407
|
+
"enabled": true,
|
|
408
|
+
"maxCallsPerMinute": 60
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
MCPEOF
|
|
412
|
+
chmod 600 "$CLAWMOAT_DIR/mcp-firewall/config.json"
|
|
413
|
+
success "MCP Firewall configured (read-only mode)"
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
# ─── Step 6: Security scan ──────────────────────────────────────────────────
|
|
417
|
+
|
|
418
|
+
step "Running initial security scan..."
|
|
419
|
+
|
|
420
|
+
REPORT_FILE="$CLAWMOAT_DIR/reports/initial-scan-$(date +%Y%m%d-%H%M%S).txt"
|
|
421
|
+
FINDINGS=0
|
|
422
|
+
CRITICAL=0
|
|
423
|
+
|
|
424
|
+
scan_report() {
|
|
425
|
+
echo "$*" >> "$REPORT_FILE"
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if ! $DRY_RUN; then
|
|
429
|
+
|
|
430
|
+
echo "# ClawMoat Initial Security Report" > "$REPORT_FILE"
|
|
431
|
+
echo "# Generated: $TIMESTAMP" >> "$REPORT_FILE"
|
|
432
|
+
echo "# OS: $OS ($ARCH)" >> "$REPORT_FILE"
|
|
433
|
+
echo "" >> "$REPORT_FILE"
|
|
434
|
+
|
|
435
|
+
# Check for exposed credential files
|
|
436
|
+
echo "## Credential Exposure Check" >> "$REPORT_FILE"
|
|
437
|
+
|
|
438
|
+
CRED_PATHS=(
|
|
439
|
+
"$HOME/.ssh"
|
|
440
|
+
"$HOME/.aws"
|
|
441
|
+
"$HOME/.gnupg"
|
|
442
|
+
"$HOME/.gcloud"
|
|
443
|
+
"$HOME/.azure"
|
|
444
|
+
"$HOME/.kube"
|
|
445
|
+
"$HOME/.docker"
|
|
446
|
+
"$HOME/.npmrc"
|
|
447
|
+
"$HOME/.pypirc"
|
|
448
|
+
"$HOME/.netrc"
|
|
449
|
+
"$HOME/.git-credentials"
|
|
450
|
+
"$HOME/.password-store"
|
|
451
|
+
"$HOME/.1password"
|
|
452
|
+
"$HOME/.env"
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
for cred in "${CRED_PATHS[@]}"; do
|
|
456
|
+
if [ -e "$cred" ]; then
|
|
457
|
+
FINDINGS=$((FINDINGS + 1))
|
|
458
|
+
CRITICAL=$((CRITICAL + 1))
|
|
459
|
+
label="$(basename "$cred")"
|
|
460
|
+
scan_report " [FOUND] $cred — will be protected by ClawMoat"
|
|
461
|
+
warn "Found: $cred — ${GREEN}now protected${RESET}"
|
|
462
|
+
fi
|
|
463
|
+
done
|
|
464
|
+
|
|
465
|
+
# Check file permissions on sensitive items
|
|
466
|
+
echo "" >> "$REPORT_FILE"
|
|
467
|
+
echo "## Permission Check" >> "$REPORT_FILE"
|
|
468
|
+
|
|
469
|
+
if [ -d "$HOME/.ssh" ]; then
|
|
470
|
+
SSH_PERMS="$(stat -c '%a' "$HOME/.ssh" 2>/dev/null || stat -f '%A' "$HOME/.ssh" 2>/dev/null || echo 'unknown')"
|
|
471
|
+
if [ "$SSH_PERMS" != "700" ] && [ "$SSH_PERMS" != "unknown" ]; then
|
|
472
|
+
scan_report " [WARN] ~/.ssh permissions are $SSH_PERMS (should be 700)"
|
|
473
|
+
warn "~/.ssh permissions: $SSH_PERMS (recommended: 700)"
|
|
474
|
+
FINDINGS=$((FINDINGS + 1))
|
|
475
|
+
fi
|
|
476
|
+
fi
|
|
477
|
+
|
|
478
|
+
# Check for .env files in common locations
|
|
479
|
+
echo "" >> "$REPORT_FILE"
|
|
480
|
+
echo "## Environment File Check" >> "$REPORT_FILE"
|
|
481
|
+
|
|
482
|
+
ENV_COUNT=0
|
|
483
|
+
while IFS= read -r -d '' envfile; do
|
|
484
|
+
ENV_COUNT=$((ENV_COUNT + 1))
|
|
485
|
+
scan_report " [FOUND] $envfile"
|
|
486
|
+
done < <(find "$HOME" -maxdepth 3 -name '.env*' -type f -print0 2>/dev/null | head -z -20)
|
|
487
|
+
|
|
488
|
+
if [ "$ENV_COUNT" -gt 0 ]; then
|
|
489
|
+
FINDINGS=$((FINDINGS + ENV_COUNT))
|
|
490
|
+
info "Found $ENV_COUNT .env file(s) — secret scanning will monitor these"
|
|
491
|
+
fi
|
|
492
|
+
|
|
493
|
+
# Node/npm global check
|
|
494
|
+
echo "" >> "$REPORT_FILE"
|
|
495
|
+
echo "## Node.js Environment" >> "$REPORT_FILE"
|
|
496
|
+
scan_report " Node.js: $(node -v 2>/dev/null || echo 'not found')"
|
|
497
|
+
scan_report " npm: $(npm -v 2>/dev/null || echo 'not found')"
|
|
498
|
+
scan_report " Global prefix: $(npm prefix -g 2>/dev/null || echo 'unknown')"
|
|
499
|
+
|
|
500
|
+
chmod 600 "$REPORT_FILE"
|
|
501
|
+
success "Security report saved to: $REPORT_FILE"
|
|
502
|
+
|
|
503
|
+
fi # end if not dry-run
|
|
504
|
+
|
|
505
|
+
# ─── Summary ─────────────────────────────────────────────────────────────────
|
|
506
|
+
|
|
507
|
+
echo ""
|
|
508
|
+
divider
|
|
509
|
+
echo ""
|
|
510
|
+
echo -e "${BOLD}🏰 ClawMoat Installation Complete!${RESET}"
|
|
511
|
+
echo ""
|
|
512
|
+
echo -e " ${GREEN}✅${RESET} OS detected: $OS ($ARCH)"
|
|
513
|
+
if $NODE_OK; then
|
|
514
|
+
echo -e " ${GREEN}✅${RESET} Node.js: v${NODE_VERSION:-unknown}"
|
|
515
|
+
fi
|
|
516
|
+
echo -e " ${GREEN}✅${RESET} ClawMoat: installed"
|
|
517
|
+
echo -e " ${GREEN}✅${RESET} Config: $CONFIG_FILE"
|
|
518
|
+
echo -e " ${GREEN}✅${RESET} Permission tier: worker (least-privilege)"
|
|
519
|
+
echo -e " ${GREEN}✅${RESET} Forbidden zones: 17 credential paths protected"
|
|
520
|
+
echo -e " ${GREEN}✅${RESET} Secret scanning: enabled"
|
|
521
|
+
echo -e " ${GREEN}✅${RESET} Network logging: enabled"
|
|
522
|
+
echo -e " ${GREEN}✅${RESET} Audit trail: enabled"
|
|
523
|
+
|
|
524
|
+
if $ENTERPRISE; then
|
|
525
|
+
echo -e " ${GREEN}✅${RESET} FinanceGuard: monitor mode"
|
|
526
|
+
echo -e " ${GREEN}✅${RESET} MCP Firewall: read-only"
|
|
527
|
+
echo -e " ${GREEN}✅${RESET} SOX templates: installed"
|
|
528
|
+
fi
|
|
529
|
+
|
|
530
|
+
if [ "${FINDINGS:-0}" -gt 0 ]; then
|
|
531
|
+
echo ""
|
|
532
|
+
echo -e " ${YELLOW}📊${RESET} Security findings: ${BOLD}$FINDINGS${RESET} items found and now protected"
|
|
533
|
+
fi
|
|
534
|
+
|
|
535
|
+
echo ""
|
|
536
|
+
divider
|
|
537
|
+
echo ""
|
|
538
|
+
echo -e "${BOLD}Next steps:${RESET}"
|
|
539
|
+
echo ""
|
|
540
|
+
echo -e " 1. ${CYAN}Configure alerts${RESET} — edit ~/.clawmoat/config.json"
|
|
541
|
+
echo -e " Set webhookUrl, emailTo, or slackChannel for security alerts"
|
|
542
|
+
echo ""
|
|
543
|
+
echo -e " 2. ${CYAN}Test your setup${RESET}"
|
|
544
|
+
echo -e " $ clawmoat scan"
|
|
545
|
+
echo ""
|
|
546
|
+
echo -e " 3. ${CYAN}View documentation${RESET}"
|
|
547
|
+
echo -e " https://clawmoat.com/docs"
|
|
548
|
+
echo ""
|
|
549
|
+
|
|
550
|
+
if ! $ENTERPRISE; then
|
|
551
|
+
echo -e " 💼 ${BOLD}Need enterprise features?${RESET} Re-run with --enterprise:"
|
|
552
|
+
echo -e " $ curl -fsSL https://clawmoat.com/install.sh | bash -s -- --enterprise"
|
|
553
|
+
echo ""
|
|
554
|
+
fi
|
|
555
|
+
|
|
556
|
+
echo -e "${DIM}Questions? https://clawmoat.com/support/ • GitHub: ClawMoat/clawmoat${RESET}"
|
|
557
|
+
echo ""
|
|
@@ -66,14 +66,14 @@ footer{border-top:1px solid var(--navy-mid);padding:40px 0;text-align:center;col
|
|
|
66
66
|
<body>
|
|
67
67
|
|
|
68
68
|
<nav>
|
|
69
|
-
<div class="container"
|
|
69
|
+
<div class="container">
|
|
70
70
|
<a href="/" class="logo">🏰 Claw<span>Moat</span></a>
|
|
71
|
+
<button class="menu-toggle" onclick="document.querySelector('.nav-links').classList.toggle('open')" aria-label="Menu">☰</button>
|
|
71
72
|
<div class="nav-links">
|
|
72
|
-
<a href="/">
|
|
73
|
-
<a href="/
|
|
73
|
+
<a href="/">Security</a>
|
|
74
|
+
<a href="/services/">AI Agents</a>
|
|
74
75
|
<a href="/blog/">Blog</a>
|
|
75
|
-
<a href="https://github.com/darfaz/clawmoat">GitHub
|
|
76
|
-
<a href="/#waitlist" class="btn-sm">Get Early Access</a>
|
|
76
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub ↗</a>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
|
79
79
|
</nav>
|
|
@@ -276,7 +276,15 @@ audit:
|
|
|
276
276
|
</article>
|
|
277
277
|
|
|
278
278
|
<footer>
|
|
279
|
-
|
|
279
|
+
<div class="container">
|
|
280
|
+
<div style="display:flex;gap:24px;justify-content:center;flex-wrap:wrap;margin-bottom:16px">
|
|
281
|
+
<a href="https://github.com/darfaz/clawmoat" style="color:var(--gray)">GitHub</a>
|
|
282
|
+
<a href="https://www.npmjs.com/package/clawmoat" style="color:var(--gray)">npm</a>
|
|
283
|
+
<a href="/blog/" style="color:var(--gray)">Blog</a>
|
|
284
|
+
<a href="mailto:hello@clawmoat.com" style="color:var(--gray)">hello@clawmoat.com</a>
|
|
285
|
+
</div>
|
|
286
|
+
<p style="text-align:center;color:var(--gray);font-size:.85rem">© 2026 ClawMoat</p>
|
|
287
|
+
</div>
|
|
280
288
|
</footer>
|
|
281
289
|
|
|
282
290
|
</body>
|
|
@@ -66,14 +66,14 @@ footer{border-top:1px solid var(--navy-mid);padding:40px 0;text-align:center;col
|
|
|
66
66
|
<body>
|
|
67
67
|
|
|
68
68
|
<nav>
|
|
69
|
-
<div class="container"
|
|
69
|
+
<div class="container">
|
|
70
70
|
<a href="/" class="logo">🏰 Claw<span>Moat</span></a>
|
|
71
|
+
<button class="menu-toggle" onclick="document.querySelector('.nav-links').classList.toggle('open')" aria-label="Menu">☰</button>
|
|
71
72
|
<div class="nav-links">
|
|
72
|
-
<a href="/">
|
|
73
|
-
<a href="/
|
|
73
|
+
<a href="/">Security</a>
|
|
74
|
+
<a href="/services/">AI Agents</a>
|
|
74
75
|
<a href="/blog/">Blog</a>
|
|
75
|
-
<a href="https://github.com/darfaz/clawmoat">GitHub
|
|
76
|
-
<a href="/#waitlist" class="btn-sm">Get Early Access</a>
|
|
76
|
+
<a href="https://github.com/darfaz/clawmoat">GitHub ↗</a>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
|
79
79
|
</nav>
|
|
@@ -297,7 +297,15 @@ tools:
|
|
|
297
297
|
</article>
|
|
298
298
|
|
|
299
299
|
<footer>
|
|
300
|
-
|
|
300
|
+
<div class="container">
|
|
301
|
+
<div style="display:flex;gap:24px;justify-content:center;flex-wrap:wrap;margin-bottom:16px">
|
|
302
|
+
<a href="https://github.com/darfaz/clawmoat" style="color:var(--gray)">GitHub</a>
|
|
303
|
+
<a href="https://www.npmjs.com/package/clawmoat" style="color:var(--gray)">npm</a>
|
|
304
|
+
<a href="/blog/" style="color:var(--gray)">Blog</a>
|
|
305
|
+
<a href="mailto:hello@clawmoat.com" style="color:var(--gray)">hello@clawmoat.com</a>
|
|
306
|
+
</div>
|
|
307
|
+
<p style="text-align:center;color:var(--gray);font-size:.85rem">© 2026 ClawMoat</p>
|
|
308
|
+
</div>
|
|
301
309
|
</footer>
|
|
302
310
|
|
|
303
311
|
</body>
|