@jgamaraalv/ts-dev-kit 3.1.0 → 3.1.2
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/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.1.2] - 2026-02-27
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- `/yolo` firewall script: deduplicate DNS results with `sort -u` in `resolve_domain()` to prevent `ipset add` failure on duplicate IPs (root cause: `marketplace.visualstudio.com` returns the same IP twice)
|
|
13
|
+
|
|
14
|
+
## [3.1.1] - 2026-02-27
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- `/yolo` firewall script: add resilient fallback for Docker Desktop environments where `ipset` kernel module is unavailable — falls back to iptables-only rules, `getent` DNS resolution, and direct GitHub domain resolution; full diagnostic log at `/tmp/firewall-init.log`
|
|
19
|
+
|
|
8
20
|
## [3.1.0] - 2026-02-27
|
|
9
21
|
|
|
10
22
|
### Added
|
package/package.json
CHANGED
package/skills/yolo/SKILL.md
CHANGED
|
@@ -114,7 +114,17 @@ Open the project in VS Code with the devcontainer.
|
|
|
114
114
|
1. Verify VS Code is installed (`command -v code`).
|
|
115
115
|
2. If VS Code is not installed, inform the user:
|
|
116
116
|
|
|
117
|
-
> **VS Code is required** for devcontainer support. Install it from https://code.visualstudio.com/ and
|
|
117
|
+
> **VS Code is required** for devcontainer support. Install it from https://code.visualstudio.com/ and re-run `/yolo`.
|
|
118
|
+
|
|
119
|
+
Stop here. Do not proceed.
|
|
120
|
+
|
|
121
|
+
3. Ensure the Dev Containers extension is installed:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
code --install-extension ms-vscode-remote.remote-containers
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This is idempotent — if already installed, VS Code simply reports it and moves on.
|
|
118
128
|
|
|
119
129
|
**Launch sequence:**
|
|
120
130
|
|
|
@@ -248,6 +258,8 @@ Key security features:
|
|
|
248
258
|
- Localhost and host network allowed
|
|
249
259
|
- Startup verification: confirms `example.com` is blocked and `api.github.com` is reachable
|
|
250
260
|
- Docker DNS rules preserved
|
|
261
|
+
- Falls back to iptables-only rules if `ipset` kernel module is unavailable (common on Docker Desktop for Mac)
|
|
262
|
+
- Full diagnostic log at `/tmp/firewall-init.log` for troubleshooting
|
|
251
263
|
|
|
252
264
|
### Step 5 — Add `.devcontainer` to `.gitignore` (optional)
|
|
253
265
|
|
|
@@ -57,7 +57,7 @@ Write this file to `.devcontainer/devcontainer.json`:
|
|
|
57
57
|
},
|
|
58
58
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=delegated",
|
|
59
59
|
"workspaceFolder": "/workspace",
|
|
60
|
-
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh",
|
|
60
|
+
"postStartCommand": "sudo /usr/local/bin/init-firewall.sh 2>&1 | tee /tmp/firewall-init.log",
|
|
61
61
|
"waitFor": "postStartCommand"
|
|
62
62
|
}
|
|
63
63
|
```
|
|
@@ -4,153 +4,279 @@ Write this file to `.devcontainer/init-firewall.sh`:
|
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
#!/bin/bash
|
|
7
|
-
set -
|
|
8
|
-
IFS=$'\n\t'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
iptables -
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
set -uo pipefail # Strict vars and pipelines, but handle errors manually
|
|
8
|
+
IFS=$'\n\t'
|
|
9
|
+
|
|
10
|
+
LOG="/tmp/firewall-init.log"
|
|
11
|
+
exec > >(tee -a "$LOG") 2>&1
|
|
12
|
+
echo "=== Firewall init started at $(date -u) ==="
|
|
13
|
+
|
|
14
|
+
# --- Diagnostics -----------------------------------------------------------
|
|
15
|
+
echo "--- Pre-flight checks ---"
|
|
16
|
+
HAVE_IPTABLES=false
|
|
17
|
+
HAVE_IPSET=false
|
|
18
|
+
|
|
19
|
+
if iptables -L -n >/dev/null 2>&1; then
|
|
20
|
+
HAVE_IPTABLES=true
|
|
21
|
+
echo "[OK] iptables is functional"
|
|
22
|
+
else
|
|
23
|
+
echo "[FAIL] iptables is NOT functional — firewall cannot be configured"
|
|
24
|
+
echo "Hint: ensure --cap-add=NET_ADMIN is set in devcontainer.json runArgs"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
if ipset list >/dev/null 2>&1 || ipset create _test hash:net 2>/dev/null; then
|
|
29
|
+
ipset destroy _test 2>/dev/null || true
|
|
30
|
+
HAVE_IPSET=true
|
|
31
|
+
echo "[OK] ipset is functional"
|
|
32
|
+
else
|
|
33
|
+
echo "[WARN] ipset is NOT functional — falling back to iptables-only rules"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if command -v dig >/dev/null 2>&1; then
|
|
37
|
+
echo "[OK] dig is available"
|
|
38
|
+
else
|
|
39
|
+
echo "[WARN] dig not found — DNS resolution will use getent"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
if command -v aggregate >/dev/null 2>&1; then
|
|
43
|
+
echo "[OK] aggregate is available"
|
|
44
|
+
else
|
|
45
|
+
echo "[WARN] aggregate not found — GitHub CIDRs will be added individually"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# --- Helper: resolve domain to IPs ----------------------------------------
|
|
49
|
+
resolve_domain() {
|
|
50
|
+
local domain="$1"
|
|
51
|
+
local ips=""
|
|
52
|
+
if command -v dig >/dev/null 2>&1; then
|
|
53
|
+
ips=$(dig +noall +answer +short A "$domain" 2>/dev/null | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | sort -u)
|
|
54
|
+
fi
|
|
55
|
+
if [ -z "$ips" ] && command -v getent >/dev/null 2>&1; then
|
|
56
|
+
ips=$(getent ahostsv4 "$domain" 2>/dev/null | awk '{print $1}' | sort -u | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$')
|
|
57
|
+
fi
|
|
58
|
+
echo "$ips"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# --- 1. Preserve Docker DNS -----------------------------------------------
|
|
62
|
+
echo "--- Preserving Docker DNS rules ---"
|
|
63
|
+
DOCKER_DNS_RULES=$(iptables-save -t nat 2>/dev/null | grep "127\.0\.0\.11" || true)
|
|
64
|
+
|
|
65
|
+
# --- 2. Flush existing rules -----------------------------------------------
|
|
66
|
+
echo "--- Flushing existing rules ---"
|
|
67
|
+
iptables -F || true
|
|
68
|
+
iptables -X || true
|
|
69
|
+
iptables -t nat -F || true
|
|
70
|
+
iptables -t nat -X || true
|
|
71
|
+
iptables -t mangle -F || true
|
|
72
|
+
iptables -t mangle -X || true
|
|
73
|
+
if [ "$HAVE_IPSET" = true ]; then
|
|
74
|
+
ipset destroy allowed-domains 2>/dev/null || true
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# --- 3. Restore Docker DNS -------------------------------------------------
|
|
23
78
|
if [ -n "$DOCKER_DNS_RULES" ]; then
|
|
24
79
|
echo "Restoring Docker DNS rules..."
|
|
25
80
|
iptables -t nat -N DOCKER_OUTPUT 2>/dev/null || true
|
|
26
81
|
iptables -t nat -N DOCKER_POSTROUTING 2>/dev/null || true
|
|
27
|
-
echo "$DOCKER_DNS_RULES" |
|
|
82
|
+
echo "$DOCKER_DNS_RULES" | while read -r rule; do
|
|
83
|
+
iptables -t nat $rule 2>/dev/null || true
|
|
84
|
+
done
|
|
28
85
|
else
|
|
29
86
|
echo "No Docker DNS rules to restore"
|
|
30
87
|
fi
|
|
31
88
|
|
|
32
|
-
#
|
|
33
|
-
|
|
89
|
+
# --- 4. Base rules (DNS, SSH, localhost) ------------------------------------
|
|
90
|
+
echo "--- Setting base rules ---"
|
|
91
|
+
# Outbound DNS
|
|
34
92
|
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
|
|
35
|
-
|
|
93
|
+
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
|
|
94
|
+
# Inbound DNS responses
|
|
36
95
|
iptables -A INPUT -p udp --sport 53 -j ACCEPT
|
|
37
|
-
|
|
96
|
+
iptables -A INPUT -p tcp --sport 53 -j ACCEPT
|
|
97
|
+
# Outbound SSH
|
|
38
98
|
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
|
|
39
|
-
# Allow inbound SSH responses
|
|
40
99
|
iptables -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
|
|
41
|
-
#
|
|
100
|
+
# Localhost
|
|
42
101
|
iptables -A INPUT -i lo -j ACCEPT
|
|
43
102
|
iptables -A OUTPUT -o lo -j ACCEPT
|
|
44
103
|
|
|
45
|
-
#
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
echo "
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
104
|
+
# --- 5. Host network -------------------------------------------------------
|
|
105
|
+
HOST_IP=$(ip route 2>/dev/null | grep default | head -1 | awk '{print $3}')
|
|
106
|
+
if [ -n "$HOST_IP" ]; then
|
|
107
|
+
HOST_NETWORK=$(echo "$HOST_IP" | sed "s/\.[0-9]*$/.0\/16/")
|
|
108
|
+
echo "Host network: $HOST_NETWORK (via $HOST_IP)"
|
|
109
|
+
iptables -A INPUT -s "$HOST_NETWORK" -j ACCEPT
|
|
110
|
+
iptables -A OUTPUT -d "$HOST_NETWORK" -j ACCEPT
|
|
111
|
+
else
|
|
112
|
+
echo "[WARN] Could not detect host IP — allowing RFC1918 ranges for Docker connectivity"
|
|
113
|
+
iptables -A INPUT -s 172.16.0.0/12 -j ACCEPT
|
|
114
|
+
iptables -A OUTPUT -d 172.16.0.0/12 -j ACCEPT
|
|
115
|
+
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
|
|
116
|
+
iptables -A OUTPUT -d 192.168.0.0/16 -j ACCEPT
|
|
117
|
+
iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
|
|
118
|
+
iptables -A OUTPUT -d 10.0.0.0/8 -j ACCEPT
|
|
54
119
|
fi
|
|
55
120
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
121
|
+
# --- 6. Allowed domains ----------------------------------------------------
|
|
122
|
+
ALLOWED_DOMAINS=(
|
|
123
|
+
"registry.npmjs.org"
|
|
124
|
+
"api.anthropic.com"
|
|
125
|
+
"sentry.io"
|
|
126
|
+
"statsig.anthropic.com"
|
|
127
|
+
"statsig.com"
|
|
128
|
+
"marketplace.visualstudio.com"
|
|
129
|
+
"vscode.blob.core.windows.net"
|
|
130
|
+
"update.code.visualstudio.com"
|
|
131
|
+
)
|
|
60
132
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
echo "
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
133
|
+
if [ "$HAVE_IPSET" = true ]; then
|
|
134
|
+
# ---- ipset mode (preferred) ----
|
|
135
|
+
echo "--- Building ipset allowlist ---"
|
|
136
|
+
ipset create allowed-domains hash:net
|
|
137
|
+
|
|
138
|
+
# GitHub dynamic IPs
|
|
139
|
+
echo "Fetching GitHub IP ranges..."
|
|
140
|
+
gh_ranges=$(curl -sf --connect-timeout 10 https://api.github.com/meta 2>/dev/null || true)
|
|
141
|
+
if [ -n "$gh_ranges" ] && echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null 2>&1; then
|
|
142
|
+
if command -v aggregate >/dev/null 2>&1; then
|
|
143
|
+
while read -r cidr; do
|
|
144
|
+
[[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]] && ipset add allowed-domains "$cidr" 2>/dev/null || true
|
|
145
|
+
done < <(echo "$gh_ranges" | jq -r '(.web + .api + .git)[]' | aggregate -q 2>/dev/null)
|
|
146
|
+
else
|
|
147
|
+
while read -r cidr; do
|
|
148
|
+
[[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]] && ipset add allowed-domains "$cidr" 2>/dev/null || true
|
|
149
|
+
done < <(echo "$gh_ranges" | jq -r '(.web + .api + .git)[]')
|
|
150
|
+
fi
|
|
151
|
+
echo "[OK] GitHub IP ranges added"
|
|
152
|
+
else
|
|
153
|
+
echo "[WARN] Could not fetch GitHub IPs — resolving github.com directly"
|
|
154
|
+
for gh_domain in "github.com" "api.github.com" "raw.githubusercontent.com" "objects.githubusercontent.com"; do
|
|
155
|
+
ips=$(resolve_domain "$gh_domain")
|
|
156
|
+
while read -r ip; do
|
|
157
|
+
[ -n "$ip" ] && ipset add allowed-domains "$ip" 2>/dev/null || true
|
|
158
|
+
done <<< "$ips"
|
|
159
|
+
done
|
|
86
160
|
fi
|
|
87
161
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
162
|
+
# Other allowed domains
|
|
163
|
+
for domain in "${ALLOWED_DOMAINS[@]}"; do
|
|
164
|
+
echo "Resolving $domain..."
|
|
165
|
+
ips=$(resolve_domain "$domain")
|
|
166
|
+
if [ -z "$ips" ]; then
|
|
167
|
+
echo "[WARN] Failed to resolve $domain — skipping"
|
|
168
|
+
continue
|
|
92
169
|
fi
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
done
|
|
97
|
-
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
if [ -z "$HOST_IP" ]; then
|
|
101
|
-
echo "ERROR: Failed to detect host IP"
|
|
102
|
-
exit 1
|
|
103
|
-
fi
|
|
170
|
+
while read -r ip; do
|
|
171
|
+
[ -n "$ip" ] && ipset add allowed-domains "$ip" 2>/dev/null || true
|
|
172
|
+
done <<< "$ips"
|
|
173
|
+
done
|
|
174
|
+
|
|
175
|
+
# Apply ipset match rule
|
|
176
|
+
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
|
104
177
|
|
|
105
|
-
|
|
106
|
-
|
|
178
|
+
else
|
|
179
|
+
# ---- iptables-only mode (fallback) ----
|
|
180
|
+
echo "--- Building iptables allowlist (no ipset) ---"
|
|
181
|
+
|
|
182
|
+
# GitHub IPs
|
|
183
|
+
echo "Fetching GitHub IP ranges..."
|
|
184
|
+
gh_ranges=$(curl -sf --connect-timeout 10 https://api.github.com/meta 2>/dev/null || true)
|
|
185
|
+
if [ -n "$gh_ranges" ] && echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null 2>&1; then
|
|
186
|
+
while read -r cidr; do
|
|
187
|
+
[[ "$cidr" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$ ]] && \
|
|
188
|
+
iptables -A OUTPUT -d "$cidr" -j ACCEPT 2>/dev/null || true
|
|
189
|
+
done < <(echo "$gh_ranges" | jq -r '(.web + .api + .git)[]')
|
|
190
|
+
echo "[OK] GitHub IP ranges added via iptables"
|
|
191
|
+
else
|
|
192
|
+
echo "[WARN] Could not fetch GitHub IPs — resolving github.com directly"
|
|
193
|
+
for gh_domain in "github.com" "api.github.com" "raw.githubusercontent.com" "objects.githubusercontent.com"; do
|
|
194
|
+
ips=$(resolve_domain "$gh_domain")
|
|
195
|
+
while read -r ip; do
|
|
196
|
+
[ -n "$ip" ] && iptables -A OUTPUT -d "$ip" -j ACCEPT 2>/dev/null || true
|
|
197
|
+
done <<< "$ips"
|
|
198
|
+
done
|
|
199
|
+
fi
|
|
107
200
|
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
201
|
+
# Other allowed domains
|
|
202
|
+
for domain in "${ALLOWED_DOMAINS[@]}"; do
|
|
203
|
+
echo "Resolving $domain..."
|
|
204
|
+
ips=$(resolve_domain "$domain")
|
|
205
|
+
if [ -z "$ips" ]; then
|
|
206
|
+
echo "[WARN] Failed to resolve $domain — skipping"
|
|
207
|
+
continue
|
|
208
|
+
fi
|
|
209
|
+
while read -r ip; do
|
|
210
|
+
[ -n "$ip" ] && iptables -A OUTPUT -d "$ip" -j ACCEPT 2>/dev/null || true
|
|
211
|
+
done <<< "$ips"
|
|
212
|
+
done
|
|
213
|
+
fi
|
|
111
214
|
|
|
112
|
-
#
|
|
215
|
+
# --- 7. Default-deny policies ----------------------------------------------
|
|
216
|
+
echo "--- Applying default-deny policies ---"
|
|
113
217
|
iptables -P INPUT DROP
|
|
114
218
|
iptables -P FORWARD DROP
|
|
115
219
|
iptables -P OUTPUT DROP
|
|
116
220
|
|
|
117
|
-
#
|
|
221
|
+
# Allow established connections
|
|
118
222
|
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
119
223
|
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
120
224
|
|
|
121
|
-
#
|
|
122
|
-
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
|
|
123
|
-
|
|
124
|
-
# Explicitly REJECT all other outbound traffic for immediate feedback
|
|
225
|
+
# Reject everything else with immediate feedback
|
|
125
226
|
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
|
|
126
227
|
|
|
127
|
-
|
|
128
|
-
echo "Verifying firewall
|
|
228
|
+
# --- 8. Verification -------------------------------------------------------
|
|
229
|
+
echo "--- Verifying firewall ---"
|
|
230
|
+
VERIFIED=true
|
|
231
|
+
|
|
129
232
|
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
|
|
130
|
-
echo "
|
|
131
|
-
|
|
233
|
+
echo "[FAIL] Firewall verification failed — reached https://example.com (should be blocked)"
|
|
234
|
+
VERIFIED=false
|
|
132
235
|
else
|
|
133
|
-
echo "
|
|
236
|
+
echo "[OK] https://example.com is blocked as expected"
|
|
134
237
|
fi
|
|
135
238
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
echo "ERROR: Firewall verification failed - unable to reach https://api.github.com"
|
|
139
|
-
exit 1
|
|
239
|
+
if curl --connect-timeout 5 https://api.github.com/zen >/dev/null 2>&1; then
|
|
240
|
+
echo "[OK] https://api.github.com is reachable as expected"
|
|
140
241
|
else
|
|
141
|
-
echo "
|
|
242
|
+
echo "[WARN] https://api.github.com is not reachable — GitHub IPs may have changed"
|
|
243
|
+
echo " Claude Code will still work, but git operations may fail"
|
|
142
244
|
fi
|
|
245
|
+
|
|
246
|
+
if [ "$VERIFIED" = false ]; then
|
|
247
|
+
echo "=== FIREWALL VERIFICATION FAILED ==="
|
|
248
|
+
exit 1
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
echo "=== Firewall configured successfully ==="
|
|
252
|
+
echo "Mode: $([ "$HAVE_IPSET" = true ] && echo 'ipset' || echo 'iptables-only')"
|
|
253
|
+
echo "Log: $LOG"
|
|
143
254
|
```
|
|
144
255
|
|
|
256
|
+
## Key improvements over the original
|
|
257
|
+
|
|
258
|
+
| Issue | Original behavior | Improved behavior |
|
|
259
|
+
|-------|-------------------|-------------------|
|
|
260
|
+
| Duplicate IPs from DNS | `ipset add` fatal error (exit 1) | Deduplicates via `sort -u` + `ipset add ... \|\| true` |
|
|
261
|
+
| `ipset` not available | Fatal crash | Falls back to iptables-only rules |
|
|
262
|
+
| `aggregate` not available | Fatal crash | Adds CIDRs individually without aggregation |
|
|
263
|
+
| `dig` not available | Fatal crash | Falls back to `getent ahostsv4` |
|
|
264
|
+
| GitHub API unreachable | Fatal crash | Resolves github.com/api.github.com directly |
|
|
265
|
+
| Domain resolution fails | Fatal crash | Skips domain with warning, continues |
|
|
266
|
+
| Host IP detection fails | Fatal crash | Allows all RFC1918 ranges as fallback |
|
|
267
|
+
| Docker DNS restore fails | Silent + potential crash | Handles per-rule with `|| true` |
|
|
268
|
+
| No diagnostic output | Blind exit code 1 | Full log at `/tmp/firewall-init.log` |
|
|
269
|
+
| GitHub unreachable after setup | Fatal crash | Warning only (Claude API is the critical path) |
|
|
270
|
+
|
|
145
271
|
## Firewall rules summary
|
|
146
272
|
|
|
147
273
|
| Rule | Direction | Purpose |
|
|
148
274
|
|------|-----------|---------|
|
|
149
|
-
| DNS (UDP 53) | Outbound | Domain name resolution |
|
|
275
|
+
| DNS (UDP/TCP 53) | Outbound | Domain name resolution |
|
|
150
276
|
| SSH (TCP 22) | Outbound | Git over SSH |
|
|
151
277
|
| Localhost | Both | Container-internal communication |
|
|
152
278
|
| Host network | Both | Docker host ↔ container communication |
|
|
153
|
-
| GitHub IPs | Outbound | Git operations, GitHub API (dynamically fetched
|
|
279
|
+
| GitHub IPs | Outbound | Git operations, GitHub API (dynamically fetched or resolved) |
|
|
154
280
|
| npm registry | Outbound | Package installation |
|
|
155
281
|
| api.anthropic.com | Outbound | Claude API calls |
|
|
156
282
|
| sentry.io | Outbound | Error reporting |
|
|
@@ -161,7 +287,7 @@ fi
|
|
|
161
287
|
## Verification on startup
|
|
162
288
|
|
|
163
289
|
The script verifies the firewall by:
|
|
164
|
-
1. Confirming `https://example.com` is **blocked** (
|
|
165
|
-
2. Confirming `https://api.github.com` is **reachable** (
|
|
290
|
+
1. Confirming `https://example.com` is **blocked** (must fail — otherwise exit 1)
|
|
291
|
+
2. Confirming `https://api.github.com` is **reachable** (warning only if it fails)
|
|
166
292
|
|
|
167
|
-
|
|
293
|
+
All output is logged to `/tmp/firewall-init.log` for debugging.
|