@llnvd/openclaw-url-guard
v0.3.1
Published
OpenClaw plugin for URL allowlisting/blocklisting in web_fetch and web_search tools
Downloads
1,007
Maintainers
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:
- The plugin extracts the URL from the request
- Checks it against your configured allowlist/blocklist policy
- Optionally queries URLhaus threat feed
- Optionally applies trust scoring
- 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
npm install @llnvd/openclaw-url-guardOr from git:
git clone https://codeberg.org/llnvd/openclaw-url-guard.git
cd openclaw-url-guard
npm install
npm run build
openclaw plugins install .Quick Start
Add to your OpenClaw config (~/.openclaw/openclaw.json):
{
"plugins": {
"entries": {
"openclaw-url-guard": {
"enabled": true,
"config": {
"mode": "allowlist",
"allowlist": [
"docs.python.org",
"developer.mozilla.org",
"en.wikipedia.org",
"github.com",
"stackoverflow.com",
"*.stackexchange.com"
],
"blockPrivateIps": true
}
}
}
}
}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 |
Basic Options
{
"mode": "allowlist",
"allowlist": ["github.com", "*.githubusercontent.com"],
"blocklist": ["evil.com"],
"blockPrivateIps": true
}- allowlist/blocklist: Hostname patterns. Use
*.domain.comfor wildcard subdomains. - blockPrivateIps: Block requests to private/internal IPs (default:
true)
Threat Feeds
Enable URLhaus threat feed lookups:
{
"mode": "allowlist",
"allowlist": ["*"],
"threatFeeds": {
"urlhaus": true,
"mode": "fail-open"
}
}urlhaus: Enable URLhaus API lookupsmode:fail-open(allow on API failure) orfail-closed(block on API failure)
SSRF Protections
SSRF protections are enabled by default. Configure if needed:
{
"ssrf": {
"validateDns": true,
"dnsTimeoutMs": 5000,
"validateRedirects": true,
"maxRedirects": 10,
"allowProtocolDowngrade": false
}
}validateDns: Resolve hostnames and block if any IP is private/reservedvalidateRedirects: Validate each redirect hop against policy + DNSallowProtocolDowngrade: 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:
{
"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 for details.
Trust Scoring
Optional scoring system for fine-grained control:
{
"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:
+10to+7: Trusted (skip threat feed checks)+6to+3: Preferred+2to-2: Neutral-3to-6: Suspicious-7to-10: Blocked
Note: Policy (allowlist/blocklist) is always enforced first. A blocked URL cannot bypass policy with a high score.
Security Defaults
- Only
http://andhttps://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:
{
"logging": {
"enabled": true,
"logBlocked": true,
"verboseErrors": true
}
}Development
npm install
npm run build
npm testRun E2E tests:
npm run test:e2eDocumentation
License
MIT
