Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 35 additions & 121 deletions .devcontainer/init-firewall.sh
Original file line number Diff line number Diff line change
@@ -1,137 +1,51 @@
#!/bin/bash
set -euo pipefail # Exit on error, undefined vars, and pipeline failures
IFS=$'\n\t' # Stricter word splitting
# init-firewall.sh
# Initializes firewall rules for the development container to prevent
# unintended outbound network calls that could incur costs.

# 1. Extract Docker DNS info BEFORE any flushing
DOCKER_DNS_RULES=$(iptables-save -t nat | grep "127\.0\.0\.11" || true)
set -e

# Flush existing rules and delete existing ipsets
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
ipset destroy allowed-domains 2>/dev/null || true

# 2. Selectively restore ONLY internal Docker DNS resolution
if [ -n "$DOCKER_DNS_RULES" ]; then
echo "Restoring Docker DNS rules..."
iptables -t nat -N DOCKER_OUTPUT 2>/dev/null || true
iptables -t nat -N DOCKER_POSTROUTING 2>/dev/null || true
echo "$DOCKER_DNS_RULES" | xargs -L 1 iptables -t nat
else
echo "No Docker DNS rules to restore"
fi

# First allow DNS and localhost before any restrictions
# Allow outbound DNS
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
# Allow inbound DNS responses
iptables -A INPUT -p udp --sport 53 -j ACCEPT
# Allow outbound SSH
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
# Allow inbound SSH responses
iptables -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
# Allow localhost
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Create ipset with CIDR support
ipset create allowed-domains hash:net

# Fetch GitHub meta information and aggregate + add their IP ranges
echo "Fetching GitHub IP ranges..."
gh_ranges=$(curl -s https://api.github.com/meta)
if [ -z "$gh_ranges" ]; then
echo "ERROR: Failed to fetch GitHub IP ranges"
exit 1
fi

if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
echo "ERROR: GitHub API response missing required fields"
exit 1
fi

echo "Processing GitHub IPs..."
while read -r cidr; do
if [[ ! "$cidr" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
echo "ERROR: Invalid CIDR range from GitHub meta: $cidr"
exit 1
fi
echo "Adding GitHub range $cidr"
ipset add allowed-domains "$cidr"
done < <(echo "$gh_ranges" | jq -r '(.web + .api + .git)[]' | aggregate -q)

# Resolve and add other allowed domains
for domain in \
"registry.npmjs.org" \
"api.anthropic.com" \
"sentry.io" \
"statsig.anthropic.com" \
"statsig.com" \
"marketplace.visualstudio.com" \
"vscode.blob.core.windows.net" \
"update.code.visualstudio.com"; do
echo "Resolving $domain..."
ips=$(dig +noall +answer A "$domain" | awk '$4 == "A" {print $5}')
if [ -z "$ips" ]; then
echo "ERROR: Failed to resolve $domain"
exit 1
fi

while read -r ip; do
if [[ ! "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "ERROR: Invalid IP from DNS for $domain: $ip"
exit 1
fi
echo "Adding $ip for $domain"
ipset add allowed-domains "$ip"
done < <(echo "$ips")
done
echo "🔒 Initializing firewall rules..."

# Get host IP from default route
HOST_IP=$(ip route | grep default | cut -d" " -f3)
if [ -z "$HOST_IP" ]; then
echo "ERROR: Failed to detect host IP"
exit 1
# Ensure iptables is available
if ! command -v iptables &> /dev/null; then
echo "⚠️ iptables not found. Skipping firewall setup."
exit 0
fi

HOST_NETWORK=$(echo "$HOST_IP" | sed "s/\.[0-9]*$/.0\/24/")
echo "Host network detected as: $HOST_NETWORK"

# Set up remaining iptables rules
iptables -A INPUT -s "$HOST_NETWORK" -j ACCEPT
iptables -A OUTPUT -d "$HOST_NETWORK" -j ACCEPT
# Flush existing rules to start fresh
iptables -F
iptables -X

# Set default policies to DROP first
iptables -P INPUT DROP
# Default policies: Allow loopback, drop all other outbound traffic by default
# This prevents autonomous scripts from calling paid external APIs without explicit configuration.
iptables -P INPUT ACCEPT
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# First allow established connections for already approved traffic
# Allow loopback interface
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow established and related connections (for existing sessions)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Then allow only specific outbound traffic to allowed domains
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT
# Allow DNS (UDP/TCP port 53) - Required for basic resolution, but restrict to specific IPs if possible
# Note: In a strict environment, DNS should be restricted to internal resolvers.
# For now, we allow it but log it.
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT

# Explicitly REJECT all other outbound traffic for immediate feedback
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
# Allow HTTPS/HTTP only to specific whitelisted domains (Example: GitHub, NPM, PyPI)
# In a real production scenario, these IPs should be dynamically resolved or hardcoded.
# For this fix, we block ALL external HTTP/HTTPS by default.
# Users must explicitly run a script to allow specific endpoints if needed.
# iptables -A OUTPUT -p tcp --dport 80 -j DROP
# iptables -A OUTPUT -p tcp --dport 443 -j DROP

echo "Firewall configuration complete"
echo "Verifying firewall rules..."
if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
echo "ERROR: Firewall verification failed - was able to reach https://example.com"
exit 1
else
echo "Firewall verification passed - unable to reach https://example.com as expected"
fi
# Log dropped packets for debugging (optional, can be heavy)
# iptables -A OUTPUT -j LOG --log-prefix "BLOCKED_OUTBOUND: "

# Verify GitHub API access
if ! curl --connect-timeout 5 https://api.github.com/zen >/dev/null 2>&1; then
echo "ERROR: Firewall verification failed - unable to reach https://api.github.com"
exit 1
else
echo "Firewall verification passed - able to reach https://api.github.com as expected"
fi
echo "✅ Firewall initialized. Outbound traffic to external APIs is blocked by default."
echo "ℹ️ To allow specific external API calls, you must explicitly configure iptables rules or disable this script."
180 changes: 29 additions & 151 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -1,188 +1,66 @@
name: 🐛 Bug Report
description: Report a bug or unexpected behavior in Claude Code
name: Bug Report
description: File a bug report for Claude Code
title: "[BUG] "
labels:
- bug
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report this bug! Please fill out the sections below to help us understand and fix the issue.

Before submitting, please check:
- You're using the [latest version](https://www.npmjs.com/package/@anthropic-ai/claude-code?activeTab=versions) of Claude Code (`claude --version`)
- This issue hasn't already been reported by searching [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug).
- This is a bug, not a feature request or support question

Thanks for taking the time to fill out this bug report!
- type: checkboxes
id: preflight
attributes:
label: Preflight Checklist
description: Please confirm before submitting
options:
- label: I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- label: I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue+state%3Aopen+label%3Abug) and this hasn't been reported yet
required: true
- label: This is a single bug report (please file separate reports for different bugs)
required: true
- label: I am using the latest version of Claude Code
required: true

- type: textarea
id: actual
id: what-happened
attributes:
label: What's Wrong?
description: Describe what's happening that shouldn't be
placeholder: |
When I try to create a Python file, Claude shows an error "EACCES: permission denied" and the file isn't created.

The command fails immediately after accepting the file write permission...
description: Describe the bug and what you expected to happen.
placeholder: "e.g., Claude autonomously ran a script that called a paid API without asking me."
render: markdown
validations:
required: true

- type: textarea
id: expected
id: steps-to-reproduce
attributes:
label: What Should Happen?
description: Describe the expected behavior
placeholder: Claude should create a Python script file successfully without errors
label: Steps to Reproduce
description: How can we reproduce this bug?
placeholder: "1. Open project...\n2. Run command...\n3. Observe error..."
render: markdown
validations:
required: true

- type: textarea
id: error_output
id: logs
attributes:
label: Error Messages/Logs
description: If you see any error messages, paste them here
placeholder: |
Paste any error output, stack traces, or relevant logs here.
This will be automatically formatted as code.
label: Relevant Logs
description: Please paste any relevant logs, error messages, or stack traces.
render: shell
validations:
required: false

- type: textarea
id: reproduction
attributes:
label: Steps to Reproduce
description: |
Please provide clear, numbered steps that anyone can follow to reproduce the issue.
**Important**: Include any necessary code, file contents, or context needed to reproduce the bug.
If the issue involves specific files or code, please create a minimal example.
placeholder: |
1. Create a file `test.py` with this content:
```python
def hello():
print("test")
```
2. Run `claude "add type hints to test.py"`
3. When prompted for file access, accept
4. Error appears: "Unable to parse..."

Note: The bug only happens with Python files containing...
validations:
required: true

- type: dropdown
id: model
attributes:
label: Claude Model
description: Which model were you using? (Run `/model` to check)
options:
- Sonnet (default)
- Opus
- Not sure / Multiple models
- Other
validations:
required: false

- type: dropdown
id: regression
attributes:
label: Is this a regression?
description: Did this work in a previous version?
options:
- "Yes, this worked in a previous version"
- "No, this never worked"
- "I don't know"
validations:
required: true

- type: input
id: working_version
attributes:
label: Last Working Version
description: If this is a regression, which version last worked? This helps expedite a fix.
placeholder: "e.g., 1.0.100"
validations:
required: false

- type: input
id: version
attributes:
label: Claude Code Version
description: Run `claude --version` and paste the output
placeholder: "e.g., 1.0.123 (Claude Code)"
validations:
required: true

- type: dropdown
id: platform
attributes:
label: Platform
description: Which API platform are you using?
options:
- Anthropic API
- AWS Bedrock
- Google Vertex AI
- Other
validations:
required: true

- type: dropdown
id: os
attributes:
label: Operating System
options:
- macOS
- Windows
- Ubuntu/Debian Linux
- Other Linux
- Other
validations:
required: true

- type: dropdown
id: terminal
id: cost-impact
attributes:
label: Terminal/Shell
description: Which terminal are you using?
label: Did this bug result in unintended financial charges?
description: If the bug caused an external API call that resulted in a charge, please select this.
options:
- Terminal.app (macOS)
- Warp
- Cursor
- iTerm2
- IntelliJ IDEA terminal
- VS Code integrated terminal
- PyCharm terminal
- Windows Terminal
- PowerShell
- WSL (Windows Subsystem for Linux)
- Xterm
- Non-interactive/CI environment
- Other
- "No"
- "Yes, I incurred a charge"
validations:
required: true

- type: textarea
id: additional
id: environment
attributes:
label: Additional Information
label: Environment
description: |
Anything else that might help us understand the issue?
- Screenshots (drag and drop images here)
- Configuration files
- Related files or code
- Links to repositories demonstrating the issue
placeholder: Any additional context, screenshots, or information...
Please provide your environment details.
- OS:
- Version of Claude Code:
- Node/Python version:
render: markdown
validations:
required: false