patchpal 0.24.1__tar.gz → 0.24.2__tar.gz
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.
- {patchpal-0.24.1/patchpal.egg-info → patchpal-0.24.2}/PKG-INFO +1 -1
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/__init__.py +1 -1
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/agent/bedrock_profile_utils.py +26 -1
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/cli/sandbox.py +59 -8
- {patchpal-0.24.1 → patchpal-0.24.2/patchpal.egg-info}/PKG-INFO +1 -1
- {patchpal-0.24.1 → patchpal-0.24.2}/LICENSE +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/MANIFEST.in +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/README.md +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/agent/__init__.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/agent/function_calling.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/agent/react.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/cli/__init__.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/cli/autopilot.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/cli/interactive.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/cli/mcp.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/cli/streaming.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/config.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/context.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/permissions.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/prompts/react_prompt.md +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/prompts/system_prompt.md +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/skills.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/__init__.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/audit.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/browser_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/code_analysis.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/common.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/definitions.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/file_reading.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/file_writing.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/find_tool.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/grep_tool.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/image_handler.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/mcp.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/repo_map.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/shell_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/todo_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/tool_schema.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/user_interaction.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal/tools/web_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal.egg-info/SOURCES.txt +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal.egg-info/dependency_links.txt +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal.egg-info/entry_points.txt +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal.egg-info/requires.txt +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/patchpal.egg-info/top_level.txt +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/pyproject.toml +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/setup.cfg +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_agent.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_cli.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_config_dynamic.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_context.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_custom_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_enabled_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_find_tool.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_guardrails.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_image_blocking.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_maximum_security.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_mcp_config.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_memory.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_memory_locations.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_operational_safety.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_optional_tools.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_permissions.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_react.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_reasoning_content.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_repo_map.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_simplified_prompt.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_skills.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_streaming.py +0 -0
- {patchpal-0.24.1 → patchpal-0.24.2}/tests/test_tools.py +0 -0
|
@@ -29,8 +29,33 @@ def _extract_model_from_arn(arn: str) -> str | None:
|
|
|
29
29
|
else:
|
|
30
30
|
region = os.getenv("AWS_REGION_NAME") or os.getenv("AWS_REGION") or "us-east-1"
|
|
31
31
|
|
|
32
|
+
# Check for custom Bedrock endpoint (VPC endpoint, custom domain, etc.)
|
|
33
|
+
# The control plane and runtime may use the same VPC endpoint base
|
|
34
|
+
custom_endpoint = (
|
|
35
|
+
os.getenv("AWS_BEDROCK_ENDPOINT")
|
|
36
|
+
or os.getenv("AWS_ENDPOINT_URL_BEDROCK")
|
|
37
|
+
or os.getenv("AWS_ENDPOINT_URL")
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# CRITICAL FIX: Derive control plane endpoint from runtime VPC endpoint
|
|
41
|
+
# Scenario: User has VPC endpoint for runtime but not explicit control plane endpoint
|
|
42
|
+
# Problem: boto3.client("bedrock") defaults to public endpoint, not VPC endpoint
|
|
43
|
+
# Solution: Automatically derive control plane VPC endpoint from runtime endpoint
|
|
44
|
+
# VPC endpoint pattern:
|
|
45
|
+
# Runtime: vpce-{id}.bedrock-runtime.{region}.vpce.amazonaws.com
|
|
46
|
+
# Control plane: vpce-{id}.bedrock.{region}.vpce.amazonaws.com
|
|
47
|
+
# This matches the automatic derivation in sandbox.py endpoint detection
|
|
48
|
+
if custom_endpoint and "bedrock-runtime" in custom_endpoint:
|
|
49
|
+
# Try to construct control plane VPC endpoint by removing -runtime
|
|
50
|
+
control_endpoint = custom_endpoint.replace("bedrock-runtime", "bedrock")
|
|
51
|
+
else:
|
|
52
|
+
control_endpoint = custom_endpoint
|
|
53
|
+
|
|
32
54
|
# Create bedrock client
|
|
33
|
-
|
|
55
|
+
if control_endpoint:
|
|
56
|
+
bedrock = boto3.client("bedrock", region_name=region, endpoint_url=control_endpoint)
|
|
57
|
+
else:
|
|
58
|
+
bedrock = boto3.client("bedrock", region_name=region)
|
|
34
59
|
|
|
35
60
|
# Get inference profile details
|
|
36
61
|
response = bedrock.get_inference_profile(inferenceProfileIdentifier=arn)
|
|
@@ -144,6 +144,7 @@ def detect_llm_endpoints_from_env():
|
|
|
144
144
|
"ANTHROPIC_API_BASE",
|
|
145
145
|
"AWS_BEDROCK_ENDPOINT",
|
|
146
146
|
"AWS_ENDPOINT_URL_BEDROCK_RUNTIME",
|
|
147
|
+
"AWS_ENDPOINT_URL_BEDROCK", # Control plane endpoint
|
|
147
148
|
"AWS_ENDPOINT_URL",
|
|
148
149
|
"AWS_BEDROCK_RUNTIME_ENDPOINT",
|
|
149
150
|
"AZURE_OPENAI_ENDPOINT",
|
|
@@ -162,6 +163,18 @@ def detect_llm_endpoints_from_env():
|
|
|
162
163
|
# Ensure it's a valid URL
|
|
163
164
|
if value.startswith("http://") or value.startswith("https://"):
|
|
164
165
|
detected_urls.append(value)
|
|
166
|
+
|
|
167
|
+
# CRITICAL FIX: For Bedrock VPC endpoints, derive control plane endpoint
|
|
168
|
+
# Scenario: User has VPC endpoint for runtime API (e.g., AWS GovCloud private network)
|
|
169
|
+
# Problem: Model capability detection needs control plane API (get_inference_profile)
|
|
170
|
+
# but boto3 doesn't automatically derive control plane from runtime endpoint
|
|
171
|
+
# VPC endpoint pattern:
|
|
172
|
+
# Runtime: vpce-{id}.bedrock-runtime.{region}.vpce.amazonaws.com
|
|
173
|
+
# Control plane: vpce-{id}.bedrock.{region}.vpce.amazonaws.com
|
|
174
|
+
# Without this, capability detection hangs trying to reach public control plane endpoint
|
|
175
|
+
if "bedrock-runtime" in value and ".vpce.amazonaws.com" in value:
|
|
176
|
+
control_plane_url = value.replace("bedrock-runtime", "bedrock")
|
|
177
|
+
detected_urls.append(control_plane_url)
|
|
165
178
|
else:
|
|
166
179
|
# Assume https if no protocol specified
|
|
167
180
|
detected_urls.append(f"https://{value}")
|
|
@@ -177,18 +190,37 @@ def detect_llm_endpoints_from_env():
|
|
|
177
190
|
if aws_region and (
|
|
178
191
|
os.environ.get("AWS_ACCESS_KEY_ID") or os.environ.get("AWS_SECRET_ACCESS_KEY")
|
|
179
192
|
):
|
|
180
|
-
# Add Bedrock
|
|
193
|
+
# Add Bedrock endpoints for the region
|
|
181
194
|
# Support both GovCloud and standard regions
|
|
182
195
|
# Also support AWS China regions
|
|
196
|
+
|
|
197
|
+
# IMPORTANT: boto3 uses standard endpoint names by default, even in GovCloud
|
|
198
|
+
# Only use -fips suffix if AWS_USE_FIPS_ENDPOINT=true is explicitly set
|
|
199
|
+
# Scenario 1: Standard GovCloud → bedrock.us-gov-east-1.amazonaws.com (boto3 default)
|
|
200
|
+
# Scenario 2: FIPS required → bedrock-fips.us-gov-east-1.amazonaws.com (explicit opt-in)
|
|
201
|
+
use_fips = os.environ.get("AWS_USE_FIPS_ENDPOINT", "").lower() == "true"
|
|
202
|
+
|
|
183
203
|
if "gov" in aws_region:
|
|
184
|
-
# GovCloud regions
|
|
185
|
-
|
|
204
|
+
# GovCloud regions
|
|
205
|
+
# Add both runtime (for LLM inference) and control plane (for model capability detection)
|
|
206
|
+
if use_fips:
|
|
207
|
+
# FIPS endpoints (only when explicitly requested via AWS_USE_FIPS_ENDPOINT=true)
|
|
208
|
+
detected_urls.append(f"https://bedrock-runtime-fips.{aws_region}.amazonaws.com")
|
|
209
|
+
detected_urls.append(f"https://bedrock-fips.{aws_region}.amazonaws.com")
|
|
210
|
+
else:
|
|
211
|
+
# Standard GovCloud endpoints (boto3 default behavior)
|
|
212
|
+
# This is what boto3 uses unless FIPS is explicitly configured
|
|
213
|
+
detected_urls.append(f"https://bedrock-runtime.{aws_region}.amazonaws.com")
|
|
214
|
+
detected_urls.append(f"https://bedrock.{aws_region}.amazonaws.com")
|
|
186
215
|
elif "cn-" in aws_region:
|
|
187
|
-
# AWS China regions use .amazonaws.com.cn
|
|
216
|
+
# AWS China regions use .amazonaws.com.cn domain
|
|
188
217
|
detected_urls.append(f"https://bedrock-runtime.{aws_region}.amazonaws.com.cn")
|
|
218
|
+
detected_urls.append(f"https://bedrock.{aws_region}.amazonaws.com.cn")
|
|
189
219
|
else:
|
|
190
|
-
# Standard commercial regions
|
|
220
|
+
# Standard commercial regions (us-east-1, eu-west-1, etc.)
|
|
221
|
+
# Add both runtime (for LLM inference) and control plane (for model capability detection)
|
|
191
222
|
detected_urls.append(f"https://bedrock-runtime.{aws_region}.amazonaws.com")
|
|
223
|
+
detected_urls.append(f"https://bedrock.{aws_region}.amazonaws.com")
|
|
192
224
|
|
|
193
225
|
# Azure OpenAI: Extract from resource name if AZURE_OPENAI_KEY is set
|
|
194
226
|
azure_key = os.environ.get("AZURE_OPENAI_KEY") or os.environ.get("AZURE_API_KEY")
|
|
@@ -276,9 +308,28 @@ fi
|
|
|
276
308
|
# Configure iptables
|
|
277
309
|
echo "Configuring firewall rules..."
|
|
278
310
|
|
|
279
|
-
#
|
|
280
|
-
|
|
281
|
-
|
|
311
|
+
# Extract DNS resolver IP(s) from /etc/resolv.conf
|
|
312
|
+
# This locks DNS queries to only the container's configured resolver,
|
|
313
|
+
# preventing agents from directly querying attacker-controlled DNS servers
|
|
314
|
+
RESOLVER_IPS=$(grep '^nameserver' /etc/resolv.conf | awk '{print $2}')
|
|
315
|
+
|
|
316
|
+
if [ -z "$RESOLVER_IPS" ]; then
|
|
317
|
+
echo "❌ ERROR: Could not detect DNS resolver from /etc/resolv.conf"
|
|
318
|
+
echo "Cannot configure secure DNS filtering without a resolver"
|
|
319
|
+
exit 1
|
|
320
|
+
fi
|
|
321
|
+
|
|
322
|
+
# Allow DNS ONLY to detected resolver IPs (SECURITY FIX)
|
|
323
|
+
# This prevents the OpenAI-style DNS tunneling attack where agents
|
|
324
|
+
# send DNS packets directly to attacker-controlled DNS servers
|
|
325
|
+
echo "Locking DNS queries to container's resolver(s):"
|
|
326
|
+
while IFS= read -r RESOLVER_IP; do
|
|
327
|
+
if [ -n "$RESOLVER_IP" ]; then
|
|
328
|
+
echo " $RESOLVER_IP (DNS)"
|
|
329
|
+
iptables -A OUTPUT -d $RESOLVER_IP -p udp --dport 53 -j ACCEPT
|
|
330
|
+
iptables -A OUTPUT -d $RESOLVER_IP -p tcp --dport 53 -j ACCEPT
|
|
331
|
+
fi
|
|
332
|
+
done <<< "$RESOLVER_IPS"
|
|
282
333
|
|
|
283
334
|
# Allow localhost
|
|
284
335
|
iptables -A OUTPUT -d 127.0.0.1/8 -j ACCEPT
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|