Welcome to the final chapter of the BashTool tutorial!
In the previous Chapter 4: Path & Filesystem Constraints, we built an "Electric Fence" around the project directory. We ensured the AI couldn't wander off into your system folders.
However, being in the "Safe Zone" isn't enough.
git status (Just looking).rm -rf * (Deleting everything).Both commands might happen inside the allowed project folder. But one is harmless, and the other is destructive.
Imagine you are at the airport.
We need to open up the command's "suitcase" (arguments and flags) to see what's inside.
-l, --help).--force, -i for overwrite).This layer, Read-Only & Safety Analysis, allows us to auto-approve safe commands so the user doesn't get annoyed, while strictly flagging dangerous ones.
The core of this system is a massive list of commands and flags that we know are safe. This logic resides in readOnlyValidation.ts.
We don't just guess; we define exactly what arguments are allowed for every tool.
Let's look at how we define safety for grep (a search tool).
// From readOnlyValidation.ts
const COMMAND_ALLOWLIST = {
grep: {
safeFlags: {
'-i': 'none', // Case insensitive (Safe)
'-c': 'none', // Count results (Safe)
'-r': 'none', // Recursive (Safe)
'--file': 'string' // Read patterns from a file (Safe)
}
},
// ... other tools like ls, cat, date
};
Explanation:
grep -i). It just changes the display mode.grep --file=patterns.txt). Since it reads a file, it is safe.--output-file (which might write data) are not in this list. If the AI tries to use them, the check fails.
It is not enough to just check if the string contains -i. Bash is complex.
grep -i is safe.
grep -i > file.txt is not safe (it overwrites file.txt).
We use a function called isCommandSafeViaFlagParsing to break the command into tokens.
// From readOnlyValidation.ts (Simplified)
export function isCommandSafeViaFlagParsing(command: string) {
// 1. Break command into tokens: ["grep", "-i", "search", "file.txt"]
const tokens = parseCommand(command);
// 2. Check if there are dangerous operators like > or |
if (tokens.includes('>')) return false;
// 3. Check every flag against the allowlist
return validateFlags(tokens);
}
Explanation:
>), the command is automatically marked as "Not Read-Only."safeFlags list we saw in Part 1.sed Case)Some tools are "Swiss Army Knives." They can be safe or dangerous depending on how they are used.
Take sed (Stream Editor).
sed -n 'p' file.txt (Just prints the file to the screen).sed -i 's/foo/bar/' file.txt (Edits the file in place).
We can't just ban sed. We need a specialized inspector. This lives in sedValidation.ts.
// From sedValidation.ts
export function sedCommandIsAllowedByAllowlist(command, options) {
// 1. Parse flags
if (command.includes('-i')) {
// If we are in "Read-Only" mode, -i is forbidden!
if (!options.allowFileWrites) return false;
}
// 2. Check the internal sed expression
const expression = extractSedExpression(command); // e.g., "s/foo/bar/"
// 3. Look for dangerous commands inside the expression
// 'w' writes to a file. 'e' executes a command.
if (expression.includes('w ') || expression.includes('e ')) {
return false;
}
return true;
}
Explanation:
-i).sed is running.w (write) or e (execute). If found, we treat it as a weapon and block it.Sometimes a command is syntactically correct, allowed by permissions, and inside the right folder... but it is still a terrible idea.
We have a file called destructiveCommandWarning.ts that acts as a final sanity check. It looks for patterns known to cause tears.
// From destructiveCommandWarning.ts
const DESTRUCTIVE_PATTERNS = [
{
// rm -rf is the classic "delete everything" command
pattern: /rm\s+-[a-zA-Z]*f/,
warning: 'Note: may force-remove files',
},
{
// git reset --hard destroys uncommitted work
pattern: /git\s+reset\s+--hard/,
warning: 'Note: may discard uncommitted changes',
}
];
Explanation:
Even if the user said "Allow all git commands," if the system sees git reset --hard, it pauses. It injects a Warning Message into the permission dialog so the user thinks twice before clicking "Approve."
How does the data flow when the AI tries to run a command like grep -r "error" .?
If a command fails this check (e.g., grep -r "error" > log.txt), it doesn't mean the command is blocked.
It simply means "Not Read-Only."
The system returns behavior: 'passthrough'. This tells the Permission Orchestrator (Chapter 3): "I can't auto-approve this. You need to ask the human user for permission."
Congratulations! You have completed the BashTool architecture tutorial.
We have built a robust system that transforms a raw, dangerous shell into a safe tool for AI agents.
By combining these five layers, we ensure that the AI can be helpful without being harmful. It can search, read, and suggest changes, but it cannot delete your data or hijack your system without your explicit consent.
End of Tutorial.
Generated by Code IQ