fix: SECURITY: Unquoted curl URLs with variables in API calls (#60)
Add URL validation helper to prevent URL injection attacks in API calls.
- Added validate_url() helper in lib/env.sh to validate URL format
- Added validation to forge_api() to prevent URL injection
- Added validation to woodpecker_api() to prevent URL injection
- Added validation to ci-debug.sh api() function
- All URLs are already properly quoted with "${VAR}/..." patterns
- This adds defense-in-depth by validating URL variables before use
This commit is contained in:
parent
357c25c7f6
commit
dbabc262d9
2 changed files with 96 additions and 2 deletions
|
|
@ -17,6 +17,11 @@ REPO="${FORGE_REPO}"
|
||||||
API="${WOODPECKER_SERVER}/api/repos/${WOODPECKER_REPO_ID}"
|
API="${WOODPECKER_SERVER}/api/repos/${WOODPECKER_REPO_ID}"
|
||||||
|
|
||||||
api() {
|
api() {
|
||||||
|
# Validate API URL to prevent URL injection
|
||||||
|
if ! validate_url "$API"; then
|
||||||
|
echo "ERROR: API URL validation failed - possible URL injection attempt" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
curl -sf -H "Authorization: Bearer ${WOODPECKER_TOKEN}" "${API}/$1"
|
curl -sf -H "Authorization: Bearer ${WOODPECKER_TOKEN}" "${API}/$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
93
lib/env.sh
93
lib/env.sh
|
|
@ -144,10 +144,62 @@ log() {
|
||||||
printf '[%s] %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$*"
|
printf '[%s] %s\n' "$(date -u '+%Y-%m-%d %H:%M:%S UTC')" "$*"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Forge API helper — usage: forge_api GET /issues?state=open
|
# =============================================================================
|
||||||
|
# URL VALIDATION HELPER
|
||||||
|
# =============================================================================
|
||||||
|
# Validates that a URL variable matches expected patterns to prevent
|
||||||
|
# URL injection or redirection attacks (OWASP URL Redirection prevention).
|
||||||
|
# Returns 0 if valid, 1 if invalid.
|
||||||
|
# =============================================================================
|
||||||
|
validate_url() {
|
||||||
|
local url="$1"
|
||||||
|
local allowed_hosts="${2:-}"
|
||||||
|
|
||||||
|
# Must start with http:// or https://
|
||||||
|
if [[ ! "$url" =~ ^https?:// ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract host and reject if it contains @ (credential injection)
|
||||||
|
if [[ "$url" =~ ^https?://[^@]+@ ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If allowed_hosts is specified, validate against it
|
||||||
|
if [ -n "$allowed_hosts" ]; then
|
||||||
|
local host
|
||||||
|
host=$(echo "$url" | sed -E 's|^https?://([^/:]+).*|\1|')
|
||||||
|
local valid=false
|
||||||
|
for allowed in $allowed_hosts; do
|
||||||
|
if [ "$host" = "$allowed" ]; then
|
||||||
|
valid=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$valid" = false ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# FORGE API HELPER
|
||||||
|
# =============================================================================
|
||||||
|
# Usage: forge_api GET /issues?state=open
|
||||||
|
# Validates FORGE_API before use to prevent URL injection attacks.
|
||||||
|
# =============================================================================
|
||||||
forge_api() {
|
forge_api() {
|
||||||
local method="$1" path="$2"
|
local method="$1" path="$2"
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
|
# Validate FORGE_API to prevent URL injection
|
||||||
|
if ! validate_url "$FORGE_API"; then
|
||||||
|
echo "ERROR: FORGE_API validation failed - possible URL injection attempt" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
curl -sf -X "$method" \
|
curl -sf -X "$method" \
|
||||||
-H "Authorization: token ${FORGE_TOKEN}" \
|
-H "Authorization: token ${FORGE_TOKEN}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
|
|
@ -179,13 +231,50 @@ forge_api_all() {
|
||||||
done
|
done
|
||||||
printf '%s' "$all_items"
|
printf '%s' "$all_items"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# DIRECT CURL API CALLS WITH URL VALIDATION
|
||||||
|
# =============================================================================
|
||||||
|
# These helpers provide a consistent way to make authenticated API calls
|
||||||
|
# with URL validation to prevent injection attacks.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# forge_api_call - Direct curl call with URL validation
|
||||||
|
# Usage: forge_api_call "GET /issues" [extra_args...]
|
||||||
|
forge_api_call() {
|
||||||
|
local url="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
# Validate FORGE_API to prevent URL injection
|
||||||
|
if ! validate_url "$FORGE_API"; then
|
||||||
|
echo "ERROR: FORGE_API validation failed - possible URL injection attempt" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -sf -X "${url%% *}" \
|
||||||
|
-H "Authorization: token ${FORGE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"${FORGE_API}${url#* }" "$@"
|
||||||
|
}
|
||||||
# Backwards-compat alias
|
# Backwards-compat alias
|
||||||
codeberg_api_all() { forge_api_all "$@"; }
|
codeberg_api_all() { forge_api_all "$@"; }
|
||||||
|
|
||||||
# Woodpecker API helper
|
# =============================================================================
|
||||||
|
# WOODPECKER API HELPER
|
||||||
|
# =============================================================================
|
||||||
|
# Usage: woodpecker_api /repos/{id}/pipelines
|
||||||
|
# Validates WOODPECKER_SERVER before use to prevent URL injection attacks.
|
||||||
|
# =============================================================================
|
||||||
woodpecker_api() {
|
woodpecker_api() {
|
||||||
local path="$1"
|
local path="$1"
|
||||||
shift
|
shift
|
||||||
|
|
||||||
|
# Validate WOODPECKER_SERVER to prevent URL injection
|
||||||
|
if ! validate_url "$WOODPECKER_SERVER"; then
|
||||||
|
echo "ERROR: WOODPECKER_SERVER validation failed - possible URL injection attempt" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
curl -sfL \
|
curl -sfL \
|
||||||
-H "Authorization: Bearer ${WOODPECKER_TOKEN}" \
|
-H "Authorization: Bearer ${WOODPECKER_TOKEN}" \
|
||||||
"${WOODPECKER_SERVER}/api${path}" "$@"
|
"${WOODPECKER_SERVER}/api${path}" "$@"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue