You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Network-policy denials currently collapse into the same plain 502 bad gateway response as DNS, TLS, timeout, and connection failures. This makes intentional private-network deployments difficult to diagnose even though netguard already knows that it rejected the resolved address.
This change:
returns typed BlockedAddressError values from netguard, with coarse reasons for private/reserved ranges and permanently blocked metadata endpoints;
maps those errors to the standard broker JSON response with error: network_policy_blocked while preserving the existing HTTP 502 status;
records network_policy_blocked in request logs for both HTTP requests and WebSocket handshakes;
gives operators actionable allowlist/private-range guidance without returning the resolved IP to an untrusted proxy client;
documents the response in the security guide, agent protocol, and embedded agent skill.
Example response for an intentional private destination:
{
"error": "network_policy_blocked",
"message": "The target resolved to an address blocked by Agent Vault's network policy. If access to this private or reserved address is intentional, add it to AGENT_VAULT_NETWORK_ALLOWLIST or set AGENT_VAULT_ALLOW_PRIVATE_RANGES=true."
}
Metadata endpoints receive distinct guidance that they are always blocked.
Type of change
Bug fix
New feature
Refactor / cleanup
Documentation
CI / build
Test plan
Existing tests pass (go test ./...)
Added/updated tests for new behavior
Manual testing (automated proxy integration coverage described below)
Validation completed:
go test ./...
go test -race ./internal/netguard ./internal/mitm
go vet ./...
golangci-lint v2.11.0 run --new-from-rev=origin/main ./... (0 issues)
go build -trimpath
git diff --check
Regression coverage verifies:
private-range and metadata denials remain distinguishable through wrapped transport errors;
plain HTTP proxy requests return 502, X-Agent-Vault-Proxy-Error: true, and network_policy_blocked;
request-log rows persist the new error code;
WebSocket upstream dials return and log the same policy-specific error;
private-range guidance mentions the supported operator controls;
metadata guidance does not suggest an allowlist bypass.
Security checklist
No secrets or credentials in code
No new unauthenticated endpoints
Input validation on new API surfaces (no new API surface)
Checked for OWASP top 10 (injection, XSS, etc.)
Security invariants
Netguard's blocked ranges, allowlist precedence, and DNS-rebinding protections are unchanged.
Cloud metadata endpoints remain blocked even when private ranges are enabled or the address is allowlisted.
The resolved blocked IP remains available in server-side diagnostics but is intentionally omitted from the client response.
Existing clients continue to receive HTTP 502; the change adds a structured broker error and actionable message.
Non-policy upstream failures retain the existing plain bad gateway / upstream_error behavior.
Coordination
#374 also updates SafeDialContext to add multi-address fallback. This PR's typed error is designed to survive normal Go error wrapping (errors.As), including joined/wrapped dial errors. The two branches touch nearby netguard code, so I am happy to rebase promptly if #374 lands first.
The PR makes outbound network-policy denials distinguishable from other upstream failures without weakening netguard’s SSRF controls.
Adds typed private-range and metadata-endpoint rejection reasons while preserving existing address validation and blocking precedence.
Returns and logs network_policy_blocked for HTTP, HTTPS, and WebSocket requests.
Adds regression coverage and documents operator remediation without exposing resolved addresses to clients.
Confidence Score: 5/5
The PR appears safe to merge and preserves the existing SSRF boundary while improving policy-denial diagnostics.
The typed-error refactor leaves address classification and guarded dialing unchanged, both HTTP and WebSocket paths recognize the new error, and response and request-log mappings remain consistent without exposing blocked IP addresses.
Important Files Changed
Filename
Overview
internal/netguard/netguard.go
Introduces typed block reasons while preserving metadata precedence, private-range allowlist behavior, all-address DNS validation, and rebinding-safe direct IP dialing.
internal/mitm/forward.go
Maps typed policy denials to the standard broker JSON response and matching request-log code while retaining generic handling for other upstream failures.
internal/mitm/websocket.go
Applies the same policy-specific response and logging behavior to WebSocket upstream dial failures.
internal/mitm/forward_test.go
Adds coverage for safe guidance, structured HTTP proxy responses, marker headers, and persisted policy error codes.
internal/mitm/websocket_test.go
Verifies that WebSocket policy denials produce the structured response and matching emitted error code.
internal/netguard/netguard_test.go
Verifies typed private-range and metadata errors while retaining existing block and allowlist invariants.
@infisical-cla-app I accepted the Infisical CLA using the @0xkaushik-ai GitHub account, but the cla/signed check is still showing the original action_required result from August 20. Could you please refresh or re-run the CLA check for this PR? Thank you.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #305.
Network-policy denials currently collapse into the same plain
502 bad gatewayresponse as DNS, TLS, timeout, and connection failures. This makes intentional private-network deployments difficult to diagnose even though netguard already knows that it rejected the resolved address.This change:
BlockedAddressErrorvalues from netguard, with coarse reasons for private/reserved ranges and permanently blocked metadata endpoints;error: network_policy_blockedwhile preserving the existing HTTP 502 status;network_policy_blockedin request logs for both HTTP requests and WebSocket handshakes;Example response for an intentional private destination:
{ "error": "network_policy_blocked", "message": "The target resolved to an address blocked by Agent Vault's network policy. If access to this private or reserved address is intentional, add it to AGENT_VAULT_NETWORK_ALLOWLIST or set AGENT_VAULT_ALLOW_PRIVATE_RANGES=true." }Metadata endpoints receive distinct guidance that they are always blocked.
Type of change
Test plan
go test ./...)Validation completed:
go test ./...go test -race ./internal/netguard ./internal/mitmgo vet ./...golangci-lint v2.11.0 run --new-from-rev=origin/main ./...(0 issues)go build -trimpathgit diff --checkRegression coverage verifies:
502,X-Agent-Vault-Proxy-Error: true, andnetwork_policy_blocked;Security checklist
Security invariants
bad gateway/upstream_errorbehavior.Coordination
#374 also updates
SafeDialContextto add multi-address fallback. This PR's typed error is designed to survive normal Go error wrapping (errors.As), including joined/wrapped dial errors. The two branches touch nearby netguard code, so I am happy to rebase promptly if #374 lands first.