Tools
Url Guard
OpenClaw plugin that guards web tool access with hostname allowlist/blocklist policy
Install
npm install
npm
Configuration Example
{
"plugins": {
"entries": {
"openclaw-url-guard": {
"enabled": true,
"config": {
"mode": "allowlist",
"allowlist": "preset:developer"
}
}
}
}
}
README
# openclaw-url-guard
OpenClaw plugin that guards web tool access with hostname allowlist/blocklist policy.
> ⚠️ **Disclaimer:** This project is a proof of concept (PoC). It is provided "as is" without
> warranty of any kind. We make no guarantees about its security, reliability, or fitness for
> any particular purpose. Use at your own risk.
## How It Works
This plugin uses OpenClaw's `before_tool_call` hook to intercept calls to `web_fetch` and
`web_search`. When either tool is called:
1. The plugin extracts the URL from the request
2. Checks it against your configured allowlist/blocklist policy
3. Optionally queries URLhaus threat feed
4. Optionally applies trust scoring
5. **Blocks** the call if the URL fails any check, or **allows** it to proceed
This approach is transparent to the LLM — it uses the standard `web_fetch` and `web_search`
tools, but they're guarded by your policy.
## Install
```bash
openclaw plugins install @llnvd/openclaw-url-guard
```
Then restart the gateway:
```bash
openclaw gateway restart
```
### Development Install
For local development or from git:
```bash
git clone https://github.com/clawosiris/openclaw-url-guard.git
cd openclaw-url-guard
npm install
npm run build
openclaw plugins install .
```
## Quick Start
After installation, configure the plugin in your OpenClaw config (`~/.openclaw/openclaw.json`):
```json
{
"plugins": {
"entries": {
"openclaw-url-guard": {
"enabled": true,
"config": {
"mode": "allowlist",
"allowlist": "preset:developer"
}
}
}
}
}
```
Restart the gateway and the plugin will automatically guard all `web_fetch` and `web_search` calls.
## Configuration
### Modes
| Mode | Description |
|------|-------------|
| `allowlist` | Only URLs matching the allowlist are allowed (default) |
| `blocklist` | All URLs allowed except those matching the blocklist |
| `hybrid` | URL must be in allowlist AND not in blocklist |
### Domain Presets
Use built-in presets for common use cases:
```json
{
"mode": "allowlist",
"allowlist": "preset:developer"
}
```
Available presets:
| Preset | Description |
|--------|-------------|
| `preset:minimal` | Original 5-domain list (docs.python.org, MDN, Wikipedia, GitHub, Stack Overflow) |
| `preset:docs` | Documentation sites (25+ domains) |
| `preset:code` | Code hosting (GitHub, GitLab, Codeberg, etc.) |
| `preset:packages` | Package registries (npm, PyPI, crates.io, etc.) |
| `preset:reference` | Reference sites (Wikipedia, Stack Overflow, W3C, etc.) |
| `preset:cloud` | Cloud provider docs (AWS, GCP, Azure, etc.) |
| `preset:ai` | AI/ML sites (OpenAI, Anthropic, Hugging Face, etc.) |
| `preset:developer` | Union of docs + code + packages + reference (recommended) |
| `preset:enterprise` | Developer + cloud |
| `preset:threats` | Blocklist preset for known threats |
Mix presets with custom domains:
```json
{
"mode": "allowlist",
"allowlist": ["preset:developer", "internal.company.com", "*.myorg.dev"]
}
```
### Basic Options
```json
{
"mode": "allowlist",
"allowlist": ["github.com", "*.githubusercontent.com"],
"blocklist": ["evil.com"],
"blockPrivateIps": true
}
```
- **allowlist/blocklist**: Hostname patterns, preset strings, or mixed arrays
- **blockPrivateIps**: Block requests to private/internal IPs (default: `true`)
### Threat Feeds
Enable URLhaus threat feed lookups:
```json
{
"mode": "allowlist",
"allowlist": ["*"],
"threatFeeds": {
"urlhaus": true,
"mode": "fail-open"
}
}
```
- `urlhaus`: Enable URLhaus API lookups
- `mode`: `fail-open` (allow on API failure) or `fail-closed` (block on API failure)
### SSRF Protections
SSRF protections are enabled by default. Configure if needed:
```json
{
"ssrf": {
"validateDns": true,
"dnsTimeoutMs": 5000,
"validateRedirects": true,
"maxRedirects": 10,
"allowProtocolDowngrade": false
}
}
```
- `validateDns`: Resolve hostnames and block if any IP is private/reserved
- `validateRedirects`: Validate each redirect hop against policy + DNS
- `allowProtocolDowngrade`: Allow HTTPS → HTTP redirects (not recommended)
### Per-Workspace Policies
Different workspaces can have different URL policies. Workspace policies are **restrictive-only** — they can tighten but never loosen the global policy:
```json
{
"mode": "allowlist",
"allowlist": ["github.com", "docs.python.org"],
"blocklist": ["malware.com"],
"workspaces": {
"/home/user/fintech-project": {
"allowlist": ["api.stripe.com"]
},
"/home/user/research": {
"blocklist": ["competitor.com"]
}
}
}
```
- **Allowlist intersection** — Workspace restricts global (only domains in BOTH allowed)
- **Blocklist union** — Workspace extends global (domains in EITHER blocked)
- **Exact path matching** — Policies apply to exact paths, not subdirectories
- **Mode inherited** — Workspaces cannot change the global mode
See [Configuration](./docs/configuration.md#per-workspace-policies) for details.
### Trust Scoring
Optional scoring system for fine-grained control:
```json
{
"mode": "allowlist",
"allowlist": ["*"],
"scoring": {
"enabled": true,
"defaultScore": 0,
"minScore": -6,
"rules": [
{ "domain": "github.com", "score": 10, "reason": "highly trusted" },
{ "domain": "*.sketch.com", "score": -5, "reason": "known suspicious" }
]
}
}
```
Score ranges:
- `+10` to `+7`: Trusted (skip threat feed checks)
- `+6` to `+3`: Preferred
- `+2` to `-2`: Neutral
- `-3` to `-6`: Suspicious
- `-7` to `-10`: Blocked
> **Note:** Policy (allowlist/blocklist) is **always enforced first**. A blocked URL cannot bypass policy with a high score.
## Security Defaults
- Only `http://` and `https://` protocols accepted
- Private/internal IP targets blocked by default
- SSRF protections enabled by default:
- DNS resolution validation (blocks hostnames resolving to private IPs)
- Redirect chain validation (validates each hop, blocks protocol downgrades)
- Hostname blocking (`localhost`, `*.local`)
- URLhaus lookups timeout after 5 seconds
- Invalid URLs are blocked
- **Policy is always enforced before scoring** — blocked URLs cannot bypass policy with high scores
## Logging
Enable verbose logging to see guard decisions:
```json
{
"logging": {
"enabled": true,
"logBlocked": true,
"verboseErrors": true
}
}
```
## Development
```bash
npm install
npm run build
npm test
```
Run E2E tests:
```bash
npm run test:e2e
```
## Documentation
- [Configuration](./docs/configuration.md)
- [API Reference](./docs/api-reference.md)
- [Trust Scoring](./docs/scoring.md)
- [Testing](./docs/testing.md)
## License
MIT
tools
Comments
Sign in to leave a comment