Bash – Sanitize JSON for sending with Curl

bashcurljson

I have to send a POST request to some service with JSON payload, and it includes some user input. That input variable needs to be JSON-encoded to prevent injection attacks.

Code example that sends requests and parses response JSON to RESP variable:

RESP=`curl --connect-timeout "10" -s -H "Content-Type: application/json" \
        -X POST -d '{ "Attribute": '"'$USERINPUT'" }',\
        $ENDPOINT | $JQ -r '.key'`

How to sanitize, or JSON encode, $USERINPUT before creating JSON payload?

Best Answer

Using the jo utility, the sanitized JSON document could be constructed using

data=$( jo Attribute="$USERINPUT" )

You would then use -d "$data" with curl to pass this to the end point.


Old answer using jq instead of jo:

Using jq:

USERINPUT=$'a e""R<*&\04\n\thello!\''

This string has a couple of double quotes, an EOT character, a newline, a tab and a single quote, along with some ordinary text.

data="$( jq --null-input --compact-output --arg str "$USERINPUT" '{"Attribute": $str}' )"

This builds a JSON object containing the user data as the value for the lone Attribute field.

The same thing using short options:

data="$( jq -nc --arg str "$USERINPUT" '{"Attribute": $str}' )"

From this we get

{"Attribute":"ae\"\"R<*&\u0004\n\thello!'"}

as the value in $data.

This can now be used in your call to curl:

RESP="$( curl --connect-timeout "10" -s \
           -H "Content-Type: application/json" \
           -X POST -d "$data" \
           "$ENDPOINT" | jq -r '.key' )"
Related Question