5 releases (2 stable)

1.0.1 Jan 27, 2024
1.0.0 Jan 24, 2024
0.2.1 Jan 22, 2024
0.2.0 Jan 22, 2024
0.1.0 Jan 22, 2024

#142 in HTTP server

AGPL-3.0

26KB
287 lines

http-cmd

Run a command over HTTP

⚠️ Warning ⚠️

Don't expose http-cmd to the internet, especially with programs that execute code (e.g. python) or commands (e.g. bash). Otherwise, execution of arbitrary code and programs is possible (aka. you get hacked)!

Motivation

The motivation for building this tool is that static site generators like Zola don't allow executing external commands for security reasons. You don't want arbitrary programs to be executed while you try to build a static website! Imagine being hacked by a third-party theme 😱

However, such static site generators support fetching remote data. This leads to the hack of how http-cmd works:

  • 💻️ Run a local HTTP server waiting for POST requests and using their body as standard input or command arguments for the external command
  • ⬆️ Let the static site generator send a POST request to run the external command
  • ⬇️ Embed the response body as the output of the external command
  • 🎉 Profit!

You can find examples of using http-cmd with Zola in the zola_examples directory.

Use cases

Here are some possible use cases:

Installation

You can install http-cmd using Cargo by running

cargo install http-cmd

You can update it using cargo-update.

If you don't want to install Cargo with the Rust toolchain, open an issue and I will publish a container image that you can run with Docker or Podman.

Config

http-cmd expects the config file http-cmd.toml in the directory where it is executed. But you can also provide a path to the a config file using the -c command line option.

Parameter Description Default
ip The IPv4/IPv6 address to bind to "127.0.0.1"
port The port to listen on 8080
max_request_body_size The maximum request body size in bytes 1048576 (1 MiB)
commands A list of command configs
commands.name A name for the command. It is used for executing the command under http://IP:PORT/NAME. Only the characters a to z (lowercase), 0 to 9 and - are allowed.
commands.stdin See the Modes section below
commands.program The program to execute when http://IP:PORT/NAME is called. It can be an absolute or relative path to the executable. Otherwise, the executable will be searched for equivalently to running the Unix which command
commands.args A list of the program's arguments

Modes

http-cmd has two modes for running a program. The mode is chosen using the boolean configuration value stdin:

  • For stdin = true, the request body is piped to the standard input of the command.
  • For stdin = false, the request body is split to arguments which are provided after the configured args. See the example below with the ls command.

Demo

Here is an example config file:

# The default
ip = "127.0.0.1"

# The default
port = 8080

# 2 KiB instead of the default of 1MiB
max_request_body_size = 2048

[[commands]]
name = "rev"
stdin = true
program = "rev"
args = []

[[commands]]
name = "ls"
stdin = false
program = "/usr/bin/ls"
args = ["-l"]

If you save this configuration to the file http-cmd.toml and run http-cmd, a server is started listening on http://127.0.0.1:8080/rev and http://127.0.0.1:8080/ls.

Now, run

curl http://127.0.0.1:8080/rev -d "Hello World!"

This command sends a POST request with the body "Hello World!". The output should be the reversed text: "!dlroW olleH" 🎉

The equivalent of what http-cmd does here with stdin set to true is the following pipe:

echo -n "Hello World!" | rev

To test the second command, run

curl http://127.0.0.1:8080/ls -d "src zola_examples"

The output depends on the content of the two directories.

This command also sends a POST request, but since stdin is set to false for the ls command, the second mode is applied. This means that http-cmd executes the command ls -l src zola_examples. The arguments src and zola_examples are placed after the program ls and its configured arguments (here only -l).

Dependencies

~11–22MB
~333K SLoC