@lowwattlabs/clawsec 2.0.1 → 2.1.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/bin/setup-venv.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * ClawSec postinstall — sets up Python venv
3
+ * ClawSec postinstall — sets up Python venv and runs initial intel sync
4
4
  * Called by npm postinstall. Safe to run multiple times.
5
5
  */
6
6
 
@@ -12,23 +12,63 @@ const os = require('os');
12
12
  const CLAWSEC_HOME = process.env.CLAWSEC_HOME || path.join(os.homedir(), '.clawsec');
13
13
  const VENV_DIR = path.join(CLAWSEC_HOME, 'venv');
14
14
  const PYTHON = path.join(VENV_DIR, 'bin', 'python3');
15
+ const INTEL_DIR = path.join(CLAWSEC_HOME, 'intel');
15
16
 
16
17
  // Don't fail install if setup fails — user can run clawsec setup later
17
18
  try {
18
- if (fs.existsSync(PYTHON)) {
19
- process.exit(0); // Already set up
20
- }
19
+ // Step 1: Create Python venv if needed
20
+ if (!fs.existsSync(PYTHON)) {
21
+ fs.mkdirSync(CLAWSEC_HOME, { recursive: true });
22
+ console.log('⚡ Setting up ClawSec Python environment (first run)...');
23
+ execSync(`python3 -m venv "${VENV_DIR}"`, { stdio: 'inherit' });
21
24
 
22
- fs.mkdirSync(CLAWSEC_HOME, { recursive: true });
23
- execSync(`python3 -m venv "${VENV_DIR}"`, { stdio: 'pipe' });
25
+ const PKG_ROOT = path.resolve(__dirname, '..');
26
+ const REQUIREMENTS = path.join(PKG_ROOT, 'requirements.txt');
24
27
 
25
- const PKG_ROOT = path.resolve(__dirname, '..');
26
- const REQUIREMENTS = path.join(PKG_ROOT, 'requirements.txt');
28
+ if (fs.existsSync(REQUIREMENTS)) {
29
+ execSync(`"${PYTHON}" -m pip install --quiet --upgrade pip`, { stdio: 'pipe' });
30
+ execSync(`"${PYTHON}" -m pip install --quiet -r "${REQUIREMENTS}"`, { stdio: 'pipe' });
31
+ }
32
+ console.log(' ✅ Python environment ready.');
33
+ }
27
34
 
28
- if (fs.existsSync(REQUIREMENTS)) {
29
- execSync(`"${PYTHON}" -m pip install --quiet --upgrade pip`, { stdio: 'pipe' });
30
- execSync(`"${PYTHON}" -m pip install --quiet -r "${REQUIREMENTS}"`, { stdio: 'pipe' });
35
+ // Step 2: Create intel directories and sync
36
+ const intelDirs = [
37
+ 'cisa-kev', 'osv', 'osv/npm', 'osv/PyPI', 'epss',
38
+ 'malwarebazaar', 'urlhaus', 'threatfox', 'feodo',
39
+ 'yara-rules', 'yara-rules/repo', 'semgrep-rules', 'semgrep-rules/repo'
40
+ ];
41
+ for (const d of intelDirs) {
42
+ fs.mkdirSync(path.join(INTEL_DIR, d), { recursive: true });
31
43
  }
44
+ fs.mkdirSync(path.join(CLAWSEC_HOME, 'reports'), { recursive: true });
45
+
46
+ // Only sync if intel cache is empty (first install)
47
+ const manifest = path.join(INTEL_DIR, 'manifest.json');
48
+ if (!fs.existsSync(manifest)) {
49
+ console.log('⚡ Downloading threat intel (first run, may take a few minutes)...');
50
+ const PKG_ROOT = path.resolve(__dirname, '..');
51
+ const syncSh = path.join(PKG_ROOT, 'lib', 'intel-sync', 'sync.sh');
52
+ if (fs.existsSync(syncSh)) {
53
+ try {
54
+ execSync(`bash "${syncSh}"`, {
55
+ stdio: 'inherit',
56
+ env: {
57
+ ...process.env,
58
+ CLAWSEC_HOME: CLAWSEC_HOME,
59
+ CLAWSEC_INTEL_DIR: INTEL_DIR,
60
+ CLAWSEC_REPORTS_DIR: path.join(CLAWSEC_HOME, 'reports'),
61
+ PATH: `${path.join(os.homedir(), '.local', 'bin')}:${process.env.PATH || '/usr/local/bin:/usr/bin:/bin'}`,
62
+ }
63
+ });
64
+ } catch {
65
+ // Sync failure is non-fatal — user can run clawsec sync later
66
+ console.log(' ⚠ Intel sync had issues. Run "clawsec sync" to retry.');
67
+ }
68
+ }
69
+ }
70
+
71
+ console.log('⚡ ClawSec ready. Run "clawsec scan ./my-skill" to get started.');
32
72
  } catch {
33
73
  // Postinstall is best-effort. The CLI will try again on first run.
34
74
  process.exit(0);
package/cli/clawsec.py CHANGED
@@ -19,7 +19,7 @@ import sys
19
19
  import time
20
20
  from pathlib import Path
21
21
 
22
- VERSION = "2.0.1"
22
+ VERSION = "2.1.0"
23
23
  CLAWSEC_DIR = os.environ.get("CLAWSEC_HOME", os.path.expanduser("~/.clawsec"))
24
24
  INTEL_DIR = os.environ.get("CLAWSEC_INTEL_DIR", os.path.join(CLAWSEC_DIR, "intel"))
25
25
  REPORTS_DIR = os.environ.get("CLAWSEC_REPORTS_DIR", os.path.join(CLAWSEC_DIR, "reports"))
@@ -31,12 +31,12 @@ usage() {
31
31
  ALL_SOURCES=(cisa-kev osv epss malwarebazaar urlhaus threatfox feodo yara-rules semgrep-rules)
32
32
 
33
33
  # Ensure intel directories exist
34
- INTEL_DIR=
35
- for src in ; do
36
- mkdir -p /
34
+ INTEL_DIR="${CLAWSEC_INTEL_DIR}"
35
+ for src in "${ALL_SOURCES[@]}"; do
36
+ mkdir -p "${INTEL_DIR}/${src}"
37
37
  done
38
- mkdir -p /osv/npm /osv/PyPI
39
- mkdir -p
38
+ mkdir -p "${INTEL_DIR}/osv/npm" "${INTEL_DIR}/osv/PyPI"
39
+ mkdir -p "${CLAWSEC_REPORTS_DIR}"
40
40
  requested_sources=()
41
41
  json_output=0
42
42
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowwattlabs/clawsec",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "ClawSec - Security Verification for ClawHub Skills",
5
5
  "bin": {
6
6
  "clawsec": "./bin/clawsec.js",