T09 · Insecure Skill Coding Practices
- Location
SKILL.md:41- Finding
Shell Command Injection Through Unescaped User-Controlled Search Arguments
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:41,SKILL.md:50,SKILL.md:59; additional affected examples appear inreferences/aisearch.md:21-27,145-156,212-220andreferences/lite-recipes.md:13-14,27-30
Vulnerability Type: Shell command injection
Risk Level: HighVulnerable command templates:
shell dws aisearch person --query "<complete value>" --dimension <dimension> --format json dws aisearch enterprise --queries "<topic>" --types <document,mail,...> --time-range "<time>" --format json dws aisearch behavior --queries "<topic>" --behavior-type <action> --direction <direction> --format jsonThe documentation also requires the search target to be passed through verbatim rather than truncated or modified. Consequently, malicious shell syntax contained in a user-provided name, employee number, telephone clue, department, topic, time range, direction, or other argument may reach the command execution layer unchanged.
Technical Analysis
The command templates place user-controlled values inside shell-style double quotes. Double quotes prevent ordinary word splitting but do not disable shell command substitution. Constructs such as
$(command)and backtick substitutions are evaluated by POSIX-compatible shells before thedwsprocess starts.For example, if a user supplies the following search value:
text $(attacker-command)the generated command can be equivalent to:
shell dws aisearch person --query "$(attacker-command)" --dimension name --format jsonIf the agent's execution tool passes this string through a shell,
attacker-commandexecutes locally and its output becomes the value of the--queryargument. Merely surrounding the value with double quotes therefore does not provide shell-safe escaping.Exploitability depends on the downstream execution mechanism. A structured process API that passes an argume ...[truncated 1731 chars]
- Remediation
View remediation
Remediation Suggestions
-
Require execution through a structured process API that accepts an executable and argument array, for example an equivalent of:
text executable: dws arguments: ["aisearch", "person", "--query", userValue, "--dimension", validatedDimension, "--format", "json"]The command must not be joined into a shell command string.
-
Explicitly prohibit execution through
sh -c,bash -c, PowerShell string evaluation, or similar shell-evaluation interfaces. -
If shell execution is unavoidable, apply a well-tested, platform-specific shell-quoting routine to every user-derived argument. Do not rely on double quotes or ad hoc character replacement.
-
Validate fixed-choice fields against strict allowlists:
- Person dimensions:
all,name,department,position,duty,supervisor,subordinate,phone, andjobNumber. - Content types: only the documented type identifiers.
- Behavior types:
all,send,create,share,edit, andreceive.
- Person dimensions:
-
Treat search text, time ranges, chat scopes, and directions as opaque argument values. They should never be interpreted as executable syntax.
-
Add adversarial tests covering command substitutions, backticks, quotes, semicolons, newlines, redirection operators, pipes, and platform-specific metacharacters. Verify that each value reaches
dwsas one literal argument without causing a secondary process to execute. -
Update every command example in
SKILL.md,references/aisearch.md, andreferences/lite-recipes.mdto state that the displayed shell syntax is illustrative and that implementations must use argument-vector execution.
-
