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
- JFrog Platform deployed in HA: Artifactory HA + multiple Xray nodes behind a load balancer without sticky sessions / session affinity.
- 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
- Run an SCA audit that triggers Xray scan-graph polling:
jf audit --watches <watch> --extended-table --nuget=true
- 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)
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 with401 Unauthorized / Authentication failed. The CLI authenticates correctly on the initialPOST /api/v1/scan/graphcall, but loses its authentication on the follow-upGET /api/v1/scan/graph/{scanId}polling call, which reaches the server asanonymousand is rejected with401.This looks like a regression introduced between 2.96.0 and 2.103.0.
Current behavior
Server-side
xray-request-logfor a single failing run (same trace ID, userxxxxx_rw):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: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:
The
POST /scan/graphsucceeds (201); only the pollingGET /scan/graph/{id}is anonymous. It fails whenever the load balancer routes theGETto a different Xray node than the one that served thePOST— deterministic for versions >= 2.103.0, but appears "intermittent" because of normal HA load-balancer routing.Reproduction steps
GETis routed to a different Xray node than thePOST->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 initialPOST, 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)