🛡️ GHSA-fm76-w8jw-xf8m — plugins-loader

🟠 CVSS 8.0 — High ✅ No Known Exploit CWE-78 OSV
8.0
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

@saltcorn/plugins-loader unsanitized plugin name leads to a remote code execution (RCE) vulnerability when creating plugins using git source

Summary

When creating a new plugin using the git source, the user-controlled value req.body.name is used to build the plugin directory where the location will be cloned. The API used to execute the git clone command with the user-controlled data is child_process.execSync. Since the user-controlled data is not validated, a user with admin permission can add escaping characters and execute arbitrary commands, leading to a command injection vulnerability.

Details

Relevant code from source (req.body) to sink (child_process.execSync).

  • file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/server/routes/plugins.js#L1400

```js

router.post(

"/",

isAdmin,

error_catcher(async (req, res) => {

const plugin = new Plugin(req.body); // [1]

[...]

try {

await load_plugins.loadAndSaveNewPlugin( // [3]

plugin,

schema === db.connectObj.default_schema || plugin.source === "github"

);

[...]

}

})

);

```

  • file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/saltcorn-data/models/plugin.ts#L44

```js

class Plugin {

[...]

constructor(o: PluginCfg | PluginPack | Plugin) {

[...]

this.name = o.name; // [2]

[...]

}

```

  • file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/server/load_plugins.js#L64-L65

```js

const loadAndSaveNewPlugin = async (plugin, force, noSignalOrDB) => {

[...]

const loader = new PluginInstaller(plugin); // [4]

const res = await loader.install(force); // [7]

[...]

};

```

  • file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/plugins-loader/plugin_installer.js#L41-L61

```js

class PluginInstaller {

constructor(plugin, opts = {}) {

[...]

const tokens =

plugin.source === "npm"

? plugin.location.split("/")

: plugin.name.split("/"); // [5]

[...]

this.tempDir = join(this.tempRootFolder, "temp_install", ...tokens); // [6]

[...]

}

async install(force) {

[...]

if (await this.prepPluginsFolder(force, pckJSON)) { // [8]

[...]

}

async prepPluginsFolder(force, pckJSON) {

[...]

switch (this.plugin.source) {

[...]

case "git":

if (force || !(await pathExists(this.pluginDir))) {

await gitPullOrClone(this.plugin, this.tempDir); // [9]

[...]

}

```

  • file: https://github.com/saltcorn/saltcorn/blob/v1.0.0-beta.13/packages/plugins-loader/download_utils.js#L112

```js

const gitPullOrClone = async (plugin, pluginDir) => {

[...]

if (fs.existsSync(pluginDir)) {

execSync(git ${setKey} -C ${pluginDir} pull);

} else {

execSync(git ${setKey} clone ${plugin.location} ${pluginDir}); // [10]

}

[...]

};

```

PoC

  • check that the file will be created by the command echo "hello">/tmp/HACKED does not exists:

```

cat /tmp/HACKED

cat: /tmp/HACKED: No such file or directory

```

  • login with an admin account
  • visit http://localhost:3000/plugins/new
  • enter the following fields:
  • Name: ;echo "hello">/tmp/HACKED
  • Source: git
  • other fields blank
  • click Create
  • you will get an error saying ENOENT: no such file or directory, .... but the command touch /tmp/HACKED will be executed
  • to verify:

```

cat /tmp/HACKED

hello

```

Impact

Remote code execution

Recommended Mitigation

Sanitize the pluginDir value before passing to execSync. Alternatively, use child_process. execFileSync API (docs: https://nodejs.org/api/child_process.html#child_processexecfilesyncfile-args-options)

How this vulnerability can be exploited

This issue can be reached over the network, attack complexity is low, an attacker needs administrative privileges on the target. No user interaction is required. Rated impact: confidentiality high, integrity high, availability high.

Weakness class

GHSA-fm76-w8jw-xf8m is classified as CWE-78: OS Command Injection. Untrusted input reaches a shell command without neutralisation, so an attacker can run arbitrary operating system commands.

Affected software

GHSA-fm76-w8jw-xf8m is recorded against 1 package.

  • @saltcorn/plugins-loader

Timeline and source

Published on 3 October 2024. No public exploit is currently recorded for this entry. Record sourced from OSV.

References

github.com (Web)
github.com (Web)
github.com (Package)
github.com (Web)
github.com (Web)
github.com (Web)
github.com (Web)
github.com (Web)

Details

Severity HIGH
CVSS Score 8.0
CVSS Vector CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P
CWE CWE-78
Public Exploit ✅ No
Source OSV
Published 2024-10-03
Updated 2026-08-20
Modified 2024-10-03
Fix URL N/A

Affected Packages

Software From version Fixed in
@saltcorn/plugins-loader

Site Security Check

Is plugins-loader part of your stack?

GHSA-fm76-w8jw-xf8m is rated CVSS 8.0 High. BotEraser scans your installation against known CVE records and tells you whether this vulnerability applies to the versions you actually run.

Scan My Site Free →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.

Browse related advisories

All advisoriesGitHub AdvisoryGitHub Advisory Undated