Skip to content

Adding external plugin support#2812

Closed
malinthaprasan wants to merge 3 commits into
wso2:mainfrom
malinthaprasan:platform-modzev2
Closed

Adding external plugin support#2812
malinthaprasan wants to merge 3 commits into
wso2:mainfrom
malinthaprasan:platform-modzev2

Conversation

@malinthaprasan

Copy link
Copy Markdown
Contributor

Purpose

Explain why this feature or fix is required. Describe the underlying problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.

Goals

Describe what solutions this feature or fix introduces to address the problems outlined above.

Approach

Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI. Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.

User stories

Summary of user stories addressed by this change>

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR introduces a public plugin development kit, explicit internal and external plugin wiring, plugin-provided authentication and middleware hooks, and a platform façade for configuring and running the server.

Changes

Plugin runtime and platform façade

Layer / File(s) Summary
Public plugin and middleware contracts
platform-api/pdk/*, platform-api/platform/middleware.go
Defines plugin lifecycle, dependencies, authentication skip paths, middleware positions, and organization access APIs, with platform-level type aliases.
Plugin adaptation and server lifecycle
platform-api/internal/plugin/*, platform-api/internal/server/*
Wraps external plugins, initializes both plugin tiers, inserts plugin middleware around the platform chain, applies auth skip paths, and shuts down configured plugins.
Platform application construction and execution
platform-api/platform/options.go, platform-api/platform/platform.go
Adds ordered construction options for configuration, logging, and plugins, plus New and Run methods for starting the server.
Built-in plugin entrypoint wiring
platform-api/cmd/*
Passes explicit plugin tiers to server startup and supplies build-specific built-in plugin lists.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PlatformApp
  participant StartPlatformAPIServer
  participant ExternalPlugin
  participant MiddlewareChain
  PlatformApp->>StartPlatformAPIServer: start with configured pdk plugins
  StartPlatformAPIServer->>ExternalPlugin: initialize with pdk.Deps
  ExternalPlugin->>StartPlatformAPIServer: provide routes, auth paths, and middleware
  StartPlatformAPIServer->>MiddlewareChain: assemble platform and plugin middleware
Loading

Possibly related PRs

  • wso2/api-platform#2759: Updates the same server middleware startup flow around authentication and scope enforcement.

Suggested reviewers: renuka-fernando, ashera96, tharindu1st, chamilaadhi, thivindu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is just the template and leaves all required sections empty. Replace the placeholder template with concrete content for purpose, goals, approach, user stories, documentation, tests, security checks, samples, related PRs, and test environment.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding external plugin support.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain modules listed in go.work or their selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@platform-api/internal/server/server.go`:
- Around line 458-460: Update the plugin initialization loop in the server setup
to track successfully initialized plugins and, when a later plugin’s Init fails,
shut down all previously initialized plugins before returning the initialization
error. Reuse each plugin’s existing cleanup or shutdown API, preserve reverse
initialization order if supported, and keep the current wrapped error from the
failing plugin.
- Around line 473-477: Update LocalJWTAuthMiddleware to validate and normalize
the request’s EscapedPath before matching, rejecting forbidden traversal or
malformed sequences before authentication bypass evaluation. Canonicalize each
configured config.SkipPaths entry and replace the raw strings.HasPrefix
comparison with a path-aware prefix check that only matches complete path
segments, preserving valid public-path skips.

In `@platform-api/pdk/deps.go`:
- Around line 38-45: Update Deps and the StartPlatformAPIServer plugin wiring to
remove the live Config *config.Server from the shared dependency object. Expose
only immutable, narrowly scoped configuration values or interfaces required by
plugins, and ensure shared capability fields cannot be replaced or used to
mutate server configuration while preserving the existing plugin functionality.
- Around line 47-64: Update platform-api/pdk/deps.go lines 47-64 so the Gateways
capability derives organization scope from the request context/organization
claim instead of accepting caller-supplied orgID parameters, while preserving
the CRUD operations. Update platform-api/pdk/middleware/auth.go lines 30-40 so
external AuthSkipPaths are not appended to the server-managed authentication
skip-list; keep bypass prefixes controlled by the platform/admin configuration.

In `@platform-api/pdk/plugin.go`:
- Around line 59-65: Centralize validation for authentication skip paths and
apply it to both plugin tiers: update AuthSkipPathProvider handling in
platform-api/pdk/plugin.go (lines 59-65) and the internal plugin path handling
in platform-api/internal/plugin/plugin.go (lines 100-109) to accept only
normalized, route-bound allowlisted prefixes. Reject malformed or overly broad
declarations and fail closed before adding paths to the authentication skip
list; ensure authentication decisions use normalized request paths rather than
unsafe raw prefix matching.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bb85e271-bdd6-4b4d-bb0c-ccbdaa88b40c

📥 Commits

Reviewing files that changed from the base of the PR and between eb5f7b1 and e476f57.

📒 Files selected for processing (14)
  • platform-api/cmd/main.go
  • platform-api/cmd/plugins_experimental.go
  • platform-api/cmd/plugins_oss.go
  • platform-api/internal/plugin/plugin.go
  • platform-api/internal/plugin/registry.go
  • platform-api/internal/server/external_plugin.go
  • platform-api/internal/server/server.go
  • platform-api/pdk/deps.go
  • platform-api/pdk/middleware.go
  • platform-api/pdk/middleware/auth.go
  • platform-api/pdk/plugin.go
  • platform-api/platform/middleware.go
  • platform-api/platform/options.go
  • platform-api/platform/platform.go
💤 Files with no reviewable changes (1)
  • platform-api/internal/plugin/registry.go

Comment on lines +458 to 460
for _, p := range plugins {
if err := p.Init(pluginDeps); err != nil {
return nil, fmt.Errorf("plugin %q failed to initialize: %w", p.Name(), err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Roll back initialized plugins when a later plugin fails.

A later Init error returns immediately, leaving earlier external/internal plugins running. platform.App.Run returns that error rather than terminating the process, so plugin goroutines or connections can leak.

Proposed rollback
+	initializedPlugins := make([]plugin.Plugin, 0, len(plugins))
+	startupSucceeded := false
+	defer func() {
+		if startupSucceeded {
+			return
+		}
+		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+		defer cancel()
+		for i := len(initializedPlugins) - 1; i >= 0; i-- {
+			if err := initializedPlugins[i].Shutdown(ctx); err != nil {
+				slogger.Error("Plugin rollback shutdown error", "plugin", initializedPlugins[i].Name(), "error", err)
+			}
+		}
+	}()
+
 	for _, p := range plugins {
 		if err := p.Init(pluginDeps); err != nil {
 			return nil, fmt.Errorf("plugin %q failed to initialize: %w", p.Name(), err)
 		}
+		initializedPlugins = append(initializedPlugins, p)
 		// ...
 	}
+	startupSucceeded = true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for _, p := range plugins {
if err := p.Init(pluginDeps); err != nil {
return nil, fmt.Errorf("plugin %q failed to initialize: %w", p.Name(), err)
initializedPlugins := make([]plugin.Plugin, 0, len(plugins))
startupSucceeded := false
defer func() {
if startupSucceeded {
return
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
for i := len(initializedPlugins) - 1; i >= 0; i-- {
if err := initializedPlugins[i].Shutdown(ctx); err != nil {
slogger.Error("Plugin rollback shutdown error", "plugin", initializedPlugins[i].Name(), "error", err)
}
}
}()
for _, p := range plugins {
if err := p.Init(pluginDeps); err != nil {
return nil, fmt.Errorf("plugin %q failed to initialize: %w", p.Name(), err)
}
initializedPlugins = append(initializedPlugins, p)
// ...
}
startupSucceeded = true
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform-api/internal/server/server.go` around lines 458 - 460, Update the
plugin initialization loop in the server setup to track successfully initialized
plugins and, when a later plugin’s Init fails, shut down all previously
initialized plugins before returning the initialization error. Reuse each
plugin’s existing cleanup or shutdown API, preserve reverse initialization order
if supported, and keep the current wrapped error from the failing plugin.

Comment on lines +473 to +477
// Declared public paths are appended before the auth middleware is built
// below, so the skip-path list is complete when the chain is assembled.
if sp, ok := p.(plugin.AuthSkipPathProvider); ok {
cfg.Auth.SkipPaths = append(cfg.Auth.SkipPaths, sp.AuthSkipPaths()...)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
ast-grep outline platform-api/internal/middleware/auth.go --items all
rg -n -C3 'SkipPaths|HasPrefix|URL\.Path|EscapedPath|path\.Clean' platform-api/internal/middleware

Repository: wso2/api-platform

Length of output: 6946


🏁 Script executed:

#!/bin/bash
set -eu -o pipefail

# Inspect the auth middleware skip-path comparison and surrounding normalization imports/usages.
sed -n '1,150p' platform-api/internal/middleware/auth.go

# Search all middleware files for path normalization helpers and path-based comparisons.
rg -n '\b(HasPrefix|TrimPrefix|TrimSuffix|path\.Clean|EscapedPath|URL\.Path|TrimRight|path\.)\b' platform-api/internal/middleware platform-api/internal/server

Repository: wso2/api-platform

Length of output: 6205


🏁 Script executed:

#!/bin/bash
set -eu -o pipefail

# Behavioral probe for Go’s path HasPrefix semantics over the same inputs used by the middleware check.
# This does not run repository code; it matches how strings.HasPrefix handles raw path prefixes.
cat >/tmp/skip_prefix_probe.go <<'EOF'
package main

import (
	"fmt"
	"strings"
)

type skip = []string

func bypass(providedSkip string, requestURLPath string, skipList skip) bool {
	for _, path := range skipList {
		if strings.HasPrefix(requestURLPath, path) {
			return true
		}
	}
	return false
}

func main() {
	cases := []struct {
		name        string
		skipList    skip
		requestPath string
	}{
		{"legitimate exact", nil, "/api/public/a"},
		{"raw prefix match", skip{"/api/public"}, "/api/public-a"},
		{"malicious dotdot bypass", skip{"/api/public"}, "/api/public/../secret"},
		{"malicious encoded traversal", skip{"/api/public"}, "/api/public/%2e%2e/secret"},
		{"canonical segment looks safe", skip{"/api/public"}, "/api/public%2f.."},
	}
	skipList := skip{"/api/public"}
	for _, c := range cases {
		list := c.skipList
		if list == nil {
			list = skipList
		}
		fmt.Printf("%s: skip=%q request=%q skip=%v bypass=%v\n", c.name, list[0], c.requestPath, list, bypass(list[0], c.requestPath, list))
	}
}
EOF
go run /tmp/skip_prefix_probe.go

Repository: wso2/api-platform

Length of output: 668


Normalize paths before matching skip paths.

LocalJWTAuthMiddleware currently compares config.SkipPaths against the raw r.URL.Path with strings.HasPrefix, so configured prefix skips are not normalized and malformed request paths such as /api/public/../secret can bypass authentication. Canonicalize skip paths and normalize EscapedPath (rejecting forbidden sequences first), then compare using a path-aware prefix check that respects path segments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform-api/internal/server/server.go` around lines 473 - 477, Update
LocalJWTAuthMiddleware to validate and normalize the request’s EscapedPath
before matching, rejecting forbidden traversal or malformed sequences before
authentication bypass evaluation. Canonicalize each configured config.SkipPaths
entry and replace the raw strings.HasPrefix comparison with a path-aware prefix
check that only matches complete path segments, preserving valid public-path
skips.

Source: Coding guidelines

Comment thread platform-api/pdk/deps.go
Comment on lines +38 to +45
type Deps struct {
Gateways Gateways
// add more capability groups as external plugins need them
// (APIs, Subscriptions, Applications, Projects, Organizations, LLM, MCP, …)

Config *config.Server
Logger *slog.Logger
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not expose the mutable server configuration to external plugins.

StartPlatformAPIServer passes the same *pdk.Deps to every external plugin. Exported fields plus Config *config.Server allow one plugin to mutate authentication, database, or listener configuration—or replace capabilities for later plugins. Pass immutable, narrowly scoped configuration values/interfaces instead of the live server config.

The server wiring confirms that this dependency object is shared across external plugins.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform-api/pdk/deps.go` around lines 38 - 45, Update Deps and the
StartPlatformAPIServer plugin wiring to remove the live Config *config.Server
from the shared dependency object. Expose only immutable, narrowly scoped
configuration values or interfaces required by plugins, and ensure shared
capability fields cannot be replaced or used to mutate server configuration
while preserving the existing plugin functionality.

Comment thread platform-api/pdk/deps.go
Comment on lines +47 to +64
// Gateways exposes CRUD access to the platform's gateways, scoped by organization.
// Every method mirrors an existing GatewayService method verbatim and takes the
// organization id explicitly — handlers MUST pass the org resolved from the
// request context, never one from request input (GO-AUTH-005).
type Gateways interface {
// RegisterGateway creates a gateway in an organization (Create).
RegisterGateway(orgID string, id *string, displayName, description string, endpoints []string,
isCritical bool, functionalityType, version, createdBy string, properties map[string]any) (*api.GatewayResponse, error)

// GetGateway returns a single gateway by id within an organization (Read).
GetGateway(gatewayID, orgID string) (*api.GatewayResponse, error)

// UpdateGateway updates a gateway within an organization (Update).
UpdateGateway(gatewayID, orgID, updatedBy string, req *api.GatewayResponse) (*api.GatewayResponse, error)

// DeleteGateway removes a gateway within an organization (Delete).
DeleteGateway(gatewayID, orgID, deletedBy string) error
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)deps\.go$|(^|/)middleware/auth\.go$|(^|/)plugin\.go$|platform-api/pdk' | sed -n '1,120p'

echo "== relevant outlines =="
for f in platform-api/pdk/deps.go platform-api/pdk/middleware/auth.go platform-api/pdk/plugin.go platform-api/internal/plugin/plugin.go; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    wc -l "$f"
    ast-grep outline "$f" --view compact 2>/dev/null | sed -n '1,160p' || true
  fi
done

echo "== deps.go relevant =="
sed -n '1,140p' platform-api/pdk/deps.go

echo "== middleware auth relevant =="
sed -n '1,100p' platform-api/pdk/middleware/auth.go

echo "== pdk plugin relevant =="
sed -n '1,120p' platform-api/pdk/plugin.go

echo "== internal plugin relevant =="
sed -n '1,150p' platform-api/internal/plugin/plugin.go

Repository: wso2/api-platform

Length of output: 13776


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== internal middleware auth =="
sed -n '1,220p' platform-api/internal/middleware/auth.go

echo "== auth skip path usage =="
rg -n "AuthSkipPaths|SkipPaths|GetOrganizationFromRequest|organization" platform-api/internal platform-api/pdk platform-api/plugins -S | sed -n '1,240p'

echo "== service gateway methods =="
rg -n "type GatewayService|func \(.*GatewayService.*\).*(Register|Get|Update|Delete)Gateway|Create|Read|Update|Delete" platform-api/internal/service -S | sed -n '1,220p'

echo "== gateway service implementation slices =="
for f in $(rg -l "type GatewayService|func \(.*GatewayService.*\).*(Register|Get|Update|Delete)Gateway" platform-api/internal/service -S); do
  echo "--- $f ---"
  wc -l "$f"
  if [ $(wc -l < "$f") -le 260 ]; then
    sed -n '1,260p' "$f"
  else
    rg -n -C 20 "func \(.*GatewayService.*\).*(Register|Get|Update|Delete)Gateway" "$f" | sed -n '1,260p'
  fi
done

echo "== pdk Deps assignment =="
rg -n "Deps\b|Gateways\b|pdk.Deps|Server\(" platform-api -S | sed -n '1,240p'

Repository: wso2/api-platform

Length of output: 50373


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== gateway service relevant methods =="
sed -n '540,790p' platform-api/internal/service/gateway.go

echo "== gateway repo relevant =="
rg -n -C 12 "func .*Create\\(|func .*GetByUUID|func .*UpdateGateway\\(|func .*Delete \\(|HasGateway|organization_uuid|organizationUUID" platform-api/internal/repository/gateway.go platform -S --glob '*.go' | sed -n '1,220p'

echo "== pdk deps assignment =="
rg -n "pdk\.Deps\{|Gateways:\s+.*GatewayService|&GatewayService\{|Deps: \{|\*GatewayService" platform-api -S

Repository: wso2/api-platform

Length of output: 26530


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== pdk deps assignment =="
rg -n "pdk\.Deps\{|Gateways:\s+\*service\.GatewayService|GatewayService\{|Deps: \{|\*GatewayService" platform-api -S

echo "== all AddAuthSkipPath/Plugin.AuthSkipPaths wiring =="
rg -n -C 8 "AddAuthSkipPath|AuthSkipPaths|SkipPaths" platform-api -S

Repository: wso2/api-platform

Length of output: 26112


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== server pdk deps creation =="
sed -n '400,455p' platform-api/internal/server/server.go

echo "== server middleware auth build =="
sed -n '540,710p' platform-api/internal/server/server.go

Repository: wso2/api-platform

Length of output: 9278


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== platform client uses for pdk AuthSkipPathProvider =="
rg -n -C 6 "implements|pdk\.Plugin|AuthSkipPaths\(\).*\[\]string|func \\(.*\\) AuthSkipPaths" . -S --glob '*.go' --glob '!**/*test.go' | sed -n '1,220p'

Repository: wso2/api-platform

Length of output: 18368


Derive tenant context at the pdk capability boundary.

The pdk contract currently lets plugins pass any orgID into pdk.Gateways, and external AuthSkipPaths is appended to the server skip-list before auth is built, both relying on callers/plugins to stay in tenant scope. Tie these operations to the request organization claim and keep bypass prefixes under platform/admin control.

📍 Affects 2 files
  • platform-api/pdk/deps.go#L47-L64 (this comment)
  • platform-api/pdk/middleware/auth.go#L30-L40
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform-api/pdk/deps.go` around lines 47 - 64, Update
platform-api/pdk/deps.go lines 47-64 so the Gateways capability derives
organization scope from the request context/organization claim instead of
accepting caller-supplied orgID parameters, while preserving the CRUD
operations. Update platform-api/pdk/middleware/auth.go lines 30-40 so external
AuthSkipPaths are not appended to the server-managed authentication skip-list;
keep bypass prefixes controlled by the platform/admin configuration.

Source: Coding guidelines

Comment on lines +59 to +65
// AuthSkipPathProvider is an optional interface a Plugin may also implement to
// declare public (unauthenticated) path prefixes. The server appends them to the
// auth skip-path list before the auth middleware is built. Keep prefixes narrow
// and specific — this is an auth-bypass surface (GO-AUTH-004).
type AuthSkipPathProvider interface {
AuthSkipPaths() []string
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Centralize validation of plugin authentication bypass paths.

Both plugin tiers can return arbitrary path prefixes, which the server adds directly to its authentication skip list. A broad or malformed prefix can bypass authentication for protected endpoints.

  • platform-api/pdk/plugin.go#L59-L65: constrain external plugin paths to a validated, route-bound allowlist.
  • platform-api/internal/plugin/plugin.go#L100-L109: apply the identical validation to internal plugin paths and fail closed on invalid declarations.

As per coding guidelines, request paths must be normalized before authentication decisions and raw prefix matching must not permit authorization bypasses.

📍 Affects 2 files
  • platform-api/pdk/plugin.go#L59-L65 (this comment)
  • platform-api/internal/plugin/plugin.go#L100-L109
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@platform-api/pdk/plugin.go` around lines 59 - 65, Centralize validation for
authentication skip paths and apply it to both plugin tiers: update
AuthSkipPathProvider handling in platform-api/pdk/plugin.go (lines 59-65) and
the internal plugin path handling in platform-api/internal/plugin/plugin.go
(lines 100-109) to accept only normalized, route-bound allowlisted prefixes.
Reject malformed or overly broad declarations and fail closed before adding
paths to the authentication skip list; ensure authentication decisions use
normalized request paths rather than unsafe raw prefix matching.

Source: Coding guidelines

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.

1 participant