@mootup/moot-templates 0.3.0 → 0.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mootup/moot-templates",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Canonical project templates (skills, teams, devcontainer, Claude hooks) for @mootup/moot-cli, synced from the mootup Python CLI source.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -14,16 +14,32 @@ done
14
14
 
15
15
  # Read per-role actor identity from .moot/actors.json. See run-moot-mcp.sh
16
16
  # for the full rationale — same rule applies to the channel adapter.
17
+ #
18
+ # SEC-2-C: env-driven Python via single-quoted heredoc — no shell-eval RCE.
17
19
  if [ -f "$PROJECT_ROOT/$ACTORS_FILE" ]; then
18
- eval $(python3 -c "
19
- import json, shlex
20
- with open('$PROJECT_ROOT/$ACTORS_FILE') as f:
21
- data = json.load(f)
22
- entry = data.get('actors', {}).get('$ROLE', {})
23
- print('KEY=' + shlex.quote(entry.get('api_key', '')))
24
- print('AID=' + shlex.quote(entry.get('actor_id', '')))
25
- print('ANAME=' + shlex.quote(entry.get('display_name', '$ROLE')))
26
- " 2>/dev/null)
20
+ OUT="$(
21
+ export _PR="$PROJECT_ROOT" _AF="$ACTORS_FILE" _ROLE="$ROLE"
22
+ python3 <<'PYEOF'
23
+ import json, os, sys
24
+ pr = os.environ['_PR']
25
+ af = os.environ['_AF']
26
+ role = os.environ['_ROLE']
27
+ try:
28
+ with open(os.path.join(pr, af)) as f:
29
+ data = json.load(f)
30
+ entry = data.get('actors', {}).get(role, {})
31
+ print(entry.get('api_key', ''))
32
+ print(entry.get('actor_id', ''))
33
+ print(entry.get('display_name', role))
34
+ except Exception:
35
+ print('', file=sys.stderr)
36
+ print('', file=sys.stderr)
37
+ print('', file=sys.stderr)
38
+ PYEOF
39
+ )"
40
+ KEY="$(printf '%s\n' "$OUT" | sed -n '1p')"
41
+ AID="$(printf '%s\n' "$OUT" | sed -n '2p')"
42
+ ANAME="$(printf '%s\n' "$OUT" | sed -n '3p')"
27
43
  if [ -n "$KEY" ]; then
28
44
  export CONVO_API_KEY="$KEY"
29
45
  else
@@ -35,12 +51,15 @@ fi
35
51
 
36
52
  # Read API URL from moot.toml
37
53
  if [ -z "$CONVO_API_URL" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
38
- URL=$(python3 -c "
39
- import tomllib
40
- with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
54
+ URL="$(
55
+ export _PR="$PROJECT_ROOT"
56
+ python3 <<'PYEOF'
57
+ import os, tomllib
58
+ with open(os.path.join(os.environ['_PR'], 'moot.toml'), 'rb') as f:
41
59
  data = tomllib.load(f)
42
60
  print(data.get('convo', {}).get('api_url', ''))
43
- " 2>/dev/null)
61
+ PYEOF
62
+ )"
44
63
  if [ -n "$URL" ]; then
45
64
  export CONVO_API_URL="$URL"
46
65
  fi
@@ -48,12 +67,15 @@ fi
48
67
 
49
68
  # Read space ID from moot.toml
50
69
  if [ -z "$CONVO_SPACE_ID" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
51
- SID=$(python3 -c "
52
- import tomllib
53
- with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
70
+ SID="$(
71
+ export _PR="$PROJECT_ROOT"
72
+ python3 <<'PYEOF'
73
+ import os, tomllib
74
+ with open(os.path.join(os.environ['_PR'], 'moot.toml'), 'rb') as f:
54
75
  data = tomllib.load(f)
55
76
  print(data.get('convo', {}).get('space_id', ''))
56
- " 2>/dev/null)
77
+ PYEOF
78
+ )"
57
79
  if [ -n "$SID" ]; then
58
80
  export CONVO_SPACE_ID="$SID"
59
81
  fi
@@ -18,16 +18,33 @@ done
18
18
  # "unknown-agent", and the backend rejects any post whose agent_id in the
19
19
  # body doesn't match the authenticated actor (HTTP 400, which the adapter
20
20
  # surfaces as an empty event_id).
21
+ #
22
+ # SEC-2-C: env-driven Python via single-quoted heredoc — no shell-eval RCE.
23
+ # CONVO_ROLE / paths reach Python via os.environ, never via shell interpolation.
21
24
  if [ -f "$PROJECT_ROOT/$ACTORS_FILE" ]; then
22
- eval $(python3 -c "
23
- import json, shlex
24
- with open('$PROJECT_ROOT/$ACTORS_FILE') as f:
25
- data = json.load(f)
26
- entry = data.get('actors', {}).get('$ROLE', {})
27
- print('KEY=' + shlex.quote(entry.get('api_key', '')))
28
- print('AID=' + shlex.quote(entry.get('actor_id', '')))
29
- print('ANAME=' + shlex.quote(entry.get('display_name', '$ROLE')))
30
- " 2>/dev/null)
25
+ OUT="$(
26
+ export _PR="$PROJECT_ROOT" _AF="$ACTORS_FILE" _ROLE="$ROLE"
27
+ python3 <<'PYEOF'
28
+ import json, os, sys
29
+ pr = os.environ['_PR']
30
+ af = os.environ['_AF']
31
+ role = os.environ['_ROLE']
32
+ try:
33
+ with open(os.path.join(pr, af)) as f:
34
+ data = json.load(f)
35
+ entry = data.get('actors', {}).get(role, {})
36
+ print(entry.get('api_key', ''))
37
+ print(entry.get('actor_id', ''))
38
+ print(entry.get('display_name', role))
39
+ except Exception:
40
+ print('', file=sys.stderr)
41
+ print('', file=sys.stderr)
42
+ print('', file=sys.stderr)
43
+ PYEOF
44
+ )"
45
+ KEY="$(printf '%s\n' "$OUT" | sed -n '1p')"
46
+ AID="$(printf '%s\n' "$OUT" | sed -n '2p')"
47
+ ANAME="$(printf '%s\n' "$OUT" | sed -n '3p')"
31
48
  if [ -n "$KEY" ]; then
32
49
  export CONVO_API_KEY="$KEY"
33
50
  else
@@ -39,12 +56,15 @@ fi
39
56
 
40
57
  # Read API URL from moot.toml
41
58
  if [ -z "$CONVO_API_URL" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
42
- URL=$(python3 -c "
43
- import tomllib
44
- with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
59
+ URL="$(
60
+ export _PR="$PROJECT_ROOT"
61
+ python3 <<'PYEOF'
62
+ import os, tomllib
63
+ with open(os.path.join(os.environ['_PR'], 'moot.toml'), 'rb') as f:
45
64
  data = tomllib.load(f)
46
65
  print(data.get('convo', {}).get('api_url', ''))
47
- " 2>/dev/null)
66
+ PYEOF
67
+ )"
48
68
  if [ -n "$URL" ]; then
49
69
  export CONVO_API_URL="$URL"
50
70
  fi
@@ -52,12 +72,15 @@ fi
52
72
 
53
73
  # Read space ID from moot.toml
54
74
  if [ -z "$CONVO_SPACE_ID" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
55
- SID=$(python3 -c "
56
- import tomllib
57
- with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
75
+ SID="$(
76
+ export _PR="$PROJECT_ROOT"
77
+ python3 <<'PYEOF'
78
+ import os, tomllib
79
+ with open(os.path.join(os.environ['_PR'], 'moot.toml'), 'rb') as f:
58
80
  data = tomllib.load(f)
59
81
  print(data.get('convo', {}).get('space_id', ''))
60
- " 2>/dev/null)
82
+ PYEOF
83
+ )"
61
84
  if [ -n "$SID" ]; then
62
85
  export CONVO_SPACE_ID="$SID"
63
86
  fi