Skip to content

Security Fix: Prevent OS Command Injection in Passbolt adapter (CWE-78)#1697

Merged
djmb merged 4 commits intobasecamp:mainfrom
NiceGuy720:fix-passbolt-rce
Nov 11, 2025
Merged

Security Fix: Prevent OS Command Injection in Passbolt adapter (CWE-78)#1697
djmb merged 4 commits intobasecamp:mainfrom
NiceGuy720:fix-passbolt-rce

Conversation

@NiceGuy720
Copy link
Contributor

Hi team,

This PR fixes a critical OS Command Injection vulnerability in the Passbolt adapter.

The item["id"] variable was interpolated directly into a shell command without escaping. An attacker who can control folder metadata in Passbolt could escalate this to RCE on the machine running kamal secrets fetch.

This patch adds the missing .to_s.shellescape to sanitize the input, fixing the vulnerability.

@jeremy jeremy requested a review from Copilot November 5, 2025 17:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enhances security in the Passbolt adapter by adding proper shell escaping to folder IDs when constructing passbolt CLI commands. However, the changes introduce several code issues including duplicate lines, inconsistent indentation, and a reference to an undefined variable.

  • Added .to_s.shellescape to folder IDs in the passbolt command for improved security
  • Introduced duplicate filter_condition assignment and inconsistent indentation
  • Removed the missing_secrets variable definition without updating its usage

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

items = `passbolt list resources #{filter_condition} #{folders.map { |item| "--folder #{item["id"].to_s.shellescape}" }.join(" ")} --json`
raise RuntimeError, "Could not read #{secrets} from Passbolt" unless $?.success?
items = JSON.parse(items)
found_names = items.map { |item| item["name"] }
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable missing_secrets is referenced on line 57 but is no longer defined. The line that calculated missing_secrets = secret_names - found_names was removed. Add this line back between lines 56 and 57.

Suggested change
found_names = items.map { |item| item["name"] }
found_names = items.map { |item| item["name"] }
missing_secrets = secret_names - found_names

Copilot uses AI. Check for mistakes.
items = `passbolt list resources #{filter_condition} #{folders.map { |item| "--folder #{item["id"].to_s.shellescape}" }.join(" ")} --json`
raise RuntimeError, "Could not read #{secrets} from Passbolt" unless $?.success?
items = JSON.parse(items)
found_names = items.map { |item| item["name"] }
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to found_names is useless, since its value is never read.

Suggested change
found_names = items.map { |item| item["name"] }

Copilot uses AI. Check for mistakes.
NiceGuy720 and others added 2 commits November 6, 2025 00:35
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

items = JSON.parse(items)
found_names = items.map { |item| item["name"] }
missing_secrets = secret_names - found_names
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to keep this line.

@NiceGuy720
Copy link
Contributor Author

NiceGuy720 commented Nov 7, 2025 via email

@djmb djmb merged commit 617d84b into basecamp:main Nov 11, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants