Skip to content

Commit f829691

Browse files
Enterprise Cookbook preview: OpenHands/enterprise-cookbook#14 (do not merge)
Preview of the Enterprise Cookbook pages produced by OpenHands/enterprise-cookbook#14 (Publish plugins and guardrails examples to the docs Cookbook tab), rendered from OpenHands/enterprise-cookbook@4132ef2. **Do not merge.** This draft exists only to get a Mintlify preview. It is updated on every push to the source PR and closed when that PR closes. Merged changes reach the docs through a separate `cookbook-sync` PR. _Opened automatically by the docs-preview workflow in OpenHands/enterprise-cookbook._
1 parent 605ea3e commit f829691

10 files changed

Lines changed: 1449 additions & 17 deletions

‎cookbook/command-blacklist.mdx‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
---
2-
title: Command blacklist
2+
title: Command Blacklist
33
description: Block known-dangerous shell commands with a PreToolUse hook bundled in a plugin. Everything not on the blocklist runs normally.
44
icon: shield-halved
55
---
66

7-
{/* GENERATED from OpenHands/enterprise-cookbook@main (command-blacklist/README.md). Edit the source, not this file. */}
7+
{/* GENERATED from OpenHands/enterprise-cookbook@4132ef20b8439104c9feb0849c49e24125ce8b66 (command-blacklist/README.md). Edit the source, not this file. */}
88

9-
<Card title="View source on GitHub" icon="github" href="https://github.com/OpenHands/enterprise-cookbook/tree/main/command-blacklist" horizontal />
9+
<Card title="View source on GitHub" icon="github" href="https://github.com/OpenHands/enterprise-cookbook/tree/4132ef20b8439104c9feb0849c49e24125ce8b66/command-blacklist" horizontal />
1010

1111
A self-contained example showing how to use **PreToolUse hooks** in a plugin to **blacklist dangerous shell commands**. When the agent tries to execute a risky command, the hook blocks it with helpful (and slightly snarky) feedback.
1212

1313
This example demonstrates the **blacklist approach**: block known dangerous patterns while allowing everything else to proceed normally.
1414

1515
## What's in the Box
1616

17-
The [`safety-guardian/`](https://github.com/OpenHands/enterprise-cookbook/tree/main/command-blacklist/safety-guardian) plugin bundles:
17+
The [`safety-guardian/`](https://github.com/OpenHands/enterprise-cookbook/tree/4132ef20b8439104c9feb0849c49e24125ce8b66/command-blacklist/safety-guardian) plugin bundles:
1818

1919
- **Hooks** (`hooks/hooks.json`) - PreToolUse hook that intercepts terminal commands
2020
- **Skill** (`skills/safety-guardian/SKILL.md`) - Documentation about what's protected
@@ -56,11 +56,11 @@ All other commands work normally - only these specific dangerous patterns are bl
5656
(So `rm -rf /tmp` is **not** blocked; use the `curl … | bash` demo below to see a block.)
5757
</Note>
5858

59-
## Try It
59+
## Run It
6060

6161
<Tabs>
6262
<Tab title="Load via API">
63-
Use the companion [`load-plugin`](https://github.com/OpenHands/enterprise-cookbook/tree/main/load-plugin) example:
63+
Use the companion [`load-plugin`](/cookbook/load-plugin) example:
6464

6565
```bash
6666
cd ../load-plugin
@@ -96,7 +96,7 @@ All other commands work normally - only these specific dangerous patterns are bl
9696

9797
## The Hook
9898

99-
The magic happens in [`hooks/hooks.json`](https://github.com/OpenHands/enterprise-cookbook/blob/main/command-blacklist/safety-guardian/hooks/hooks.json):
99+
The magic happens in [`hooks/hooks.json`](https://github.com/OpenHands/enterprise-cookbook/blob/4132ef20b8439104c9feb0849c49e24125ce8b66/command-blacklist/safety-guardian/hooks/hooks.json):
100100

101101
```json safety-guardian/hooks/hooks.json
102102
{
@@ -156,7 +156,7 @@ This example uses a **blacklist** approach:
156156
- ❌ **Con:** Can't catch every dangerous pattern
157157
- ❌ **Con:** Clever variations might slip through
158158

159-
For high-security scenarios, see the companion [`command-whitelist`](https://github.com/OpenHands/enterprise-cookbook/tree/main/command-whitelist) example that shows the **whitelist** approach (only allow explicitly approved commands).
159+
For high-security scenarios, see the companion [`command-whitelist`](/cookbook/command-whitelist) example that shows the **whitelist** approach (only allow explicitly approved commands).
160160

161161
## Hook Types
162162

@@ -201,15 +201,15 @@ This follows the **Claude Code plugin format**, compatible with:
201201
How plugins work
202202
</Card>
203203

204-
<Card title="load-plugin" href="https://github.com/OpenHands/enterprise-cookbook/tree/main/load-plugin" icon="arrow-up-right-from-square">
204+
<Card title="load-plugin" href="/cookbook/load-plugin" icon="plug">
205205
Programmatic plugin loading
206206
</Card>
207207

208-
<Card title="launch-plugin-badge" href="https://github.com/OpenHands/enterprise-cookbook/tree/main/launch-plugin-badge" icon="arrow-up-right-from-square">
208+
<Card title="launch-plugin-badge" href="/cookbook/launch-plugin-badge" icon="rocket">
209209
No-code plugin launcher
210210
</Card>
211211

212-
<Card title="command-whitelist" href="https://github.com/OpenHands/enterprise-cookbook/tree/main/command-whitelist" icon="arrow-up-right-from-square">
212+
<Card title="command-whitelist" href="/cookbook/command-whitelist" icon="shield-check">
213213
Whitelist approach (opposite strategy)
214214
</Card>
215215
</CardGroup>

‎cookbook/command-whitelist.mdx‎

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
---
2+
title: Command Whitelist
3+
description: Only allow approved shell commands with PreToolUse hooks (whitelist approach for strict security).
4+
icon: shield-check
5+
---
6+
7+
{/* GENERATED from OpenHands/enterprise-cookbook@4132ef20b8439104c9feb0849c49e24125ce8b66 (command-whitelist/README.md). Edit the source, not this file. */}
8+
9+
<Card title="View source on GitHub" icon="github" href="https://github.com/OpenHands/enterprise-cookbook/tree/4132ef20b8439104c9feb0849c49e24125ce8b66/command-whitelist" horizontal />
10+
11+
A self-contained example showing how to use **PreToolUse hooks** in a plugin to **whitelist approved shell commands**. The agent can only execute commands that are explicitly on the approved list - everything else is blocked.
12+
13+
This example demonstrates the **whitelist approach**: deny everything by default, only allow specific approved commands.
14+
15+
## What's in the Box
16+
17+
The [`strict-mode/`](https://github.com/OpenHands/enterprise-cookbook/tree/4132ef20b8439104c9feb0849c49e24125ce8b66/command-whitelist/strict-mode) plugin bundles:
18+
19+
- **Hooks** (`hooks/hooks.json`) - PreToolUse hook that validates commands against a whitelist
20+
- **Skill** (`skills/strict-mode/SKILL.md`) - Documentation about what's allowed
21+
- **Plugin manifest** (`.claude-plugin/plugin.json`) - Standard Claude Code plugin format
22+
23+
## How It Works
24+
25+
```text
26+
User: "Install the requests package with pip"
27+
↓
28+
Agent: *prepares terminal command: pip install requests*
29+
↓
30+
PreToolUse Hook: *intercepts before execution*
31+
├─ Extracts command name: "pip"
32+
├─ Checks whitelist: [ls, cat, grep, find, ...]
33+
├─ Not found in whitelist!
34+
└─ Returns exit code 2 (block) + explanation
35+
↓
36+
Agent: *receives block + reason, explains to user*
37+
↓
38+
User: *sees which commands are allowed*
39+
```
40+
41+
## Whitelisted Commands
42+
43+
Only these commands are allowed (all read-only operations):
44+
45+
**File Operations:** `ls`, `cat`, `head`, `tail`, `file`
46+
**Search & Filter:** `grep`, `find`, `wc`
47+
**System Info:** `pwd`, `whoami`, `date`, `uname`, `df`, `du`, `stat`
48+
**Utilities:** `echo`, `which`, `env`, `printenv`, `history`, `tree`
49+
50+
Everything else is **blocked by default**.
51+
52+
## Try It
53+
54+
### Option 1: Load via API
55+
56+
Use the companion [`load-plugin`](/cookbook/load-plugin) example:
57+
58+
```bash
59+
cd ../load-plugin
60+
61+
# This will be blocked (pip not whitelisted)
62+
python load_plugin.py \
63+
--repo-path command-whitelist/strict-mode \
64+
--message "Install the requests package"
65+
66+
# This will be allowed (ls is whitelisted)
67+
python load_plugin.py \
68+
--repo-path command-whitelist/strict-mode \
69+
--message "List all Python files in the current directory"
70+
```
71+
72+
### Option 2: Launch via Badge
73+
74+
Click to test strict mode:
75+
76+
[![Try Strict Mode](https://img.shields.io/badge/Try%20Strict%20Mode-blue)](https://app.all-hands.dev/launch?plugins=W3sic291cmNlIjogImdpdGh1YjpPcGVuSGFuZHMvZW50ZXJwcmlzZS1jb29rYm9vayIsICJyZWYiOiAibWFpbiIsICJyZXBvX3BhdGgiOiAiY29tbWFuZC13aGl0ZWxpc3Qvc3RyaWN0LW1vZGUifV0%3D\&message=Install%20the%20requests%20package)
77+
78+
<Tip>
79+
To test the plugin from a branch before it's merged, pass `--ref <branch>` to `load_plugin.py`.
80+
</Tip>
81+
82+
## The Hook
83+
84+
The magic happens in [`hooks/hooks.json`](https://github.com/OpenHands/enterprise-cookbook/blob/4132ef20b8439104c9feb0849c49e24125ce8b66/command-whitelist/strict-mode/hooks/hooks.json):
85+
86+
```json
87+
{
88+
"hooks": {
89+
"PreToolUse": [
90+
{
91+
"matcher": "terminal",
92+
"hooks": [
93+
{
94+
"type": "command",
95+
"command": "input=$(cat)\n# ... POSIX-sh whitelist check ...\nexit 0",
96+
"timeout": 5
97+
}
98+
]
99+
}
100+
]
101+
}
102+
}
103+
```
104+
105+
**How it works:**
106+
107+
1. **`PreToolUse`** - Runs **before** the terminal tool executes
108+
2. **`matcher: "terminal"`** - Only applies to shell commands
109+
3. **Inline POSIX-sh script** (run via `/bin/sh -c`; kept inline rather than a
110+
`bash -c '...'` wrapper or an external `.sh` file — see the note in the
111+
[command-blacklist README](/cookbook/command-blacklist#the-hook) for why):
112+
- Extracts the command name from the JSON input
113+
- Checks if it's in the hardcoded whitelist
114+
- Returns `exit 0` (allow) or `exit 2` (block, with a `{"decision":"deny",...}` reason)
115+
116+
The whitelist is maintained as a simple space-separated list in the script:
117+
118+
```sh
119+
allowed="ls cat grep find head tail wc echo pwd whoami date uname df du tree file which env printenv history stat"
120+
```
121+
122+
## Whitelist vs. Blacklist
123+
124+
| Approach | Strategy | Security | Usability | Best For |
125+
| ------------------------------------------------------------------ | -------------------------------- | ----------------------------------------------- | -------------------------------------------- | ------------------------------------- |
126+
| **Whitelist** (this) | Deny by default, allow specific | ✅ **High** - Can't execute unexpected commands | ⚠️ **Limited** - Must pre-approve everything | High-security, read-only, educational |
127+
| **Blacklist** ([`command-blacklist`](/cookbook/command-blacklist)) | Allow by default, block specific | ⚠️ **Medium** - New patterns might slip through | ✅ **Full** - Everything works except blocked | General protection, development work |
128+
129+
**Whitelist** = "Only these few things are allowed"
130+
**Blacklist** = "Everything is allowed except these specific things"
131+
132+
## When to Use Each Approach
133+
134+
### Use Whitelist (Strict Mode) When:
135+
136+
- 🎓 **Educational** - Teaching safe command usage
137+
- 🔍 **Analysis only** - Reading/inspecting systems
138+
- 🛡️ **Maximum security** - Untrusted users or agents
139+
- 📊 **Auditing** - Examining existing systems
140+
- 🧪 **Sandboxes** - Limiting experimental environments
141+
142+
### Use Blacklist (Safety Guardian) When:
143+
144+
- 🚀 **Development** - Need full tooling access
145+
- 🔧 **General protection** - Block obvious dangers
146+
- ⚡ **Productivity** - Don't want to pre-approve everything
147+
- 🏗️ **Building** - Need to install, compile, deploy
148+
- 🎯 **Specific risks** - Known dangerous patterns to block
149+
150+
## Extending the Whitelist
151+
152+
To allow additional commands, edit the `allowed` list in `hooks/hooks.json`
153+
(add the command name, space-separated):
154+
155+
```sh
156+
allowed="ls cat grep find ... git python npm"
157+
```
158+
159+
Each command name is matched exactly - no wildcards or partial matches. For commands with subcommands (like `git clone`), you'll need to whitelist the main command (`git`) and handle subcommand validation separately if needed.
160+
161+
## Security Considerations
162+
163+
**✅ Strengths:**
164+
165+
- Completely locks down command execution
166+
- Easy to audit (small whitelist)
167+
- Can't be bypassed by clever command variations
168+
- Works well for truly untrusted agents
169+
170+
**⚠️ Limitations:**
171+
172+
- Very restrictive (might frustrate users)
173+
- Requires updating the list as needs evolve
174+
- Doesn't prevent reading sensitive files (allows `cat /etc/passwd`)
175+
- Simple command extraction (not full shell parsing)
176+
177+
For production security, consider:
178+
179+
1. Combining with file path restrictions
180+
2. Adding argument validation (not just command name)
181+
3. Logging all blocked attempts
182+
4. Using a proper JSON parser instead of grep
183+
184+
## Plugin Structure
185+
186+
```text
187+
strict-mode/
188+
├── .claude-plugin/
189+
│ └── plugin.json # Plugin metadata
190+
├── hooks/
191+
│ └── hooks.json # PreToolUse hook definition
192+
└── skills/
193+
└── strict-mode/
194+
└── SKILL.md # Documentation (auto-loaded)
195+
```
196+
197+
This follows the **Claude Code plugin format**, compatible with:
198+
199+
- OpenHands Cloud plugin launcher
200+
- Claude Desktop plugin marketplace
201+
- Any system supporting the `.claude-plugin` spec
202+
203+
## Related
204+
205+
- [OpenHands Hooks Guide](/sdk/guides/hooks) - Full hook documentation
206+
- [Plugin System](/sdk/guides/plugins) - How plugins work
207+
- [`load-plugin`](/cookbook/load-plugin) - Programmatic plugin loading
208+
- [`launch-plugin-badge`](/cookbook/launch-plugin-badge) - No-code plugin launcher
209+
- [`command-blacklist`](/cookbook/command-blacklist) - Blacklist approach (opposite strategy)
210+
211+
## Real-World Use Cases
212+
213+
- **Code review agents** - Only allow read operations on source code
214+
- **Security auditing** - Inspect systems without modification
215+
- **Student environments** - Safe learning sandbox
216+
- **Public demos** - Allow exploration without damage
217+
- **CI/CD read-only steps** - Verify without changing artifacts
218+
219+
## Progressive Enhancement
220+
221+
Start strict, then gradually expand:
222+
223+
1. **Day 1:** Only allow `ls`, `cat`, `grep` (ultra-strict)
224+
2. **Week 1:** Add `find`, `wc`, `head`, `tail` (more inspection tools)
225+
3. **Month 1:** Add `git` for version control (read-only)
226+
4. **As needed:** Carefully evaluate and add new commands
227+
228+
This way you build trust and understand usage patterns before opening up.

‎cookbook/conversation-tags.mdx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ description: Attach key-value metadata to a conversation with tags and read it b
44
icon: tags
55
---
66

7-
{/* GENERATED from OpenHands/enterprise-cookbook@main (conversation-tags/README.md). Edit the source, not this file. */}
7+
{/* GENERATED from OpenHands/enterprise-cookbook@4132ef20b8439104c9feb0849c49e24125ce8b66 (conversation-tags/README.md). Edit the source, not this file. */}
88

9-
<Card title="View source on GitHub" icon="github" href="https://github.com/OpenHands/enterprise-cookbook/tree/main/conversation-tags" horizontal />
9+
<Card title="View source on GitHub" icon="github" href="https://github.com/OpenHands/enterprise-cookbook/tree/4132ef20b8439104c9feb0849c49e24125ce8b66/conversation-tags" horizontal />
1010

1111
Stash your own key-value metadata on an OpenHands conversation — for example an
1212
external `environment_url` or `environment_conversation_id` — and read it back
@@ -49,7 +49,7 @@ and then *polls* the Cloud read instead of reading once.
4949
> the agent server is the authoritative place to write them, and the Cloud
5050
> reflects the result. The agent `POST /api/conversations` also accepts `tags`
5151
> at creation time if you provision the sandbox yourself (see
52-
> [`clone-and-attach`](https://github.com/OpenHands/enterprise-cookbook/tree/main/clone-and-attach)).
52+
> [`clone-and-attach`](https://github.com/OpenHands/enterprise-cookbook/tree/4132ef20b8439104c9feb0849c49e24125ce8b66/clone-and-attach)).
5353
5454
## Tag rules
5555

‎cookbook/index.mdx‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Enterprise Cookbook
33
description: Runnable examples for building on the OpenHands API with OpenHands Cloud or OpenHands Enterprise.
44
---
55

6-
{/* GENERATED from OpenHands/enterprise-cookbook@main (cookbook.yaml). Edit the source, not this file. */}
6+
{/* GENERATED from OpenHands/enterprise-cookbook@4132ef20b8439104c9feb0849c49e24125ce8b66 (cookbook.yaml). Edit the source, not this file. */}
77

88
Standalone, runnable examples for teams building on the OpenHands API with OpenHands Cloud or
99
OpenHands Enterprise. Each page is generated from an example in
@@ -20,12 +20,42 @@ Observe conversations and react to their state.
2020
</Card>
2121
</CardGroup>
2222

23+
## Plugins, skills & MCP
24+
25+
Extend conversations with plugins, skills, and MCP servers.
26+
27+
<CardGroup cols={2}>
28+
<Card title="Launch Plugin Badge" icon="rocket" href="/cookbook/launch-plugin-badge">
29+
Build a no-code /launch link, HTML button, or README badge that loads a plugin.
30+
</Card>
31+
32+
<Card title="Load Plugin" icon="plug" href="/cookbook/load-plugin">
33+
Start a conversation with a plugin pre-loaded via the REST API.
34+
</Card>
35+
36+
<Card title="Test MCP Config" icon="vial" href="/cookbook/test-mcp-config">
37+
Validate MCP server configs against a sandbox agent-server via POST /api/mcp/test.
38+
</Card>
39+
40+
<Card title="Upload Skills" icon="upload" href="/cookbook/upload-skills">
41+
Upload a local agent-skills directory into a sandbox, then start a conversation that uses them.
42+
</Card>
43+
</CardGroup>
44+
2345
## Guardrails
2446

2547
Constrain what the agent can do with hooks.
2648

2749
<CardGroup cols={2}>
28-
<Card title="Command blacklist" icon="shield-halved" href="/cookbook/command-blacklist">
50+
<Card title="Command Blacklist" icon="shield-halved" href="/cookbook/command-blacklist">
2951
Block known-dangerous shell commands with a PreToolUse hook bundled in a plugin. Everything not on the blocklist runs normally.
3052
</Card>
53+
54+
<Card title="Command Whitelist" icon="shield-check" href="/cookbook/command-whitelist">
55+
Only allow approved shell commands with PreToolUse hooks (whitelist approach for strict security).
56+
</Card>
57+
58+
<Card title="Workspace Isolation" icon="folder-tree" href="/cookbook/workspace-isolation">
59+
Enforce directory boundaries with hooks to prevent agents from navigating or writing outside assigned workspace.
60+
</Card>
3161
</CardGroup>

0 commit comments

Comments
 (0)