

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Still calibrating
click for more info
Not enough gems
Cost: 6 gems
1: Injection
incomplete
2: Fixing SQL Injection
incomplete
3: Injection Beyond SQL
incomplete
4: Safe Validation and Sanitization
incomplete
5: When to Sanitize
incomplete
6: Unsafe Archive Extraction
incomplete
7: Safe Archive Extraction
incomplete
8: LLM Prompt Injection
incomplete
9: Limiting Tool Calls
incomplete
10: Narrow Tool Interfaces
incomplete
11: File Upload Security
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Limiting which tools a model can call still isn't enough. You should also narrow the interface of each tool.
This is a more nuanced concept, but to be clear, here's the opposite of what I mean:
async function executeShellCommand(command: string): Promise<string> {
const { stdout } = await exec(command);
return stdout;
}
An arbitrary exec tool is just about the most insecure thing you can hand to a user-facing LLM. However, a dedicated searchBooks tool is a lot better:
async function searchBooks(query: string): Promise<string> {
return await bookCatalogApi({ query, limit: 5 });
}
All the model can do here is specify the query string and receive up to five results at a time, a limit it can't change. It also gives us the control to validate the query string in deterministic code and reject anything that doesn't match our expected patterns.
Bearly Secure's status tool lets the model supply both orderId and userId, so a prompt can steer it toward another customer's orders. Bind status lookups to the authenticated user.
With Bearly Secure still running, run and submit the CLI tests from the project root.