Audit and harden all module shell scripts against command injection (follow-up from dotfiles fix)
- Dominant language
- HCL
- Stars
- 79
- Forks
- 161
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 38
Description
## Context
The `dotfiles` module recently received a fix to address insecure shell expansion and missing input validation in its `run.sh` script. The fix added:
- Strict character whitelist validation on URI inputs
- URL scheme validation (only `https?://`, `ssh://`, `git@`, `git://`)
- Proper double-quoting of all shell variables
This same class of vulnerability — **unvalidated and/or unquoted user-controllable inputs interpolated into shell scripts** — exists across many other modules in the registry. These need the same treatment.
## Affected Modules
### High Priority (user-provided URLs/paths used without validation)
**`git-clone/run.sh`**
- `REPO_URL` is passed directly to `git clone` with **no input validation** (no character whitelist, no URL format check)
- `CLONE_PATH` and `BRANCH_NAME` are also unvalidated
- `POST_CLONE_SCRIPT` is base64-decoded and executed (by design, but worth noting)
**`personalize/run.sh`**
- `$SCRIPT` (from `PERSONALIZE_PATH`) is used **unquoted** in multiple places: `[ ! -f $SCRIPT ]`, `[ ! -x $SCRIPT ]`, and direct execution `$SCRIPT`
- Word splitting and globbing possible via crafted paths
**`filebrowser/run.sh`**
- `$ROOT_DIR`, `${DB_PATH}`, `${LOG_PATH}`, `${SERVER_BASE_PATH}`, `${PORT}` are used **unquoted** in commands
- e.g. `filebrowser config set --baseURL=${SERVER_BASE_PATH} --port=${PORT} ... --root=$ROOT_DIR`
- `tee -a ${LOG_PATH}` is also unquoted
**`code-server/run.sh`**
- `${ADDITIONAL_ARGS}` is expanded **unquoted** in the `run_code_server` function
- Extension names passed to `--install-extension` without validation
### Medium Priority (internal/credential values, but still unquoted)
**`jfrog-oauth/run.sh`** and **`jfrog-token/run.sh`**
- `${JFROG_URL}`, `${JFROG_SERVER_ID}`, `${ARTIFACTORY_USERNAME}` used without quoting
- `${REGISTER_DOCKER}` is expanded and executed as a bare command
**`vault-github/run.sh`**
- `${AUTH_PATH}`, `${GITHUB_EXTERNAL_AUTH_ID}` used in commands without strict validation
**`vault-jwt/run.sh`**
- `${VAULT_JWT_AUTH_PATH}`, `${VAULT_JWT_ROLE}` used in `vault write` command without validation
**`vault-token/run.sh`**
- `${VAULT_NAMESPACE}` used without validation
**`github-upload-public-key/run.sh`**
- `$CODER_EXTERNAL_AUTH_ID` used unquoted in commands
- `$GITHUB_API_URL` used unquoted in `curl` calls
## Recommended Fix Pattern
Follow the pattern established in the `dotfiles` module fix:
1. **Input validation** — For URL inputs, add a strict character whitelist regex (e.g. `[^a-zA-Z0-9._/:@-]`) and validate the URL scheme. For path inputs, validate against shell metacharacters.
2. **Quote all variables** — Every `$VAR` and `${VAR}` used in shell commands must be wrapped in double quotes to prevent word splitting and globbing.
3. **`set -euo pipefail`** — Ensure all scripts start with this for fail-fast behavior (some already do, some don't).
4. **Test coverage** — Verify that valid inputs still work and that payloads containing `;`, `&`, `|`, `$`, backticks, `(`, `)` etc. are rejected.
## Example: `git-clone/run.sh`
Before:
```bash
REPO_URL="${REPO_URL}"
# ... no validation ...
git clone "$REPO_URL" "$CLONE_PATH"
```
After (following dotfiles pattern):
```bash
REPO_URL="${REPO_URL}"
if [ -n "$REPO_URL" ]; then
if [[ "$REPO_URL" =~ [^a-zA-Z0-9._/:@-] ]]; then
echo "ERROR: REPO_URL contains invalid characters" >&2
exit 1
fi
if ! [[ "$REPO_URL" =~ ^(https?://|ssh://|git@|git://) ]]; then
echo "ERROR: REPO_URL must be a valid repository URL" >&2
exit 1
fi
fi
```
Created on behalf of @DevelopmentCats
Contributor guide
Assessment
This issue has not been assessed yet.