Skip to content

jf audit fails with 401 Unauthorized on SCA scan against an Xray HA cluster (regression since 2.103.0) #817

Description

@gregoryboue

Describe the bug

When running jf audit (SCA scan) against a JFrog Platform deployed in HA (multiple Xray nodes behind a load balancer), the scan fails with 401 Unauthorized / Authentication failed. The CLI authenticates correctly on the initial POST /api/v1/scan/graph call, but loses its authentication on the follow-up GET /api/v1/scan/graph/{scanId} polling call, which reaches the server as anonymous and is rejected with 401.

This looks like a regression introduced between 2.96.0 and 2.103.0.

Current behavior

failed to execute SCA scan: scanning NuGet dependencies failed with error: server response: 401 Unauthorized
{
  "error": "Authentication failed"
}

Server-side xray-request-log for a single failing run (same trace ID, user xxxxx_rw):

xray-node-B | xxxxx_rw  | POST /api/v1/scan/graph?watch=<watch>&scan_type=dependency | 201
xray-node-D | anonymous | GET  /api/v1/scan/graph/<scanId>                           | 401

At the exact same time, another project on the same cluster using CLI 2.96.0 performs the same POST + GET sequence and stays authenticated on every node (including node-D), returning 202/200:

xray-node-C | yyyyy_rw | POST /api/v1/scan/graph          | 201
xray-node-D | yyyyy_rw | GET  /api/v1/scan/graph/<scanId> | 202   <- stays authenticated
xray-node-A | yyyyy_rw | GET  /api/v1/scan/graph/<scanId> | 200

So the failure correlates with the CLI version, not with the server or the user.

On the Xray node that returns 401, the server log shows the auth-header login being rejected before falling back to anonymous:

[tokens] Failed to get LoginByAuthHeaderWithFallback. err:statusCode: 400
[authorization_filter] Failed to authenticate. err:Error: Authentication failed, StatusCode: 401

The POST /scan/graph succeeds (201); only the polling GET /scan/graph/{id} is anonymous. It fails whenever the load balancer routes the GET to a different Xray node than the one that served the POST — deterministic for versions >= 2.103.0, but appears "intermittent" because of normal HA load-balancer routing.

Reproduction steps

  1. JFrog Platform deployed in HA: Artifactory HA + multiple Xray nodes behind a load balancer without sticky sessions / session affinity.
  2. Configure the CLI server with user/password (or access token):
    jf config add eul --url=https://<platform>/ --user=<user> --password=<pass> --interactive=false
    jf config use eul
    
  3. Run an SCA audit that triggers Xray scan-graph polling:
    jf audit --watches <watch> --extended-table --nuget=true
    
  4. Repeat until the polling GET is routed to a different Xray node than the POST -> failed to execute SCA scan: ... 401 Unauthorized.

Expected behavior

The polling GET /api/v1/scan/graph/{scanId} request must carry the same credentials / access token as the initial POST, so the scan result can be retrieved regardless of which node in an HA cluster the request is routed to (as was the case in 2.96.0).

JFrog CLI-Security version: bundled with JFrog CLI 2.103.0 / 2.105.0
JFrog CLI version (if applicable): 2.103.0 and 2.105.0 fail; 2.96.0 works
Operating system type and version: Linux amd64 (running inside a Jenkins agent container)
JFrog Artifactory version: 7.146.8 (HA, 3 primary nodes)
JFrog Xray version: 3.143.10 (HA cluster, 4 nodes behind a load balancer)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions