Hurl 8.1.0, of Config and Security

The Hurl team is super happy to announce Hurl 8.1.0! Surfer

Hurl is a command line tool powered by curl, that runs HTTP requests defined in a simple plain text format:

GET https://example.org/api/tests/4567
HTTP 200
[Asserts]
jsonpath "$.status" == "RUNNING"    # Check the status code
jsonpath "$.tests" count == 25      # Check the number of items
jsonpath "$.id" matches /\d{4}/     # Check the format of the id


POST https://example.org/api/tests
{
  "name": "foo"
}
HTTP 201
[Asserts]
header "x-foo" contains "bar"
certificate "Expire-Date" daysAfterNow > 15
ip == "2001:0db8:85a3:0000:0000:8a2e:0370:7334"

What’s New in This Release

Configuration File

In Hurl 8.0.0, we’ve improved the way you can configure Hurl with environment variables (for instance export HURL_IPV6=true / --ipv6).

In Hurl 8.1.0, we extend the possibility to configure Hurl by adding support for configuration file. Hurl will look for a configuration file at $XDG_CONFIG_HOME/hurl/config (or $HOME/.config/hurl/config if $XDG_CONFIG_HOME is not set). The configuration file is a list of options added to each Hurl run.

For instance:

$ cat ~/.config/hurl/config
# Hurl config file
--header x-identifier:quux
--verbose
--delay=1s
--fail-with-body

So, Hurl now reads its configuration from four sources, from lowest to highest priority:

  • Configuration file (ex: ~/.config/hurl/config)
  • Environment variables (ex: export HURL_INSECURE=true)
  • Command-line options (ex: hurl --insecure)
  • Options section options (ex: insecure: true in file, with [Options] section)

JSONPath Query Configuration

In Hurl 8.0.0, we’ve revamped our JSONPath engine and added support for RFC 9535: JSONPath: Query Expression for JSON specification. In RFC 9535, every query result always returns a list. To facilitate JSONPath query usage, we coerce lists that return a single value to this value. This coercion also turns empty results into “no value”.

Let’s say we have this JSON:

{
  "fruits": [
    "Apple", "Lemon", "Strawberry"
  ]
}

By the spec, the JSONPath query $.fruits[0] should return a list of one element ["Apple"]. As the result list has only one single element, Hurl JSONPath query returns the string “Apple”. So we’re able to write this Hurl file:

GET https://example.org/captures-json
HTTP 200
[Asserts]
jsonpath "$.fruits[0]" isString
jsonpath "$.fruits[0]" == "Apple"

We’ve been doing this coercion since the very first Hurl version but some people prefer not having this (to have similar results as https://jsonpath.com). We’ve heard you! So, in Hurl 8.1.0, we’ve added a --no-jsonpath-coercion option. It can be set in the new Hurl configuration file, on command line or using the env variable HURL_NO_JSONPATH_COERCION=true, or per request in an [Options] section. Using this option, JSONPath queries always return a list:

GET https://example.org/captures-json
[Options]
no-jsonpath-coercion: true
HTTP 200
[Asserts]
jsonpath "$.fruits[0]" isList
jsonpath "$.fruits[0]" count == 1
jsonpath "$.fruits[0]" nth 0 == "Apple"

Other New Options

Hurl 8.1.0 adds some new options:

--no-header to remove HTTP request headers

Let’s say you don’t want any User-Agent nor Accept HTTP header request, you can use --no-header option:

$ hurl --no-header user-agent --no-header Accept foo.hurl

It also works on a specific request:

# This request will send a default User-Agent header
GET https://example.org

# This request will NOT send a User-Agent header
GET https://example.org
[Options]
no-header: User-Agent
HTTP 200

And can be configured with environment variable HURL_NO_HEADER:

$ export HURL_NO_HEADER="user-agent|Accept"
$ hurl foo.hurl

--fail-with-body to get HTTP response even with errors

By default, Hurl outputs the last response body only when the run succeeds; when there are errors (HTTP runtimes or asserts errors), Hurl doesn’t output any response. But sometimes the response body is necessary to explain failures. In Hurl previous versions, you can use --very-verbose or --output combined with --no-assert.

In Hurl 8.1.0, we add --fail-with-body option: this option changes Hurl’s default behavior when there are errors and output the HTTP response regardless of asserts / HTTP runtime errors. Like many other options, this option can be used as a command line option (hurl --fail-with-body foo.hurl), with environment variable (export HURL_FAIL_WITH_BODY=true), with Hurl configuration file, or per request with [Options] section.

$ hurl --fail-with-body foo.hurl
{
  "slideshow": {
    "author": "Yours Truly",
    "date": "date of publication",
    "slides": [
      {
        "title": "Wake up to WonderWidgets!",
        "type": "all"
      }
    ],
    "title": "Sample Slide Show"
  }
}
error: Assert failure
  --> foo.hurl:4:0
   |
   | GET https://httpbin.org/json
   | ...
 4 | jsonpath "$.slideshow.author" == "Someone"
   |   actual:   string <Yours Truly>
   |   expected: string <Someone>
   |

--tls-min / --tls-max

--tls-min and --tls-max set the minimum and maximum allowed TLS version. Used together,, you can pin a given TLS version:

$ hurl --tls-min 1.3 --tls-max 1.3 tlscert.hurl

Fixed Bugs and Security Issues

Apart from these enhancements, we have received an unusual amount of security advisories from various contributors, over the last 6 months. It goes from parsing issues in JSONPath expression to malicious debug curl command and finally to our first official CVE!

Simply said, Hurl 8.1.0 is the Hurl version that has the largest number of bugs/CVEs fixed since the first public version. While analyzing and fixing them, we’ve reclassified some reports to “bugs”.

Bugs count

It’s rather obvious than the vast majority of these issues were written partly (if not totally) by LLM agents. Each issue takes time to digest, analyzing the automated prose is time-consuming, but we’ve found very few false positives. Almost all issues reported were indeed a defect in Hurl in some way or another. Sometimes CVEs were here and well reproducible but the reproduction sample didn’t even compile. Other times, a very super clear repro step was provided with a good source code analysis and possible fixes. Many reporters were first-time GitHub users!

We’re not at all in the same league as curl or the Linux Kernel, but still feel the raise and impact of automation by AI, like these projects. For security and bugs, we find it a big plus. For maintainers’ time, that’s another story...

That’s all for today!

There are a lot of other improvements with Hurl 8.1.0...and many more fixes; you can check the complete list of enhancements and bug fixes in our release note.

If you like Hurl, don’t hesitate to support us with a star on GitHub and share it on 𝕏 / Twitter and Bluesky!

We’ll be happy to hear from you, either for enhancement requests or for sharing your success story using Hurl!