Merge pull request 'fix: SECURITY: Unquoted curl URLs with variables in API calls (#60)' (#69) from fix/issue-60 into main
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
This commit is contained in:
commit
16b0a9a318
2 changed files with 71 additions and 4 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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
70
lib/env.sh
70
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,23 @@ forge_api_all() {
|
||||||
done
|
done
|
||||||
printf '%s' "$all_items"
|
printf '%s' "$all_items"
|
||||||
}
|
}
|
||||||
# Backwards-compat alias
|
|
||||||
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