# URL Security Measures in Agent-Reach: How Malicious Links Are Blocked

> Agent-Reach uses a four-layer defense system including host validation, allow-lists, credential scrubbing, and automated testing to block malicious URLs and protect your system.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: security
- Published: 2026-08-05

---

**Agent-Reach implements a four-layer defense system combining strict host validation, channel-specific allow-lists, credential scrubbing, and automated testing to prevent malicious URLs from compromising the system.**

Every external URL entering Agent-Reach is treated as **untrusted data**. The codebase applies rigorous parsing and validation before any network request occurs, ensuring that look-alike domains, credential leaks, and unsupported schemes are blocked at multiple checkpoints.

## Strict Host Validation with `host_matches()`

The core of URL security lives in [`agent_reach/utils/url.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/url.py). The `host_matches()` function implements **canonical host validation** through precise URL parsing and matching logic.

### How `host_matches()` Works

```python
from agent_reach.utils.url import host_matches

# Accepted: exact match or legitimate subdomain

assert host_matches("https://twitter.com/user/status/1", "twitter.com")
assert host_matches("https://m.twitter.com/status/1", "twitter.com")

# Rejected: look-alike attacks and credential injection

assert not host_matches("https://twitter.com.evil.test/status/1", "twitter.com")
assert not host_matches("https://twitter.com@evil.test/status/1", "twitter.com")
assert not host_matches("https://user:pass@twitter.com/status/1", "twitter.com")

```

According to the source code in [`agent_reach/utils/url.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/url.py) (lines 20-43), `host_matches()` performs:

- **Scheme restriction**: Only `http` and `https` are permitted — `ftp`, `file`, `javascript`, and other schemes are rejected immediately
- **User-info blocking**: Any URL containing `user:pass@` credentials fails validation
- **Port validation**: Non-standard or malformed ports trigger rejection
- **Subdomain normalization**: Uses `urllib.parse.urlsplit` to isolate the hostname, then validates against exact domain matches or legitimate subdomains

This prevents **homograph attacks** and **look-alike domains** such as `twitter.com.evil.test` or `twitter.com@evil.test` from bypassing filters.

## Channel-Specific Domain Guards

Each integration channel in Agent-Reach implements its own `can_handle()` method that calls `host_matches()` with platform-specific allow-lists. This creates **defense in depth** — even if one channel's configuration were compromised, others remain protected.

### Twitter Channel Example

In [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) (lines 40-42), the `can_handle()` method restricts processing to official Twitter domains:

```python
from agent_reach.channels.twitter import TwitterChannel

channel = TwitterChannel()

# Official domains are accepted

print(channel.can_handle("https://x.com/user/status/1"))      # True

print(channel.can_handle("https://twitter.com/user/status/1")) # True

# Impostors are rejected

print(channel.can_handle("https://x.com.evil.com/status/1"))  # False

```

The `can_handle()` pattern is replicated across all credential-bearing channels, ensuring that each URL is validated against the **explicit domain whitelist** for its intended platform before any processing occurs.

## Credential Scrubbing for Safe Logging

Even validated URLs may contain sensitive parameters. Before any URL appears in logs, error messages, or user-facing output, `scrub_url_credentials()` in [`agent_reach/utils/text.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/text.py) (lines 24-29) applies **aggressive redaction**:

```python
from agent_reach.utils.text import scrub_url_credentials

raw = "Failed to fetch https://user:secret@api.example.com/data?access_token=abcd1234"
clean = scrub_url_credentials(raw)

print(clean)

# Output: "Failed to fetch https://***@api.example.com/data?access_token=***"

```

This function removes:

- **User-info components**: `username:password@` → `***@`
- **Password-like query parameters**: `api_key`, `access_token`, `secret`, and similar patterns

By scrubbing credentials at the logging layer, Agent-Reach prevents **accidental secret exposure** even if a malformed URL somehow reaches the system.

## Automated Security Testing

The [`tests/test_url_security.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_url_security.py) suite provides **continuous verification** of all URL security measures. This test-driven approach ensures that:

- Valid URLs for each channel are accepted
- Invalid schemes (`ftp://`, `file://`) are rejected
- Look-alike domains fail validation
- User-info injection is blocked
- Malformed ports trigger errors
- Credential scrubbing functions correctly

Tests run on every CI pass, preventing regression of security controls.

## How the Security Layers Interact

Agent-Reach URL security follows a **fail-fast pipeline**:

1. **Parse and validate** — `host_matches()` applies strict scheme, port, and hostname checks
2. **Channel gate** — `can_handle()` enforces platform-specific domain allow-lists
3. **Redact on output** — `scrub_url_credentials()` sanitizes any remaining URL before logging
4. **Verify continuously** — [`test_url_security.py`](https://github.com/Panniantong/Agent-Reach/blob/main/test_url_security.py) validates all paths automatically

Any failure at an early layer prevents the URL from progressing, minimizing attack surface.

## Summary

- **`host_matches()`** in [`agent_reach/utils/url.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/url.py) provides canonical host validation with strict scheme and credential blocking
- **Channel `can_handle()` methods** enforce platform-specific domain allow-lists for defense in depth
- **`scrub_url_credentials()`** in [`agent_reach/utils/text.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/text.py) prevents secret leakage in logs and error messages
- **[`test_url_security.py`](https://github.com/Panniantong/Agent-Reach/blob/main/test_url_security.py)** ensures all security controls remain effective through automated testing

## Frequently Asked Questions

### How does Agent-Reach prevent look-alike domain attacks?

`host_matches()` parses URLs with `urllib.parse.urlsplit` and validates hostnames against explicit allow-lists using exact or legitimate subdomain matching. This blocks attacks like `twitter.com.evil.test` or `x.com@evil.test` that attempt to spoof legitimate platforms.

### What happens if a URL contains embedded credentials?

The URL fails validation at the `host_matches()` layer if user-info (`user:pass@`) is present. Additionally, `scrub_url_credentials()` redacts any remaining credential-like patterns from URLs before they appear in logs or error messages, providing defense in depth.

### Which URL schemes does Agent-Reach accept?

Only `http` and `https` schemes are permitted. `host_matches()` rejects `ftp`, `file`, `javascript`, `data`, and all other schemes immediately upon parsing, preventing protocol-based attacks.

### Where is the URL security test suite located?

The dedicated test file [`tests/test_url_security.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_url_security.py) exercises acceptance and rejection paths for all credential-bearing channels. It validates that look-alikes, user-info, unsupported schemes, and malformed ports are properly blocked.