fix: address code review feedback

- Replace unsafe JSON string concatenation with jq in cmd_create() and cmd_update()
- Add HTTP status code checking and error message extraction in api_call()
- Prevent JSON injection vulnerabilities from special characters
- Improve error messages with actual API responses
This commit is contained in:
Jason Woltje
2026-01-29 21:24:01 -06:00
parent 10b66ddb4a
commit bbb2ed45ea

View File

@@ -54,13 +54,30 @@ api_call() {
-H "Content-Type: application/json"
-H "x-workspace-id: ${WORKSPACE_ID}"
-s
-w "\n%{http_code}"
)
if [[ -n "$data" ]]; then
args+=(-d "$data")
fi
curl "${args[@]}" "$url"
local response
response=$(curl "${args[@]}" "$url")
# Extract HTTP status code from last line
local http_code
http_code=$(echo "$response" | tail -n1)
local body
body=$(echo "$response" | sed '$d')
# Check for errors
if [[ "$http_code" -ge 400 ]]; then
local error_msg
error_msg=$(echo "$body" | jq -r '.message // .error // "API request failed"' 2>/dev/null || echo "API request failed")
error "HTTP $http_code: $error_msg"
fi
echo "$body"
}
# Commands
@@ -142,20 +159,22 @@ cmd_create() {
[[ -z "$content" ]] && error "Content required"
# Build JSON payload
local payload="{\"content\": \"$content\""
[[ -n "$title" ]] && payload+=", \"title\": \"$title\""
[[ -n "$category" ]] && payload+=", \"category\": \"$category\""
[[ -n "$status" ]] && payload+=", \"status\": \"$status\""
[[ -n "$priority" ]] && payload+=", \"priority\": \"$priority\""
if [[ -n "$tags" ]]; then
local tags_json
tags_json=$(echo "$tags" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";""))')
payload+=", \"tags\": $tags_json"
fi
payload+="}"
# Build JSON payload using jq for safety
local payload
payload=$(jq -n \
--arg content "$content" \
--arg title "$title" \
--arg category "$category" \
--arg status "$status" \
--arg priority "$priority" \
--arg tags "$tags" \
'{content: $content} +
(if $title != "" then {title: $title} else {} end) +
(if $category != "" then {category: $category} else {} end) +
(if $status != "" then {status: $status} else {} end) +
(if $priority != "" then {priority: $priority} else {} end) +
(if $tags != "" then {tags: ($tags | split(",") | map(gsub("^\\s+|\\s+$";"")))} else {} end)'
)
response=$(api_call POST "/api/ideas" "$payload")
echo "$response" | jq -r '.id // empty' > /dev/null || error "Failed to create idea"
@@ -257,42 +276,20 @@ cmd_update() {
esac
done
# Build update payload
local payload="{"
local first=true
if [[ -n "$title" ]]; then
payload+="\"title\": \"$title\""
first=false
fi
if [[ -n "$content" ]]; then
[[ "$first" == false ]] && payload+=", "
payload+="\"content\": \"$content\""
first=false
fi
if [[ -n "$status" ]]; then
[[ "$first" == false ]] && payload+=", "
payload+="\"status\": \"$status\""
first=false
fi
if [[ -n "$category" ]]; then
[[ "$first" == false ]] && payload+=", "
payload+="\"category\": \"$category\""
first=false
fi
if [[ -n "$tags" ]]; then
[[ "$first" == false ]] && payload+=", "
local tags_json
tags_json=$(echo "$tags" | jq -R 'split(",") | map(gsub("^\\s+|\\s+$";""))')
payload+="\"tags\": $tags_json"
first=false
fi
payload+="}"
# Build update payload using jq for safety
local payload
payload=$(jq -n \
--arg title "$title" \
--arg content "$content" \
--arg status "$status" \
--arg category "$category" \
--arg tags "$tags" \
'(if $title != "" then {title: $title} else {} end) +
(if $content != "" then {content: $content} else {} end) +
(if $status != "" then {status: $status} else {} end) +
(if $category != "" then {category: $category} else {} end) +
(if $tags != "" then {tags: ($tags | split(",") | map(gsub("^\\s+|\\s+$";"")))} else {} end)'
)
response=$(api_call PATCH "/api/ideas/${idea_id}" "$payload")
echo "$response" | jq -r '.id // empty' > /dev/null || error "Failed to update idea"