Skip to content

fix(plugins): reject relative plugin dirs to prevent cwd fallback (CWE-426) - #3199

Open
divyansh42 wants to merge 3 commits into
tektoncd:mainfrom
divyansh42:fix/SRVKP-13570-plugin-untrusted-search-path
Open

fix(plugins): reject relative plugin dirs to prevent cwd fallback (CWE-426)#3199
divyansh42 wants to merge 3 commits into
tektoncd:mainfrom
divyansh42:fix/SRVKP-13570-plugin-untrusted-search-path

Conversation

@divyansh42

@divyansh42 divyansh42 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Changes

FindPlugin() in pkg/plugins/plugins.go silently discarded the error from getPluginDir(). In minimal environments (scratch/distroless containers, Kubernetes pods running as arbitrary UIDs without /etc/passwd entries), all home-dir resolution fallbacks (dscl, getent, sh -c "cd && pwd") can fail, causing getPluginDir() to return ("", err). The discarded error left dir as an empty string, so filepath.Join("", "tkn-<arg>") produced a relative path. syscall.Exec then resolved it against the current working directory — a classic untrusted search path (CWE-426).

Additionally, TKN_PLUGINS_DIR and XDG_CONFIG_HOME were accepted even when set to relative paths, creating the same cwd-resolution risk without any home-dir failure at all.

Fix:

  • getPluginDir() now returns an error if TKN_PLUGINS_DIR or XDG_CONFIG_HOME is not an absolute path.
  • FindPlugin() properly handles the error from getPluginDir() and skips the dir lookup (falling through to exec.LookPath) instead of silently using an empty string.

Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

  • Includes tests (if functionality changed/added)
  • Run the code checkers with make check
  • Regenerate the manpages, docs and go formatting with make generated
  • Commit messages follow commit message best practices

See the contribution guide
for more details.

Release Notes

Fix untrusted search path (CWE-426): plugin discovery no longer falls back to the current working directory when home-dir resolution fails or when TKN_PLUGINS_DIR/XDG_CONFIG_HOME is set to a relative path.

…E-426)

FindPlugin() silently discarded the error from getPluginDir(), so when
$HOME was unresolvable in minimal environments (scratch containers, pods
running as arbitrary UIDs), filepath.Join("", "tkn-<arg>") produced a
relative path. syscall.Exec then resolved it against the current working
directory, allowing an attacker who controls cwd to execute an arbitrary
binary.

Additionally, TKN_PLUGINS_DIR and XDG_CONFIG_HOME were accepted even
when set to relative paths, creating the same cwd-resolution risk without
any home-dir failure.

Fix: getPluginDir() now returns an error for non-absolute env var paths.
FindPlugin() properly handles the error and skips the dir lookup instead
of silently falling through with an empty string.

Fixes: SRVKP-13570

Signed-off-by: Divyanshu Agrawal <diagrawa@redhat.com>
@tekton-robot tekton-robot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Sep 2, 2026
@tekton-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
To complete the pull request process, please ask for approval from divyansh42 after the PR has been reviewed.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@tekton-robot tekton-robot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Sep 2, 2026
@divyansh42
divyansh42 requested a balanced review from Copilot September 2, 2026 07:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Relative HOME values still permit cwd-relative plugin lookup, and the cwd regression test does not exercise that behavior.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Hardens plugin discovery against current-working-directory fallback.

Changes:

  • Rejects relative plugin configuration paths.
  • Falls back to PATH when plugin-directory resolution fails.
  • Adds security regression tests.
File summaries
File Description
pkg/plugins/plugins.go Validates plugin paths and changes lookup fallback.
pkg/plugins/plugins_test.go Tests relative paths and fallback behavior.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pkg/plugins/plugins.go
Comment thread pkg/plugins/plugins_test.go Outdated
…iew)

homedir.Expand accepts $HOME verbatim, so HOME=relative/dir yielded a
relative plugin dir without an error. Add an IsAbs check on the expanded
result to cover this case.

Also replace the cwd regression test with one that actually exercises
the attack path: chdir into the malicious dir, keep it off PATH, and
assert FindPlugin returns an error rather than the cwd binary.

Signed-off-by: Divyanshu Agrawal <diagrawa@redhat.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The working-directory regression test currently passes against the vulnerable baseline and should directly exercise that behavior.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread pkg/plugins/plugins_test.go Outdated
The previous test used a non-existent relative path, so both old and new
code returned "cannot find plugin" — the test couldn't distinguish them.

Using "." means the old code resolves filepath.Join(".", "tkn-evil")
against cwd and finds the binary (fail), while the fixed code rejects
"." as non-absolute (pass), proving the vulnerable path is closed.

Signed-off-by: Divyanshu Agrawal <diagrawa@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants