T09 · Insecure Skill Coding Practices
- Location
react-component-generator.sh:2- Finding
Command Injection and Unrestricted File Overwrite Through Component Name
- Content
View full analysis
Vulnerability Details
File Location:
react-component-generator.sh, lines 2-14
Vulnerability Type: Shell command injection through dynamically constructedsedprogram and unrestricted output path
Risk Level: Highbash NAME="${1:-MyComponent}" TYPE="${2:-function}" cat > "$NAME.jsx" << 'JSX' export default function COMP_NAME(props) { return ( <div> <h1>COMP_NAME</h1> </div> ); } JSX sed -i "s/COMP_NAME/$NAME/g" "$NAME.jsx"Technical Analysis
The first positional argument is accepted as
NAMEwithout validation. Although the shell variables are quoted, quoting only prevents shell word splitting and pathname expansion. It does not make attacker-controlled data safe when that data is inserted into the source code of another interpreter.At line 14,
NAMEis embedded directly into asedsubstitution expression:bash sed -i "s/COMP_NAME/$NAME/g" "$NAME.jsx"Characters meaningful to
sed, including the/delimiter, command separators, backslashes, newlines, and GNUsedflags such ase, can change the meaning of the generated program. Under GNUsed, a crafted replacement expression can reach theefunctionality, which evaluates generated text through a shell. Successful exploitation may require constructing a matching path or directory because the same malicious value is also used as the output filename, but the script imposes no restriction preventing that setup.The same input is also used directly as a filesystem path in both the redirection and the
sed -itarget. Absolute paths, path separators, and traversal sequences such as../are accepted. Consequently, the script can create or truncate a writable file outside the expected working directory, provided its final path ends in.jsx. Existing files are overwritten without confirmation.The unused
TYPEvariable does not mitigate either issue.A
...[truncated 1675 chars]
- Remediation
View remediation
Remediation Suggestions
-
Validate the component name before using it. Restrict it to a React-compatible identifier, for example:
bash if [[ ! "$NAME" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then printf 'Error: invalid component name\n' >&2 exit 1 fi -
Explicitly reject path separators, traversal components, control characters, and
sedmetacharacters. A strict allowlist is preferable to trying to escape every dangerous character. -
Write generated files only beneath a designated output directory. Resolve and verify the final path before writing to ensure it remains within that directory.
-
Refuse to overwrite existing files unless the caller explicitly supplies a trusted overwrite option:
bash output="${OUTPUT_DIR}/${NAME}.jsx" if [[ -e "$output" ]]; then printf 'Error: output file already exists\n' >&2 exit 1 fi -
Avoid constructing executable
sedsource from user input. After strict identifier validation, generate the component directly with a here-document:bash cat > "$output" <<JSX export default function ${NAME}(props) { return ( <div> <h1>${NAME}</h1> </div> ); } JSX -
Run the generator with least privilege, particularly in CI or build environments, and add tests covering traversal strings, delimiters, newlines, shell syntax, and attempts to overwrite existing files.
-
