In the previous Path & Filesystem Validation chapter, we built a secure fence around the files the AI is allowed to touch. We know where it can go.
But knowing where it is doesn't tell us what it's doing.
If the AI is in your Documents folder, running Get-Content (reading a file) is harmless. Running Remove-Item (deleting a file) is a disaster.
Welcome to Read-Only Command Analysis. This is the component that tells the difference between "Looking" and "Touching."
Imagine a historic library with rare, fragile books.
Obviously, we want to give the AI a Read-Only Pass by default. We want it to be able to look up information without us constantly approving every single action. But if it tries to write, delete, or change settings, we want the security guard to stop it and ask for permission.
The AI wants to check your computer's IP address.
Get-NetIPAddress -AddressFamily IPv4Later, the AI tries to change your IP address.
New-NetIPAddress -IPAddress 192.168.1.50PowerShell has thousands of commands (Cmdlets). We cannot possibly know if all of them are safe just by looking at their names.
Instead of trying to guess which ones are dangerous (a "Blacklist"), we do the opposite. We maintain a strict Allowlist (a "Whitelist"). Only commands explicitly known to be safe are allowed to run automatically.
We store this in a dictionary called CMDLET_ALLOWLIST.
// readOnlyValidation.ts (Simplified)
export const CMDLET_ALLOWLIST = {
// Reading files is safe
'get-content': {
safeFlags: ['-Path', '-Tail', '-Encoding']
},
// Listing files is safe
'get-childitem': {
safeFlags: ['-Path', '-Recurse', '-File']
},
// Checking processes is safe
'get-process': {
safeFlags: ['-Name', '-Id']
}
}
Explanation: If the AI tries to run Remove-Item, the tool looks at this list. Remove-Item is not there. Therefore, it is not Read-Only.
Being on the VIP list isn't enough. We also have to check what "baggage" (flags/arguments) the command is carrying.
Some commands are safe unless you use a specific flag.
Get-WmiObject looks like a "Get" command, but it can trigger network requests or run code if passed complex filters.Git is generally safe, but git clean deletes files.
We solve this by defining safeFlags for every command.
// Example Logic
function validateFlags(args, config) {
for (const arg of args) {
// If it looks like a flag (starts with -)
if (arg.startsWith('-')) {
// Check if this flag is in our allowed list
if (!config.safeFlags.includes(arg)) {
return false; // Unknown flag! Block it.
}
}
}
return true;
}
Explanation: If the AI runs Get-ChildItem -DestroyEverything, the tool sees that -DestroyEverything is not in the safeFlags list for Get-ChildItem. It immediately revokes the Read-Only status.
PowerShell is powerful because you can chain commands together using the pipe | symbol. This passes the output of one command to the next.
The Rule: A chain is only as safe as its weakest link.
Get-Process | Sort-ObjectGet-Process: Safe.Sort-Object: Safe (it just reorganizes data).Get-Process | Stop-ProcessGet-Process: Safe.Stop-Process: Dangerous.The tool must loop through every segment of the pipeline. If even one command is not on the Allowlist, the whole chain stops.
How does the tool make this decision?
The logic lives in readOnlyValidation.ts. Let's look at the main function isReadOnlyCommand.
We use the parsed command (from Chapter 3) to look at every command in the pipeline.
// readOnlyValidation.ts (Simplified)
export function isReadOnlyCommand(command, parsed) {
// 1. Get all parts of the pipeline (e.g. "Get-Date | Write-Host")
const segments = getPipelineSegments(parsed);
// 2. Loop through every single command
for (const pipeline of segments) {
const cmd = pipeline.commands[0];
// 3. Check if the command is on the Guest List AND checks flags
if (!isAllowlistedCommand(cmd, command)) {
return false; // Found a stranger! Not read-only.
}
}
return true; // All checks passed.
}
Explanation: This function is the "Manager." It iterates through the chain. If everyone behaves, it returns true.
This helper function checks a specific command against the configuration.
// readOnlyValidation.ts (Simplified)
export function isAllowlistedCommand(cmd, originalText) {
// 1. Look up the rules for this specific command
const config = CMDLET_ALLOWLIST[cmd.name.toLowerCase()];
if (!config) return false; // Not on the list
// 2. Check every argument
for (const arg of cmd.args) {
if (isFlag(arg)) {
// 3. Ensure the flag is in safeFlags
if (!config.safeFlags.includes(arg)) {
return false; // Illegal flag detected
}
}
}
return true;
}
Explanation: This is the "Bouncer." It checks the ID (name) and the bag (flags).
We also support external tools like git. Because git doesn't use standard PowerShell flags, we have custom logic for it.
// readOnlyValidation.ts (Simplified)
function isGitSafe(args) {
// git [subcommand] [flags]
const subcommand = args[0];
// Check strict list of safe subcommands
const safeGitCommands = ['status', 'log', 'diff', 'show'];
if (!safeGitCommands.includes(subcommand)) {
return false; // "git push" is NOT safe
}
return true;
}
Explanation: For tools like Git, the "Command" is actually the first argument (status, push). We handle these with special helper functions.
In this chapter, we learned how Read-Only Command Analysis acts as the library rules for the AI.
CMDLET_ALLOWLIST). If it's not on the list, it's blocked.-Force or --delete) are sneaking in.Now the AI can safely Read files and Run harmless commands without bothering you. But what if the AI tries to run a command that is theoretically safe, but contains a hidden malicious script inside a variable?
Next Chapter: Security & Threat Detection
Generated by Code IQ