Skip to content

Local PFS locks legitimate callers out of /listsecrets and /Telemetries/ after auth fix in #4090 #4130

@YizukiAme

Description

@YizukiAme

Bug Description

The March 13 auth hardening in PR #4090 changed local_user_only() to trust only request.environ["REMOTE_USER"], but the local PFS startup path still launches plain Waitress (waitress.serve(...)) without any middleware that injects REMOTE_USER for local requests.

Under normal WSGI rules, client-supplied headers are exposed as HTTP_* keys, not REMOTE_USER, so local callers never satisfy the guard. The two endpoints still protected by @local_user_only/v1.0/Connections/<name>/listsecrets and /v1.0/Telemetries/ — now return 403 even for the same desktop user who started PFS.

This is not an intentional breaking change — there is no corresponding documentation update, CHANGELOG entry, or migration path. The in-tree tests still send X-Remote-User (which no longer maps to REMOTE_USER), confirming the regression is unintentional.

Root Cause

src/promptflow-devkit/promptflow/_sdk/_service/utils/utils.py L60-66:

user = request.environ.get("REMOTE_USER")
if user != getpass.getuser():
    abort(403)

src/promptflow-devkit/promptflow/_cli/_pf/_service.py:

waitress.serve(app, host=service_host, port=port, threads=PF_SERVICE_WORKER_NUM)
# No middleware to inject REMOTE_USER for local requests

Evidence

  1. Gate reads REMOTE_USERutils.py L60
  2. No injection pathwaitress.serve() is called without any auth middleware
  3. Tests still use old contracttests/sdk_pfs_test/utils.py L66, L129, L231 and test_telemetry_apis.py L15 still send X-Remote-User
  4. Historical context confirms this was the API contract:
  5. No follow-up — No subsequent PR/issue addresses the broken local auth path
  6. #4092 is unrelated — that's a listing/spam issue, not this regression

Steps to Reproduce

  1. Start local PFS: pf service start
  2. Try to list secrets: GET /v1.0/Connections/my-conn/listsecrets
  3. Response: 403 Forbidden (even though you are the local user who started PFS)
  4. Same for POST /v1.0/Telemetries/

Expected Behavior

The security fix in #4090 should have simultaneously provided a new trusted identity mechanism for local PFS callers. Local requests from the user who started PFS should still be authorized.

Suggested Fix

Keep the anti-spoofing fix from #4090, but also add a trusted local auth mechanism that actually populates REMOTE_USER in the PFS hosting stack — for example, a WSGI middleware that sets REMOTE_USER to getpass.getuser() for connections originating from 127.0.0.1/::1. Update the test helpers and swagger text to reflect the real contract.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions