Read-only labels are only safe when the full command path is understood. Many utilities accept options that invoke pagers, preprocessors, plugins, or embedded interpreters, and those features can cross the boundary from viewing data to executing code. If the filtering logic only checks a few known dangerous flags, attackers can often reach an alternate argument or built-in behavior that still runs commands.
How “Read-Only” Becomes Execution
A read-only label describes the intended outcome, not the full behaviour of the binary or its dependencies. Many tools can still hand work off to pagers, shell helpers, syntax highlighters, filters, or plugins, and those pathways may execute commands even when the top-level action is only “display.” The security question is whether the command path contains any execution-capable branch, not whether the first verb looks harmless.
This is why allowlisting only a short set of “dangerous” flags is brittle. If the utility supports alternate options, environment-driven behaviour, or embedded scripting, a user can often reach the same execution primitive through a different argument combination. The result is a control that appears restrictive but still permits arbitrary command execution through functionality the filter did not enumerate.
Read-only utilities also inherit risk from the programs they invoke. If the allowed command launches a pager that honours shell escapes, a formatter that loads extensions, or a parser that can call out to helper programs, the outer command is merely a launcher. In practice, the trust boundary is the entire invocation chain, not the first executable named in the policy.
Why Filtering by Flag Names Fails
The core failure mode is incomplete modelling of application behaviour. Security controls that inspect only a few known-bad flags assume the dangerous path is obvious and stable, but command-line interfaces are full of alternate switches, aliases, config files, and implicit defaults. Attackers look for the one path that still reaches a shell, a subshell, or a script interpreter.
That is especially true when the allowlist is built around “safe” viewing commands. A command may be safe in one mode and unsafe in another, depending on whether it loads pagers, honours less-like escapes, expands variables, or executes user-supplied expressions. If the policy engine does not parse the command semantically, it can miss the exact feature that changes the command from inspection to execution.
For defenders, the practical lesson is that command filtering must be based on verified behaviour, not reputation. If a command family can reach code execution through plugins, preprocessors, or shell delegation, then it is not truly read-only from a security perspective, even if most everyday uses are benign.
Risk and Threat Considerations
Allowlisted read-only commands create a hidden execution surface because the attacker only needs one alternate path that the filter forgot to block. That can turn a routine inspection command into a code-execution primitive, especially when the tool supports shell escapes, embedded interpreters, or helper processes that inherit the current user’s authority.
Failure mechanism: The control enumerates a few forbidden flags, but the command still exposes another argument, default behaviour, plugin hook, or environment-controlled branch that invokes a shell or interpreter.
Impact: An attacker can move from permitted read access to arbitrary command execution, then use the same foothold for data theft, tampering, or lateral movement under the victim process’s privileges.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK and OWASP Agentic AI Top 10 address the attack and risk surface, while CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| CIS Controls v8 | CIS 6 — Access Control Management | Restricts which commands and execution paths users can invoke. |
| CIS 8 — Audit Log Management | Logging helps detect unexpected shell escapes or helper launches from read-only tools. | |
| CIS 16 — Application Software Security | Secure command behavior requires testing for unsafe option handling and embedded execution features. | |
| Recommendation — Constrain permitted commands and remove unnecessary execution paths from allowlists. Log command invocations and alert on unexpected child-process creation. Test allowed utilities for hidden execution-capable features before approving them. | ||
| MITRE ATT&CK | T1059 — Command and Scripting Interpreter | The risk is arbitrary command execution via interpreter or shell invocation. |
| T1202 — Indirect Command Execution | Read-only commands can delegate execution to another program such as a pager or helper. | |
| Recommendation — Hunt for paths that reach command or scripting interpreters through allowed utilities. Block indirect execution chains that pass attacker control into helper programs. | ||
| OWASP Agentic AI Top 10 | A2 — Tool Misuse | A command becomes dangerous when a benign-looking tool can be steered into execution. |
| A3 — Identity and Privilege Abuse | Execution risk rises when the allowed command runs with more privilege than the caller should have. | |
| A6 — Prompt Injection | The same control failure pattern applies when untrusted input steers a tool into unsafe behaviour. | |
| Recommendation — Treat tool invocation as unsafe when alternate arguments can trigger execution. Minimise privileges so a misused utility cannot execute with excess authority. Assume untrusted input can redirect tools into unsafe execution paths. | ||
Practitioner Guidance
What to verify: Validate the full execution path of every allowlisted command, including pager invocation, extension loading, pre/post-processing, and any feature that can spawn a shell or external helper. If you cannot explain the command’s transitive behaviour from documented sources and testing, do not treat it as read-only.
Common mistake: Treating “no obvious dangerous flag” as equivalent to “no execution risk.” In practice, the safer test is whether the command can be coerced into code execution through any supported mode, not whether the top-level invocation looks harmless.
Practitioner takeaway: Allowlisting works only when the allowed command is provably non-executing across all supported paths, because a single overlooked branch is enough to convert a viewing command into an execution channel.
Related resources from NHI Mgmt Group
- Why does arbitrary command execution in an AI studio create such a severe security risk?
- Why can deleting a Git repository directory create command execution risk when other Git operations are still available?
- Why do read-only AI agents still create serious security risk?
- Why do sanitised MCP inputs still leave organisations exposed to command execution risk?
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 20, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org