@llnvd/openclaw-url-guard 0.0.1
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.
- package/.forgejo/workflows/ci.yaml +117 -0
- package/.husky/pre-commit +1 -0
- package/.oxlintrc.json +14 -0
- package/.prettierignore +3 -0
- package/.prettierrc +7 -0
- package/CONTRIBUTING.md +173 -0
- package/LICENSE +21 -0
- package/README.md +191 -0
- package/TASK.md +39 -0
- package/dist/package.json +39 -0
- package/dist/src/config.d.ts +150 -0
- package/dist/src/config.js +206 -0
- package/dist/src/filters/matcher.d.ts +6 -0
- package/dist/src/filters/matcher.js +111 -0
- package/dist/src/filters/urlhaus.d.ts +8 -0
- package/dist/src/filters/urlhaus.js +141 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +16 -0
- package/dist/src/scoring/engine.d.ts +2 -0
- package/dist/src/scoring/engine.js +118 -0
- package/dist/src/tools/safeFetch.d.ts +2 -0
- package/dist/src/tools/safeFetch.js +121 -0
- package/dist/src/tools/safeSearch.d.ts +2 -0
- package/dist/src/tools/safeSearch.js +81 -0
- package/dist/src/types.d.ts +99 -0
- package/dist/src/types.js +2 -0
- package/docs/AGENT-INSTALL.md +118 -0
- package/docs/DEPLOY_GIST.md +84 -0
- package/docs/README.md +40 -0
- package/docs/api-reference.md +274 -0
- package/docs/configuration.md +218 -0
- package/docs/openclaw-integration.md +155 -0
- package/docs/scoring.md +81 -0
- package/docs/testing.md +53 -0
- package/docs/usage-modes.md +127 -0
- package/examples/openclaw-config-avoid-sites.yaml +49 -0
- package/examples/openclaw-config-learning-sites.yaml +43 -0
- package/examples/openclaw-config-scoring.yaml +43 -0
- package/openclaw.plugin.json +66 -0
- package/openspec/changes/e2e-real-openclaw-tests/design.md +106 -0
- package/openspec/changes/e2e-real-openclaw-tests/proposal.md +35 -0
- package/openspec/changes/e2e-real-openclaw-tests/specs/e2e-real-instance/spec.md +197 -0
- package/openspec/changes/e2e-real-openclaw-tests/tasks.md +34 -0
- package/openspec/config.yaml +8 -0
- package/openspec/specs/e2e-real-instance/spec.md +197 -0
- package/package.json +39 -0
- package/src/config.ts +228 -0
- package/src/filters/matcher.ts +126 -0
- package/src/filters/urlhaus.ts +170 -0
- package/src/index.ts +14 -0
- package/src/scoring/engine.ts +144 -0
- package/src/tools/safeFetch.ts +163 -0
- package/src/tools/safeSearch.ts +108 -0
- package/src/types.ts +136 -0
- package/tests/e2e/cases/backward-compat.test.ts +22 -0
- package/tests/e2e/cases/blocklist-block.test.ts +18 -0
- package/tests/e2e/cases/scoring-suspicious.test.ts +30 -0
- package/tests/e2e/cases/trusted-bypass.test.ts +31 -0
- package/tests/e2e/cases/urlhaus-live.test.ts +33 -0
- package/tests/e2e/fixtures/config.ts +60 -0
- package/tests/e2e/fixtures/test-urls.ts +5 -0
- package/tests/e2e/harness.ts +73 -0
- package/tests/integration/allowlist.test.ts +87 -0
- package/tests/integration/blocklist.test.ts +48 -0
- package/tests/integration/bypass-protection.test.ts +151 -0
- package/tests/integration/config-validation.test.ts +55 -0
- package/tests/integration/error-handling.test.ts +57 -0
- package/tests/integration/fixtures/urlhaus-sample.csv +6 -0
- package/tests/integration/helpers/client.ts +185 -0
- package/tests/integration/helpers/config.ts +103 -0
- package/tests/integration/helpers/gateway.ts +185 -0
- package/tests/integration/helpers/test-mode.ts +20 -0
- package/tests/integration/hybrid.test.ts +56 -0
- package/tests/integration/ssrf.test.ts +61 -0
- package/tests/integration/urlhaus.test.ts +56 -0
- package/tests/integration.test.ts +72 -0
- package/tests/matcher.test.ts +62 -0
- package/tests/safeFetch.test.ts +247 -0
- package/tests/safeSearch.test.ts +80 -0
- package/tests/scoring.test.ts +106 -0
- package/tests/security.test.ts +130 -0
- package/tests/urlhaus.test.ts +124 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
name: Lint & Format
|
|
11
|
+
runs-on: codeberg-tiny
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout
|
|
14
|
+
uses: https://code.forgejo.org/actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Setup Node.js
|
|
17
|
+
uses: https://code.forgejo.org/actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: "20"
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: npm ci
|
|
23
|
+
|
|
24
|
+
- name: Lint
|
|
25
|
+
run: npm run lint
|
|
26
|
+
|
|
27
|
+
- name: Format check
|
|
28
|
+
run: npm run format:check
|
|
29
|
+
|
|
30
|
+
build:
|
|
31
|
+
name: Build
|
|
32
|
+
runs-on: codeberg-tiny
|
|
33
|
+
steps:
|
|
34
|
+
- name: Checkout
|
|
35
|
+
uses: https://code.forgejo.org/actions/checkout@v4
|
|
36
|
+
|
|
37
|
+
- name: Setup Node.js
|
|
38
|
+
uses: https://code.forgejo.org/actions/setup-node@v4
|
|
39
|
+
with:
|
|
40
|
+
node-version: "20"
|
|
41
|
+
|
|
42
|
+
- name: Install dependencies
|
|
43
|
+
run: npm ci
|
|
44
|
+
|
|
45
|
+
- name: Build
|
|
46
|
+
run: npm run build
|
|
47
|
+
|
|
48
|
+
test-unit:
|
|
49
|
+
name: Unit Tests
|
|
50
|
+
runs-on: codeberg-small
|
|
51
|
+
needs: [lint, build]
|
|
52
|
+
steps:
|
|
53
|
+
- name: Checkout
|
|
54
|
+
uses: https://code.forgejo.org/actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Setup Node.js
|
|
57
|
+
uses: https://code.forgejo.org/actions/setup-node@v4
|
|
58
|
+
with:
|
|
59
|
+
node-version: "20"
|
|
60
|
+
|
|
61
|
+
- name: Install dependencies
|
|
62
|
+
run: npm ci
|
|
63
|
+
|
|
64
|
+
- name: Build
|
|
65
|
+
run: npm run build
|
|
66
|
+
|
|
67
|
+
- name: Run unit tests
|
|
68
|
+
run: npm test -- --exclude 'tests/e2e/**'
|
|
69
|
+
|
|
70
|
+
test-e2e:
|
|
71
|
+
name: E2E Tests
|
|
72
|
+
runs-on: codeberg-small
|
|
73
|
+
needs: [lint, build]
|
|
74
|
+
steps:
|
|
75
|
+
- name: Checkout
|
|
76
|
+
uses: https://code.forgejo.org/actions/checkout@v4
|
|
77
|
+
|
|
78
|
+
- name: Setup Node.js
|
|
79
|
+
uses: https://code.forgejo.org/actions/setup-node@v4
|
|
80
|
+
with:
|
|
81
|
+
node-version: "20"
|
|
82
|
+
|
|
83
|
+
- name: Install dependencies
|
|
84
|
+
run: npm ci
|
|
85
|
+
|
|
86
|
+
- name: Build
|
|
87
|
+
run: npm run build
|
|
88
|
+
|
|
89
|
+
- name: Run E2E tests
|
|
90
|
+
run: npm run test:e2e
|
|
91
|
+
|
|
92
|
+
test-integration-real:
|
|
93
|
+
name: Integration Tests (Real Gateway)
|
|
94
|
+
runs-on: codeberg-small
|
|
95
|
+
needs: [test-unit, test-e2e]
|
|
96
|
+
timeout-minutes: 5
|
|
97
|
+
# Only run on main branch pushes (not PRs)
|
|
98
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
99
|
+
steps:
|
|
100
|
+
- name: Checkout
|
|
101
|
+
uses: https://code.forgejo.org/actions/checkout@v4
|
|
102
|
+
|
|
103
|
+
- name: Setup Node.js
|
|
104
|
+
uses: https://code.forgejo.org/actions/setup-node@v4
|
|
105
|
+
with:
|
|
106
|
+
node-version: "20"
|
|
107
|
+
|
|
108
|
+
- name: Install dependencies
|
|
109
|
+
run: npm ci
|
|
110
|
+
|
|
111
|
+
- name: Build
|
|
112
|
+
run: npm run build
|
|
113
|
+
|
|
114
|
+
- name: Run integration tests with real gateway
|
|
115
|
+
run: npm run test:integration
|
|
116
|
+
env:
|
|
117
|
+
INTEGRATION_TESTS: "true"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
package/.oxlintrc.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/crates/oxc_linter/schemas/config.schema.json",
|
|
3
|
+
"plugins": ["typescript"],
|
|
4
|
+
"rules": {
|
|
5
|
+
"no-unused-vars": "warn",
|
|
6
|
+
"no-console": "off",
|
|
7
|
+
"eqeqeq": "error",
|
|
8
|
+
"no-var": "error",
|
|
9
|
+
"prefer-const": "warn",
|
|
10
|
+
"typescript/no-explicit-any": "warn",
|
|
11
|
+
"typescript/no-unused-vars": "warn"
|
|
12
|
+
},
|
|
13
|
+
"ignorePatterns": ["dist/", "node_modules/", "*.js"]
|
|
14
|
+
}
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Contributing to openclaw-url-guard
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Clone the repository
|
|
7
|
+
git clone https://codeberg.org/llnvd/openclaw-url-guard.git
|
|
8
|
+
cd openclaw-url-guard
|
|
9
|
+
|
|
10
|
+
# Install dependencies
|
|
11
|
+
npm install
|
|
12
|
+
|
|
13
|
+
# Build
|
|
14
|
+
npm run build
|
|
15
|
+
|
|
16
|
+
# Run tests
|
|
17
|
+
npm test
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Code Quality
|
|
21
|
+
|
|
22
|
+
This project uses strict linting enforced by pre-commit hooks.
|
|
23
|
+
|
|
24
|
+
### Tools
|
|
25
|
+
|
|
26
|
+
- **oxlint** — Fast Rust-based linter (71 rules)
|
|
27
|
+
- **prettier** — Code formatting
|
|
28
|
+
- **husky + lint-staged** — Pre-commit enforcement
|
|
29
|
+
|
|
30
|
+
### Commands
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Run linter
|
|
34
|
+
npm run lint
|
|
35
|
+
|
|
36
|
+
# Fix auto-fixable issues
|
|
37
|
+
npm run lint:fix
|
|
38
|
+
|
|
39
|
+
# Format code
|
|
40
|
+
npm run format
|
|
41
|
+
|
|
42
|
+
# Check formatting
|
|
43
|
+
npm run format:check
|
|
44
|
+
|
|
45
|
+
# Run all checks (lint + format + test)
|
|
46
|
+
npm run check
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Pre-commit Hook
|
|
50
|
+
|
|
51
|
+
Every commit automatically runs:
|
|
52
|
+
1. `oxlint --fix` on staged `.ts` files
|
|
53
|
+
2. `prettier --write` on staged `.ts` files
|
|
54
|
+
|
|
55
|
+
If linting fails, the commit is rejected. Fix the issues and try again.
|
|
56
|
+
|
|
57
|
+
## Project Structure
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
src/
|
|
61
|
+
├── index.ts # Plugin entry point
|
|
62
|
+
├── config.ts # Configuration types and defaults
|
|
63
|
+
├── types.ts # TypeScript interfaces
|
|
64
|
+
├── tools/
|
|
65
|
+
│ ├── safeFetch.ts # safe_web_fetch implementation
|
|
66
|
+
│ └── safeSearch.ts # safe_web_search implementation
|
|
67
|
+
└── filters/
|
|
68
|
+
├── matcher.ts # URL/hostname matching logic
|
|
69
|
+
└── urlhaus.ts # URLhaus threat feed integration
|
|
70
|
+
|
|
71
|
+
tests/
|
|
72
|
+
└── matcher.test.ts # Unit tests for matching logic
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Adding New Threat Feeds
|
|
76
|
+
|
|
77
|
+
Threat feeds live in `src/filters/`. To add a new feed:
|
|
78
|
+
|
|
79
|
+
1. Create a new file (e.g., `src/filters/phishtank.ts`)
|
|
80
|
+
2. Implement the `ThreatFeed` interface:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
export interface ThreatFeed {
|
|
84
|
+
name: string;
|
|
85
|
+
update(): Promise<void>;
|
|
86
|
+
isBlocked(url: string): boolean;
|
|
87
|
+
getLastUpdate(): Date | null;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
3. Register it in `src/filters/index.ts`
|
|
92
|
+
4. Add configuration options to `src/config.ts`
|
|
93
|
+
5. Add tests in `tests/`
|
|
94
|
+
|
|
95
|
+
### Feed Implementation Example
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { ThreatFeed } from '../types';
|
|
99
|
+
|
|
100
|
+
export class PhishTankFeed implements ThreatFeed {
|
|
101
|
+
name = 'phishtank';
|
|
102
|
+
private blockedUrls = new Set<string>();
|
|
103
|
+
private lastUpdate: Date | null = null;
|
|
104
|
+
|
|
105
|
+
async update(): Promise<void> {
|
|
106
|
+
// Fetch feed from https://phishtank.org/
|
|
107
|
+
// Parse and populate this.blockedUrls
|
|
108
|
+
this.lastUpdate = new Date();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
isBlocked(url: string): boolean {
|
|
112
|
+
return this.blockedUrls.has(url);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getLastUpdate(): Date | null {
|
|
116
|
+
return this.lastUpdate;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Testing
|
|
122
|
+
|
|
123
|
+
We use [Vitest](https://vitest.dev/) for testing.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
# Run all tests
|
|
127
|
+
npm test
|
|
128
|
+
|
|
129
|
+
# Run tests in watch mode
|
|
130
|
+
npm run test:watch
|
|
131
|
+
|
|
132
|
+
# Run specific test file
|
|
133
|
+
npx vitest run tests/matcher.test.ts
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Writing Tests
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { describe, it, expect } from 'vitest';
|
|
140
|
+
import { matchHostname } from '../src/filters/matcher';
|
|
141
|
+
|
|
142
|
+
describe('matchHostname', () => {
|
|
143
|
+
it('matches exact domains', () => {
|
|
144
|
+
expect(matchHostname('example.com', 'example.com')).toBe(true);
|
|
145
|
+
expect(matchHostname('example.com', 'other.com')).toBe(false);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Pull Requests
|
|
151
|
+
|
|
152
|
+
1. Fork the repository
|
|
153
|
+
2. Create a feature branch (`git checkout -b feat/my-feature`)
|
|
154
|
+
3. Make your changes
|
|
155
|
+
4. Ensure tests pass (`npm run check`)
|
|
156
|
+
5. Commit with conventional commit messages
|
|
157
|
+
6. Push and open a PR
|
|
158
|
+
|
|
159
|
+
### Commit Message Format
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
type: description
|
|
163
|
+
|
|
164
|
+
feat: add PhishTank threat feed support
|
|
165
|
+
fix: handle URLs with ports correctly
|
|
166
|
+
docs: update configuration examples
|
|
167
|
+
chore: update dependencies
|
|
168
|
+
test: add edge case tests for wildcards
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Questions?
|
|
172
|
+
|
|
173
|
+
Open an issue on [Codeberg](https://codeberg.org/llnvd/openclaw-url-guard/issues).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 llnvd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# openclaw-url-guard
|
|
2
|
+
|
|
3
|
+
OpenClaw plugin that guards web tool access with hostname allowlist/blocklist policy.
|
|
4
|
+
|
|
5
|
+
> ⚠️ **Disclaimer:** This project is a proof of concept (PoC). It is provided "as is" without
|
|
6
|
+
> warranty of any kind. We make no guarantees about its security, reliability, or fitness for
|
|
7
|
+
> any particular purpose. Use at your own risk.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
### From Git (recommended for now)
|
|
12
|
+
|
|
13
|
+
The npm package is not yet published. Install directly from Codeberg:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Clone and build
|
|
17
|
+
git clone https://codeberg.org/llnvd/openclaw-url-guard.git
|
|
18
|
+
cd openclaw-url-guard
|
|
19
|
+
npm install
|
|
20
|
+
npm run build
|
|
21
|
+
|
|
22
|
+
# Install as OpenClaw plugin (from the repo directory)
|
|
23
|
+
openclaw plugins install .
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or install directly via npm/git URL:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install git+https://codeberg.org/llnvd/openclaw-url-guard.git
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### From npm (once published)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install @llnvd/openclaw-url-guard
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start (Secure Installation)
|
|
39
|
+
|
|
40
|
+
This plugin provides guarded alternatives to the native `web_fetch` and `web_search` tools.
|
|
41
|
+
**For full protection, you must disable the native tools** — otherwise the LLM can bypass
|
|
42
|
+
the guard by calling the unprotected tools directly.
|
|
43
|
+
|
|
44
|
+
Add to OpenClaw config (`~/.openclaw/openclaw.json`):
|
|
45
|
+
|
|
46
|
+
```json5
|
|
47
|
+
{
|
|
48
|
+
// Disable native web tools (required for security)
|
|
49
|
+
"tools": {
|
|
50
|
+
"deny": ["web_fetch", "web_search"]
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
// Enable the url-guard plugin
|
|
54
|
+
"plugins": {
|
|
55
|
+
"entries": {
|
|
56
|
+
"@llnvd/openclaw-url-guard": {
|
|
57
|
+
"enabled": true,
|
|
58
|
+
"config": {
|
|
59
|
+
"mode": "allowlist",
|
|
60
|
+
"allowlist": [
|
|
61
|
+
"docs.python.org",
|
|
62
|
+
"developer.mozilla.org",
|
|
63
|
+
"en.wikipedia.org",
|
|
64
|
+
"github.com",
|
|
65
|
+
"stackoverflow.com"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This configuration:
|
|
75
|
+
1. **Denies** the native `web_fetch` and `web_search` tools (they won't be sent to the LLM)
|
|
76
|
+
2. **Enables** the plugin's `safe_web_fetch` and `safe_web_search` as the only web access tools
|
|
77
|
+
|
|
78
|
+
The guarded tools:
|
|
79
|
+
- `safe_web_fetch` — fetches URLs through the policy filter
|
|
80
|
+
- `safe_web_search` — searches the web and filters results by policy
|
|
81
|
+
|
|
82
|
+
> **⚠️ Security Note:** Without `tools.deny`, the native tools remain available and a
|
|
83
|
+
> prompt injection attack could instruct the LLM to use `web_fetch` instead of
|
|
84
|
+
> `safe_web_fetch`, completely bypassing the guard.
|
|
85
|
+
|
|
86
|
+
Optional threat intel feed settings:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
plugins:
|
|
90
|
+
- name: "@llnvd/openclaw-url-guard"
|
|
91
|
+
config:
|
|
92
|
+
mode: allowlist
|
|
93
|
+
allowlist:
|
|
94
|
+
- docs.python.org
|
|
95
|
+
threatFeeds:
|
|
96
|
+
urlhaus: true
|
|
97
|
+
mode: fail-open # default: fail-open, alternative: fail-closed
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
URLhaus behavior:
|
|
101
|
+
|
|
102
|
+
- applies to `safe_web_fetch` only
|
|
103
|
+
- runs after local allowlist/blocklist checks pass
|
|
104
|
+
- blocks when URLhaus lists the URL
|
|
105
|
+
- on URLhaus API/network failure:
|
|
106
|
+
- `fail-open`: allow request
|
|
107
|
+
- `fail-closed`: block request
|
|
108
|
+
|
|
109
|
+
## Security Defaults
|
|
110
|
+
|
|
111
|
+
- only `http://` and `https://` URLs are accepted
|
|
112
|
+
- private/internal IP targets are blocked by default (`blockPrivateIps: true`)
|
|
113
|
+
- URLhaus lookups time out after 5 seconds to avoid hanging requests
|
|
114
|
+
- blocked tool responses are minimal by default; set `logging.verboseErrors: true` for detailed reasons and score metadata
|
|
115
|
+
|
|
116
|
+
## Trust Scoring (Issue #3)
|
|
117
|
+
|
|
118
|
+
Optional trust scoring replaces binary allow/block with a score range from `+10` to `-10`.
|
|
119
|
+
|
|
120
|
+
- `+10` to `+7`: Trusted (always allow, skips threat feed checks)
|
|
121
|
+
- `+6` to `+3`: Preferred (allow, still check threat feeds)
|
|
122
|
+
- `+2` to `-2`: Neutral
|
|
123
|
+
- `-3` to `-6`: Suspicious (allow with warning when logging is enabled)
|
|
124
|
+
- `-7` to `-9`: Risky (blocked by default)
|
|
125
|
+
- `-10`: Forbidden (always blocked)
|
|
126
|
+
|
|
127
|
+
Scoring is disabled by default for backward compatibility. Enable it with:
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
plugins:
|
|
131
|
+
- name: "@llnvd/openclaw-url-guard"
|
|
132
|
+
config:
|
|
133
|
+
mode: allowlist
|
|
134
|
+
scoring:
|
|
135
|
+
enabled: true
|
|
136
|
+
defaultScore: 0
|
|
137
|
+
minScore: -6
|
|
138
|
+
rules:
|
|
139
|
+
- domain: github.com
|
|
140
|
+
score: 8
|
|
141
|
+
reason: trusted source
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Documentation
|
|
145
|
+
|
|
146
|
+
- [Documentation Index](./docs/README.md)
|
|
147
|
+
- [OpenClaw Integration](./docs/openclaw-integration.md) — **start here**
|
|
148
|
+
- [Agent Installation Guide](./docs/AGENT-INSTALL.md) — for AI agents installing this plugin
|
|
149
|
+
- [API Reference](./docs/api-reference.md)
|
|
150
|
+
- [Configuration](./docs/configuration.md)
|
|
151
|
+
- [Trust Scoring](./docs/scoring.md)
|
|
152
|
+
- [Testing](./docs/testing.md)
|
|
153
|
+
- [Usage Modes](./docs/usage-modes.md)
|
|
154
|
+
|
|
155
|
+
## Development
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm test
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Run E2E tests only:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
npm run test:e2e
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Enable live URLhaus network E2E test:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
E2E_NETWORK_TESTS=true npm run test:e2e
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for contributor workflow.
|
|
174
|
+
|
|
175
|
+
## CI Pipeline
|
|
176
|
+
|
|
177
|
+
This project uses Codeberg Actions (Forgejo Actions) for continuous integration.
|
|
178
|
+
|
|
179
|
+
| Job | Runner | Trigger | Description |
|
|
180
|
+
|-----|--------|---------|-------------|
|
|
181
|
+
| Lint & Format | `codeberg-tiny` | push, PR | oxlint + prettier |
|
|
182
|
+
| Build | `codeberg-tiny` | push, PR | TypeScript compilation |
|
|
183
|
+
| Unit Tests | `codeberg-small` | push, PR | Core functionality tests |
|
|
184
|
+
| E2E Tests | `codeberg-small` | push, PR | Integration test harness |
|
|
185
|
+
| Live Feed Tests | `codeberg-small` | main push only | URLhaus network tests |
|
|
186
|
+
|
|
187
|
+
Workflow: [`.forgejo/workflows/ci.yaml`](./.forgejo/workflows/ci.yaml)
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT
|
package/TASK.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Task: Improve Documentation for openclaw-url-guard Plugin
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
Enhance the documentation for the openclaw-url-guard plugin to improve clarity, usability, and completeness.
|
|
5
|
+
|
|
6
|
+
## Scope
|
|
7
|
+
- Improve README.md with comprehensive documentation
|
|
8
|
+
- Add detailed configuration explanations
|
|
9
|
+
- Include practical usage examples
|
|
10
|
+
- Document security considerations
|
|
11
|
+
- Add development and contribution guidelines
|
|
12
|
+
|
|
13
|
+
## Current Issues
|
|
14
|
+
The existing documentation was basic and lacked:
|
|
15
|
+
- Detailed configuration explanations
|
|
16
|
+
- Practical usage examples for different modes
|
|
17
|
+
- Security considerations
|
|
18
|
+
- Clear organization and structure
|
|
19
|
+
- Usage of wildcards and threat feeds
|
|
20
|
+
|
|
21
|
+
## Improvements Made
|
|
22
|
+
1. Enhanced README.md with:
|
|
23
|
+
- Better organization and structure
|
|
24
|
+
- Detailed configuration explanations with all options documented
|
|
25
|
+
- Usage examples for different modes (allowlist, blocklist, hybrid)
|
|
26
|
+
- Security considerations
|
|
27
|
+
- Development and contribution guidelines
|
|
28
|
+
- Clear examples with wildcards and threat feeds
|
|
29
|
+
|
|
30
|
+
2. Maintained existing functionality while improving clarity
|
|
31
|
+
|
|
32
|
+
## Documentation Structure
|
|
33
|
+
The improved documentation now includes:
|
|
34
|
+
- Plugin overview and features
|
|
35
|
+
- Clear installation instructions
|
|
36
|
+
- Comprehensive configuration schema documentation
|
|
37
|
+
- Practical usage examples with different modes
|
|
38
|
+
- Security considerations
|
|
39
|
+
- Development and contribution guidelines
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@llnvd/openclaw-url-guard",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "OpenClaw plugin for URL allowlisting/blocklisting in web_fetch and web_search tools",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc -p tsconfig.json",
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"test:e2e": "vitest run tests/e2e/",
|
|
11
|
+
"test:integration": "INTEGRATION_TESTS=true vitest run tests/integration/",
|
|
12
|
+
"lint": "oxlint src/ tests/",
|
|
13
|
+
"lint:fix": "oxlint --fix src/ tests/",
|
|
14
|
+
"format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts'",
|
|
15
|
+
"format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts'",
|
|
16
|
+
"check": "npm run lint && npm run format:check && npm run test",
|
|
17
|
+
"prepare": "husky"
|
|
18
|
+
},
|
|
19
|
+
"lint-staged": {
|
|
20
|
+
"*.ts": [
|
|
21
|
+
"oxlint --fix",
|
|
22
|
+
"prettier --write"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^25.3.5",
|
|
27
|
+
"husky": "^9.1.7",
|
|
28
|
+
"lint-staged": "^15.4.3",
|
|
29
|
+
"oxlint": "^1.51.0",
|
|
30
|
+
"prettier": "^3.5.3",
|
|
31
|
+
"typescript": "^5.6.3",
|
|
32
|
+
"vitest": "^2.1.8"
|
|
33
|
+
},
|
|
34
|
+
"openclaw": {
|
|
35
|
+
"extensions": [
|
|
36
|
+
"./dist/src/index.js"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|