Togoder security

npm package security report

semantic-release npm package: is it safe?

Risky patterns found that deserve a look.

Needs review Version 25.0.9 Files reviewed 27 Size 85.0 KB Scanned

Summary

Togoder Security scanned the npm package semantic-release@25.0.9 on Oct 6, 2026. An AI review of 27 source files produced 9 medium, 11 low severity findings. The overall verdict is medium: the findings flag risky but common patterns (dynamic code, unsafe defaults, broad file or network access) rather than confirmed malware.

0
critical
0
high
9
medium
11
low

Findings 20

medium

Runtime code execution via plugin loading

NPS-BECFD8FF2C33

The application is designed to load and execute plugins based on the 'plugins', 'extends', and other plugin-related options parsed from the command line. These options are coerced from user input and passed to the main module. This constitutes a dynamic module loading mechanism where user-controlled input determines what code gets executed. If an attacker can control the CLI arguments or configuration, they may achieve arbitrary code execution.

cli.js:25
medium

Dynamic import based on configuration

NPS-76667BCCEF20

The CLI dynamically imports './index.js' at runtime after parsing user-controlled options from process.argv. While the module path is static, the options parsed from CLI arguments are passed directly into the imported module. In the context of semantic-release, these options include plugin names and shareable configurations which are resolved and executed as code. An attacker who can influence the CLI arguments (e.g., via CI/CD configuration or a malicious .releaserc file) could cause arbitrary plugin code to be loaded and executed.

cli.js:65
medium

Dynamic module loading from external input

NPS-C1CB37E99ED9

The extends config option allows loading arbitrary modules via importFrom.silent(__dirname, extendPath) and importFrom(cwd, extendPath), where extendPath comes directly from the configuration. This enables loading and executing code from any resolvable module path, which could be exploited if an attacker can control the config (e.g., a malicious shared config). This is a legitimate feature of semantic-release, but it represents a code execution vector.

lib/get-config.js:35
medium

Environment variable and credential harvesting

NPS-20F3FD813224

The code reads multiple sensitive environment variables (GH_TOKEN, GITHUB_TOKEN, GL_TOKEN, GITLAB_TOKEN, BB_TOKEN, BITBUCKET_TOKEN, GIT_CREDENTIALS) to extract git authentication credentials. While this is the intended functionality for semantic-release to authenticate with git providers, it demonstrates credential harvesting behavior that could be abused if the package were compromised or if the collected credentials were sent elsewhere.

lib/get-git-auth-url.js:66
medium

Command injection risk

NPS-96EDF25CA61D

getCommits uses gitLogParser.parse with a format string constructed from user-supplied from and to values: { _: ${from ? from + '..' : ''}${to} }. These values are passed to git-log-parser, which may construct a git log command. If the parser does not safely shell-escape these values, an attacker controlling from or to (e.g., via branch/tag names in a CI context) could inject git options or shell metacharacters.

lib/git.js:56
medium

Dynamic module loading from external input

NPS-451FE1491FF2

The code calls loadPlugin(context, name, pluginsPath) where 'name' and 'pluginsPath' are derived from plugin configuration. This function likely dynamically imports or requires modules based on user-supplied or configuration-supplied names, which could be abused to load arbitrary code if the plugin name is not properly validated. While this is typical for a plugin system (semantic-release), it represents a dynamic import risk.

lib/plugins/normalize.js:14
medium

Code execution via plugin function invocation

NPS-6937C56AD7CE

The plugin function (or method) retrieved from the loaded module is invoked with configuration and context data. This is expected behavior for a plugin framework but means arbitrary code from third-party plugins will execute. If a malicious plugin is installed, it would run with access to environment, file system, and network.

lib/plugins/normalize.js:35
medium

Plugin loading mechanism

NPS-5C076302324C

The code loads external plugins from the filesystem based on names provided in configuration. While this is expected behavior for a plugin system, it represents a code execution vector if the configuration is not properly validated or if an attacker can influence plugin paths.

lib/plugins/utils.js:49
medium

Dynamic import with computed path

NPS-2009962D3AAB

The loadPlugin function uses dynamic import() with a computed file path derived from user-controlled plugin names and configuration. This could potentially load and execute arbitrary modules if an attacker can control the plugin name or path, though resolve-from is used to resolve paths relative to known directories.

lib/plugins/utils.js:62
low

dynamic module loading

NPS-83A904B1DE67

Uses createRequire to load package.json for engine constraints. This is standard practice for ESM modules needing to read package metadata.

bin/semantic-release.js:10
low

process execution

NPS-A8F98F710643

This is the CLI entry point for semantic-release. It checks Node.js and Git versions before invoking the main CLI. The execa('git', ['--version']) call is a legitimate version check, not a security concern.

bin/semantic-release.js:27
low

Debug information exposure

NPS-12F760EBEC7F

When the 'debug' flag is set, debug logging is enabled for the 'semantic-release:*' namespace. Debug logs may contain sensitive information such as tokens or credentials used during the release process. If debug output is captured in logs (common in CI environments), this could lead to credential leakage.

cli.js:60
low

Error output potentially containing sensitive data

NPS-348A390496F6

On error, the code writes the inspected error object to stderr. It uses a 'hideSensitive' utility to redact sensitive environment variables, which is a good practice. However, if the redaction is incomplete or if sensitive data exists outside of environment variables (e.g., passed as CLI arguments), it could still be exposed in error output.

cli.js:68
low

Environment variable access

NPS-1EEEB922A411

The repoUrl({ cwd, env }) call passes the environment object into the git URL resolution logic. While this file itself does not read secrets directly, environment access is delegated to ./git.js. This is normal for CI tools but warrants review of the imported module.

lib/get-config.js:76
low

Potential credential/secret exposure in debug output

NPS-BE16A7779AF3

debug("options values: %O", options) logs the full resolved options object, which may include tokens, repository credentials, or environment-derived secrets passed via CLI options or config. Debug output could leak sensitive values if logs are captured.

lib/get-config.js:88
low

Sensitive credential handling in URLs

NPS-DCC7C6F4446E

Function formatAuthUrl embeds raw credentials into URLs (auth: gitCredentials) and these URLs are then passed to git.verifyAuth. If these URLs were logged, leaked, or exfiltrated, credentials could be exposed. Debug logging is present but appears to log URLs in some cases.

lib/get-git-auth-url.js:28
low

Spawning processes or shell commands

NPS-A6F60E09211D

The code calls verifyAuth (imported from ./git.js) which invokes git operations. Although the actual command execution is in the imported module, this file orchestrates spawning git processes to verify authentication URLs, passing user-controlled credentials as part of the URL.

lib/get-git-auth-url.js:40
low

Spawning external processes

NPS-7A392B01E66F

The module extensively spawns the git binary via execa with arguments derived from parameters such as repositoryUrl, branch, tagName, ref, and note. Several of these are used with -- separators or passed as distinct argv entries (mitigating shell injection), but ref/branch/tag names flow into git subcommands (rev-list, tag, check-ref-format, show-ref, ls-remote). If callers do not validate these inputs, malicious values could influence git behavior (e.g., option injection via leading dashes).

lib/git.js
low

JSON parsing of git note content

NPS-5A53B2D6DB13

getTagsNotes executes git log with --notes=refs/notes/semantic-release* and JSON.parse()s the resulting note payloads. Git notes are repository-controlled data; a malicious commit/note could contain a crafted JSON payload. JSON.parse itself is safe from code execution, but the parsed object is later used (e.g., channels) and could influence release behavior.

lib/git.js
low

Environment variable access

NPS-46DAE188FA0A

getCommits reads process.env and merges it with execaOptions.env when invoking git-log-parser. This propagates all environment variables (including credentials like GITHUB_TOKEN, NPM_TOKEN) into the child git process. While this is common for git operations, it expands the exposure surface if any downstream logging or error path leaks the env.

lib/git.js:57

Files reviewed

FileVerdictWhat the reviewer saw
cli.js medium The CLI is part of semantic-release and dynamically loads plugins and configurations based on user-controlled input, which is an inherent risk of arbitrary code execution if input is not trusted, though no direct malicious intent or obfuscation is present.
lib/get-config.js medium This appears to be legitimate semantic-release configuration loading code, but it dynamically imports user-specified 'extends' modules (code execution vector) and logs full options which may contain credentials.
lib/get-git-auth-url.js medium This is the legitimate semantic-release get-git-auth-url module; it harvests git tokens from environment variables to build authenticated repository URLs, which is expected behavior but involves sensitive credential handling and process spawning.
lib/git.js medium This is legitimate semantic-release git utility code that shells out to git; the main concerns are potential command/option injection through unvalidated refs and propagation of process.env to child git processes, but no data exfiltration, credential harvesting, obfuscation, or backdoor patterns were found.
lib/plugins/normalize.js medium No direct malicious patterns (exfiltration, credential theft, obfuscation, backdoors) were found, but the code implements a dynamic plugin loader that executes third-party code, which is a potential security risk if plugin sources are not trusted.
lib/plugins/utils.js medium The code implements a plugin loading system with dynamic imports and filesystem resolution; while no obvious malicious patterns are present, the dynamic module loading from computed paths warrants caution.
bin/semantic-release.js safe The code is a standard CLI entry point for semantic-release that performs version checks and delegates to the main CLI; no malicious patterns were found.
index.js safe This is the legitimate entry point for the semantic-release package, with no malicious patterns such as data exfiltration, credential harvesting, obfuscation, or unauthorized process execution detected.
lib/branches/expand.js safe No malicious patterns detected
lib/branches/get-tags.js safe No malicious patterns detected
lib/branches/index.js safe No malicious patterns detected; the code is a standard branch validation module using expected dependencies and no suspicious operations.
lib/branches/normalize.js safe Cleared by Jev triage; no further analysis needed
lib/definitions/branches.js safe Cleared by Jev triage; no further analysis needed
lib/definitions/constants.js safe Cleared by Jev triage; no further analysis needed
lib/definitions/errors.js safe Cleared by Jev triage; no further analysis needed
lib/definitions/plugins.js safe No malicious patterns detected; the code is a legitimate plugin configuration module for semantic-release and exhibits no data exfiltration, credential harvesting, obfuscation, process spawning, or other suspicious behavior.
lib/get-commits.js safe No malicious patterns detected; the file simply retrieves git commits using the debug logger and a local getCommits helper.
lib/get-error.js safe Cleared by Jev triage; no further analysis needed
lib/get-last-release.js safe Cleared by Jev triage; no further analysis needed
lib/get-logger.js safe Cleared by Jev triage; no further analysis needed
lib/get-next-version.js safe Cleared by Jev triage; no further analysis needed
lib/get-release-to-add.js safe Cleared by Jev triage; no further analysis needed
lib/hide-sensitive.js safe No malicious patterns detected; the code only redacts sensitive environment variable values from log output.
lib/plugins/index.js safe No malicious patterns detected in the plugin loading and configuration logic.
lib/plugins/pipeline.js safe Cleared by Jev triage; no further analysis needed
Show 2 more files
FileVerdictWhat the reviewer saw
lib/utils.js safe No malicious patterns detected
lib/verify.js safe No malicious patterns detected

Scanned versions of semantic-release

VersionVerdictFilesScanned
25.0.9 Needs review 27 Oct 6, 2026

Frequently asked questions

Is semantic-release safe to use?

No confirmed malware was found in semantic-release@25.0.9, but the review flagged 9 medium, 11 low severity findings for risky patterns worth checking before you rely on it.

Does semantic-release contain malware?

No malware was identified in semantic-release@25.0.9 when Togoder Security scanned it on Oct 6, 2026. A new version can still introduce malicious code, so scan the exact versions in your lockfile.

How was semantic-release checked?

Togoder Security downloaded the published npm package and had an AI model read its 27 source files, looking for install scripts, credential access, network exfiltration, obfuscation, backdoors and crypto-wallet theft. The results are cached by file hash and shown here.

How do I scan semantic-release together with the rest of my dependencies?

Upload your lockfile at https://security.togoder.click/scan or call the API documented at https://security.togoder.click/api-docs. Files that have already been scanned, like the ones in semantic-release@25.0.9, cost nothing.

Related security reports