GitHub Security Advisory: GHSA-3p24-9x7v-7789
Package: gov.nsa.emissary:emissary (MAVEN)
Severity: HIGH (CVSS 8.8)
CWE: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection'), CWE-116: Improper Encoding or Escaping of Output
Vulnerable versions: <= 8.42.0
Patched in: 8.43.0

Summary: Emissary has an OS Command Injection via Unvalidated IN_FILE_ENDING / OUT_FILE_ENDING in Executrix

Details:
### Summary

`Executrix.getCommand()` constructs shell commands by substituting temporary file paths directly into a `/bin/sh -c` string with no escaping. The `IN_FILE_ENDING` and `OUT_FILE_ENDING` configuration keys flow into those paths unmodified. A place author who sets either key to a shell metacharacter sequence achieves arbitrary OS command execution in the JVM's security context when the place processes any payload. No runtime privileges beyond place configuration authorship are required, and no API or network access is needed.

This is a **framework-level defect** — `Executrix` provides no escaping mechanism and no validation on file ending values. Downstream implementors have no safe way to use the API as designed.

---

### Root Cause

#### Step 1 — `IN_FILE_ENDING` flows into temp path construction without validation

**[`TempFileNames.java:32-36`](src/main/java/emissary/util/shell/TempFileNames.java#L32-L36)**

```java
public TempFileNames(String tmpDir, String placeName, String inFileEnding, String outFileEnding) {
    base = Long.toString(System.nanoTime());
    tempDir = FileManipulator.mkTempFile(tmpDir, placeName);
    in  = base + inFileEnding;        // no sanitization
    out = base + outFileEnding;       // no sanitization
    basePath       = tempDir + File.separator + base;
    inputFilename  = basePath + inFileEnding;   // injected value lands here
    outputFilename = basePath + outFileEnding;  // and here
}
```

`inFileEnding` is concatenated directly onto a numeric base to produce `inputFilename`. No character class, no regex, no escaping.

#### Step 2 — The injected path is substituted verbatim into a shell string

**[`Executrix.java:1053-1065`](src/main/java/emissary/util/shell/Executrix.java#L1053-L1065)**

```java
public String[] getCommand(final String[] tmpNames, final String commandArg,
                           final int cpuLimit, final int vmSzLimit) {
    String c = commandArg;
    c = c.replaceAll("<INPUT_PATH>",  tmpNames[INPATH]);  // contains inFileEnding verbatim
    c = c.replaceAll("<OUTPUT_PATH>", tmpNames[OUTPATH]);
    c = c.replaceAll("<INPUT_NAME>",  tmpNames[IN]);
    c = c.replaceAll("<OUTPUT_NAME>", tmpNames[OUT]);

    String ulimitv = "";
    if (!SystemUtils.IS_OS_MAC) {
        ulimitv = "ulimit -v " + vmSzLimit + "; ";
    }
    return new String[] {"/bin/sh", "-c",
        "ulimit -c 0; " + ulimitv + "cd " + tmpNames[DIR] + "; " + c};
}
```

The final array element is passed to `/bin/sh -c`. Shell metacharacters in any substituted value are interpreted by the shell.

The identical pattern exists in the `TempFileNames` overload at **[`Executrix.java:1103-1115`](src/main/java/emissary/util/shell/Executrix.java#L1103-L1115)**.

#### Step 3 — `setInFileEnding()` and `setOutFileEnding()` perform no validation

**[`Executrix.java:1176-1196`](src/main/java/emissary/util/shell/Executrix.java#L1176-L1196)**

```java
public void setInFileEnding(final String argInFileEnding) {
    this.inFileEnding