Skip to content

[fix](arrow-flight) Stop writing bearer tokens to fe.log - #66572

Open
CalvinKirs wants to merge 1 commit into
apache:masterfrom
CalvinKirs:adbc_token
Open

[fix](arrow-flight) Stop writing bearer tokens to fe.log#66572
CalvinKirs wants to merge 1 commit into
apache:masterfrom
CalvinKirs:adbc_token

Conversation

@CalvinKirs

@CalvinKirs CalvinKirs commented Aug 7, 2026

Copy link
Copy Markdown
Member

What problem does this PR solve?

Issue Number: close #xxx

Related PR: #xxx

Problem Summary:

Arrow Flight SQL bearer tokens are written to fe.log in cleartext.

FlightTokenManagerImpl logs the token verbatim at INFO when it is minted, evicted from either cache, and invalidated, and it also puts the token into the IllegalArgumentException messages that FlightBearerTokenAuthenticator.validateBearer logs at ERROR:

LOG.info("Created flight token for user: {}, token: {}", username, token);

A bearer token is a complete credential until it expires — arrow_flight_token_alive_time_second defaults to 86400s. So anyone who can read fe.log, or the log aggregation platform it is shipped to, or a backup of either, can take a live token, send it as Authorization: Bearer <token> to the Arrow Flight SQL port (arrow_flight_sql_port, default 8070), and run queries as that user without ever knowing their password. Logs routinely reach a much wider audience than the credential store does, which is what makes this worth fixing even though the log file itself is not world readable.

What this PR does

Adds org.apache.doris.common.util.TokenMasker, which offers the two renderings a secret can reasonably have in a message:

  • tokenId(t)sha256:1a2b3c4d, a truncated SHA-256. It is stable, so a log line and the error message returned to the client still point at the same token and can be matched up, but no part of the secret survives in it. This is what the flight token paths now use. The existing "search for this token in fe.log to see the evict reason" hint therefore still works — it now says token id, and the id appears both in the client's error and in the log.
  • maskPrefix(t)abc***, revealing only a short leading prefix, for the case where a human has to recognize which configured secret was involved (token rotation). This is the helper that already existed privately in MetaService; it is moved into the utility and reused rather than duplicated.

Every token-valued site in the Arrow Flight path is converted: the four LOG.info calls in FlightTokenManagerImpl, the four IllegalArgumentException messages in validateToken/getTokenDetails, the one in FlightSessionsWithTokenManager.createConnectContext, and the teardown warning in FlightSqlConnectPoolMgr.unregisterConnection. That last one is worth spelling out: a Flight SQL ConnectContext's peerIdentity is the bearer token itselfFlightBearerTokenAuthenticator.createAuthResultWithBearerToken returns the token as the peer identity, and FlightSqlConnectPoolMgr keys its flightToken2ConnectionId map by it — so ctx.getPeerIdentity() in a log line leaks a live token under a name that does not look like one.

Two more credentials with the same problem, found while auditing for other instances:

  • Env logs the cluster token adopted from a helper node at INFO (get token from helper node. token={}). That token authenticates metadata access between FE nodes, so it gets maskPrefix, consistent with how MetaService already renders the same token.
  • Auth echoes initial_root_password into a WARN — and it does so from the branch that runs when the configured value failed 2-staged SHA-1 validation, which is exactly the case where an operator put a plaintext password in the config. The value is simply dropped from the message; it adds nothing to the diagnosis that the config key name does not already give.

Finally, a checkstyle rule rejects a value whose name says it holds a token/password/secret/peer identity being passed straight into a LOG.x(...) call, as a parameter or concatenated into the message. It matches across lines, because the credential argument frequently sits on a continuation line — that is true of the FlightSqlConnectPoolMgr case above, which a line-based rule silently misses.

It is a backstop, not a substitute for review, and the honest limitation is that it only knows the naming convention: peerIdentity had to be taught to it by hand once it turned out to be a token, and any other alias would be equally invisible. It reports no violation anywhere in fe/ after this PR, so it lands without a single suppression.

Release note

Arrow Flight SQL bearer tokens are no longer written to fe.log. Log lines and error messages now carry a non-reversible token id (sha256: prefix) instead of the token itself.

Check List (For Author)

  • Test
    • Regression test
    • Unit Test
    • Manual test (add detailed scripts or steps below)
    • No need to test or manual test. Explain why:
      • This is a refactor/code format and no logic has been changed.
      • Previous test can cover this change.
      • No code files have been changed.
      • Other reason

TokenMaskerTest covers that the token id is a digest and cannot contain any part of the token, that it is stable for the same token and differs across tokens, the empty/null handling, and maskPrefix including its too-short-to-reveal branch.

The checkstyle rule was verified to actually fire, not just to be quiet: re-adding the original LOG.info(..., username, token) line, and separately un-masking the multi-line FlightSqlConnectPoolMgr call, each fail the build at that line with the new message; restoring them goes back to green.

  • Behavior changed:
    • No.
    • Yes.

The text of some Arrow Flight error messages changes: where they used to echo the bearer token, they now carry token id: sha256:.... Anything that parsed the token out of an error message or out of fe.log would need to use the id instead. No API, wire format or configuration changes.

  • Does this need documentation?
    • No.
    • Yes.

@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@CalvinKirs

Copy link
Copy Markdown
Member Author

run buildall

@CalvinKirs

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Codex automated review failed and did not complete.

Error: All Codex review accounts are usage-limited; earliest retry is 2026-08-08T03:32:00Z.
Workflow run: https://github.com/apache/doris/actions/runs/31156591198

Please trigger /review again after that time.

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 28848 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 788dfc8eacf6d4dab8b052c502f0706e611552ca, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17591	3926	3888	3888
q2	1986	318	196	196
q3	10287	1347	797	797
q4	4680	465	334	334
q5	7505	827	544	544
q6	176	164	133	133
q7	738	792	596	596
q8	9314	1605	1620	1605
q9	5544	4093	4044	4044
q10	6704	1618	1362	1362
q11	504	344	327	327
q12	730	565	455	455
q13	18095	3247	2738	2738
q14	264	276	243	243
q15	q16	740	718	668	668
q17	1048	1002	1088	1002
q18	6566	5570	5550	5550
q19	1174	1207	982	982
q20	789	656	580	580
q21	5593	2518	2508	2508
q22	428	353	296	296
Total cold run time: 100456 ms
Total hot run time: 28848 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	4264	4184	4168	4168
q2	277	330	208	208
q3	4478	4983	4377	4377
q4	2155	2262	1438	1438
q5	4278	4133	4152	4133
q6	220	169	125	125
q7	1705	1579	1451	1451
q8	2464	2374	2164	2164
q9	7386	7212	7264	7212
q10	4284	4271	3848	3848
q11	549	426	357	357
q12	712	716	520	520
q13	3189	3484	3116	3116
q14	299	299	272	272
q15	q16	688	754	649	649
q17	1317	1333	1286	1286
q18	12152	11052	11841	11052
q19	1199	1111	1145	1111
q20	2221	2210	1949	1949
q21	5778	4852	4935	4852
q22	521	460	404	404
Total cold run time: 60136 ms
Total hot run time: 54692 ms

Arrow Flight SQL bearer tokens were logged verbatim at INFO when they were
minted, evicted and invalidated, and were embedded in the
IllegalArgumentExceptions that FlightBearerTokenAuthenticator logs at ERROR.
A bearer token is a full credential until it expires
(arrow_flight_token_alive_time_second, one day by default), so anyone able to
read fe.log or the log pipeline - operators without any database privilege,
log aggregation users, backups - could replay one against the Arrow Flight SQL
port and run queries as that user.

Add TokenMasker with the two renderings a secret may have in a message:

- tokenId(): a truncated SHA-256, e.g. "sha256:1a2b3c4d". Stable, so log lines
  and the error message handed back to the client still refer to the same
  token, but no part of the secret is disclosed. Used for flight tokens; the
  "search for this token in fe.log" hint keeps working, on the id instead.
- maskPrefix(): reveals a short leading prefix, for the case where a human has
  to recognize which configured secret was involved. This is the helper that
  already lived privately in MetaService, moved here and reused.

Note that a Flight SQL ConnectContext's peerIdentity IS the bearer token, so
the unregisterConnection() teardown log in FlightSqlConnectPoolMgr is masked
too. Two more credentials that had the same problem elsewhere: the cluster
token adopted from a helper node in Env.getClusterIdFromStorage(), and
initial_root_password in Auth, which was echoed by the branch that runs when
the configured value is not a 2-staged SHA-1 hash - that is, when it is most
likely a plaintext password.

Finally, a checkstyle rule rejects a value whose name says it holds a
token/password/secret/peer identity being passed straight to a log call. It
matches across lines, since the argument often sits on a continuation line.
It only knows the naming convention, so it is a backstop rather than a
substitute for review - peerIdentity had to be taught to it by hand. The rule
reports no violation on the current tree.
@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 158367 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 788dfc8eacf6d4dab8b052c502f0706e611552ca, data reload: false

query5	4328	565	447	447
query6	460	233	201	201
query7	4839	567	340	340
query8	315	161	151	151
query9	8750	4011	4021	4011
query10	500	362	290	290
query11	5848	2186	1997	1997
query12	150	98	95	95
query13	1234	590	419	419
query14	6081	4289	3979	3979
query14_1	3777	3819	3855	3819
query15	201	196	173	173
query16	992	459	443	443
query17	922	677	539	539
query18	2456	466	338	338
query19	202	183	142	142
query20	100	100	101	100
query21	227	154	133	133
query22	12994	12995	12874	12874
query23	15840	14927	14655	14655
query23_1	14803	14737	14643	14643
query24	7636	1693	1255	1255
query24_1	1252	1240	1249	1240
query25	500	419	350	350
query26	1320	378	215	215
query27	2580	580	377	377
query28	4539	2013	2006	2006
query29	1059	620	468	468
query30	347	260	226	226
query31	1172	1113	1048	1048
query32	97	63	60	60
query33	524	297	234	234
query34	1177	1176	621	621
query35	748	745	643	643
query36	760	793	701	701
query37	154	107	90	90
query38	1820	1808	1678	1678
query39	821	821	822	821
query39_1	761	776	779	776
query40	251	174	143	143
query41	66	67	66	66
query42	97	95	93	93
query43	319	316	277	277
query44	1439	774	771	771
query45	188	174	176	174
query46	1050	1159	721	721
query47	1552	1579	1425	1425
query48	413	440	309	309
query49	590	409	297	297
query50	1052	432	346	346
query51	10767	10796	10719	10719
query52	88	98	87	87
query53	265	275	198	198
query54	302	246	230	230
query55	77	74	71	71
query56	316	323	311	311
query57	1027	1001	932	932
query58	306	270	279	270
query59	1537	1619	1349	1349
query60	325	287	273	273
query61	179	180	175	175
query62	401	323	271	271
query63	236	209	202	202
query64	2949	1073	852	852
query65	3894	3834	3829	3829
query66	1813	481	357	357
query67	19943	20066	19895	19895
query68	3174	1508	899	899
query69	408	292	267	267
query70	855	792	772	772
query71	349	330	323	323
query72	3050	2595	2313	2313
query73	818	793	447	447
query74	4646	4503	4300	4300
query75	2357	2323	1993	1993
query76	2324	1144	781	781
query77	353	365	278	278
query78	11114	11088	10658	10658
query79	1412	1121	722	722
query80	1276	553	466	466
query81	551	330	286	286
query82	702	171	139	139
query83	388	322	302	302
query84	328	165	132	132
query85	979	618	516	516
query86	400	246	216	216
query87	1992	1986	1851	1851
query88	3700	2779	2767	2767
query89	384	319	288	288
query90	1903	203	207	203
query91	205	185	167	167
query92	65	60	55	55
query93	1691	1496	979	979
query94	695	357	328	328
query95	817	532	475	475
query96	976	793	343	343
query97	2447	2470	2328	2328
query98	198	185	189	185
query99	738	735	635	635
Total cold run time: 245061 ms
Total hot run time: 158367 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.65 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 788dfc8eacf6d4dab8b052c502f0706e611552ca, data reload: false

query1	0.00	0.00	0.01
query2	0.10	0.04	0.04
query3	0.25	0.12	0.13
query4	1.61	0.14	0.14
query5	0.24	0.21	0.21
query6	1.16	0.83	0.79
query7	0.04	0.01	0.00
query8	0.06	0.04	0.03
query9	0.36	0.33	0.30
query10	0.55	0.53	0.52
query11	0.19	0.13	0.14
query12	0.17	0.14	0.14
query13	0.45	0.46	0.46
query14	0.99	0.99	0.96
query15	0.59	0.58	0.57
query16	0.33	0.31	0.32
query17	1.08	1.05	1.12
query18	0.21	0.20	0.20
query19	2.00	1.95	1.94
query20	0.02	0.01	0.01
query21	15.43	0.20	0.13
query22	5.00	0.05	0.05
query23	16.18	0.30	0.12
query24	2.97	0.42	0.29
query25	0.10	0.06	0.05
query26	0.73	0.20	0.15
query27	0.04	0.04	0.04
query28	3.57	0.66	0.36
query29	12.47	3.93	3.18
query30	0.27	0.17	0.15
query31	2.77	0.55	0.31
query32	3.22	0.59	0.48
query33	3.07	3.25	3.14
query34	15.57	3.92	3.27
query35	3.21	3.22	3.23
query36	0.55	0.44	0.44
query37	0.08	0.07	0.06
query38	0.05	0.03	0.04
query39	0.04	0.02	0.02
query40	0.16	0.15	0.14
query41	0.09	0.04	0.04
query42	0.04	0.03	0.03
query43	0.04	0.03	0.04
Total cold run time: 96.05 s
Total hot run time: 23.65 s

@CalvinKirs

Copy link
Copy Markdown
Member Author

run buildall

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-H: Total hot run time: 29319 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpch-tools
Tpch sf100 test result on commit 66d27c868aaa56336ecb433e51ce44e60bcd86a1, data reload: false

------ Round 1 ----------------------------------
============================================
q1	17602	4006	3955	3955
q2	2006	330	198	198
q3	10294	1409	836	836
q4	4678	466	348	348
q5	7480	846	553	553
q6	179	175	139	139
q7	733	891	601	601
q8	9337	1585	1642	1585
q9	5256	4067	4052	4052
q10	6736	1620	1364	1364
q11	505	353	320	320
q12	751	560	448	448
q13	18058	3269	2750	2750
q14	264	256	243	243
q15	q16	739	725	656	656
q17	1047	1054	952	952
q18	6564	5646	5581	5581
q19	1305	1283	1152	1152
q20	816	694	545	545
q21	6178	2851	2719	2719
q22	461	372	322	322
Total cold run time: 100989 ms
Total hot run time: 29319 ms

----- Round 2, with runtime_filter_mode=off -----
============================================
q1	5019	4647	4693	4647
q2	298	348	220	220
q3	4965	5225	4649	4649
q4	2293	2282	1486	1486
q5	4741	4472	4495	4472
q6	233	177	130	130
q7	1893	1765	1575	1575
q8	2417	2180	2178	2178
q9	7221	6932	6762	6762
q10	4207	4226	3786	3786
q11	541	410	378	378
q12	708	716	500	500
q13	2959	3289	2805	2805
q14	266	284	251	251
q15	q16	655	680	615	615
q17	1265	1245	1230	1230
q18	12218	10966	11912	10966
q19	1102	1072	1061	1061
q20	2196	2191	1931	1931
q21	5382	4688	4732	4688
q22	511	492	437	437
Total cold run time: 61090 ms
Total hot run time: 54767 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
TPC-DS: Total hot run time: 157830 ms
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/tpcds-tools
TPC-DS sf100 test result on commit 66d27c868aaa56336ecb433e51ce44e60bcd86a1, data reload: false

query5	4296	582	458	458
query6	461	233	201	201
query7	4917	585	344	344
query8	328	157	145	145
query9	8752	4081	4097	4081
query10	475	358	300	300
query11	5802	2186	1986	1986
query12	145	98	100	98
query13	1286	587	433	433
query14	6034	4263	3962	3962
query14_1	3773	3792	3763	3763
query15	204	193	179	179
query16	1027	476	446	446
query17	930	720	535	535
query18	2491	452	324	324
query19	220	194	143	143
query20	104	100	101	100
query21	225	159	134	134
query22	13059	13065	12707	12707
query23	15763	15026	14605	14605
query23_1	14680	14624	14703	14624
query24	7434	1682	1218	1218
query24_1	1240	1223	1203	1203
query25	517	443	352	352
query26	1300	361	207	207
query27	2627	603	385	385
query28	4564	2046	2041	2041
query29	1054	607	478	478
query30	345	265	231	231
query31	1185	1108	1034	1034
query32	113	67	57	57
query33	534	301	234	234
query34	1181	1151	641	641
query35	724	748	647	647
query36	771	769	700	700
query37	159	121	99	99
query38	1828	1764	1671	1671
query39	844	832	786	786
query39_1	796	793	791	791
query40	258	169	142	142
query41	81	71	71	71
query42	97	96	96	96
query43	317	318	273	273
query44	1432	778	771	771
query45	196	181	165	165
query46	1099	1215	739	739
query47	1557	1570	1487	1487
query48	396	433	298	298
query49	607	436	311	311
query50	1061	438	337	337
query51	10938	10855	10491	10491
query52	89	90	77	77
query53	265	282	199	199
query54	305	264	239	239
query55	81	73	68	68
query56	344	313	295	295
query57	1048	994	924	924
query58	305	286	275	275
query59	1529	1609	1369	1369
query60	345	284	265	265
query61	180	179	172	172
query62	406	325	271	271
query63	237	199	196	196
query64	3033	1009	842	842
query65	3920	3822	3813	3813
query66	1827	479	385	385
query67	20082	19903	19735	19735
query68	3356	1507	1040	1040
query69	410	306	272	272
query70	902	797	764	764
query71	387	337	325	325
query72	2988	2654	2253	2253
query73	856	749	448	448
query74	4658	4499	4309	4309
query75	2355	2340	2028	2028
query76	2339	1135	735	735
query77	338	361	270	270
query78	11083	11118	10467	10467
query79	1184	1155	772	772
query80	629	567	467	467
query81	461	323	280	280
query82	283	172	143	143
query83	407	328	295	295
query84	328	165	130	130
query85	949	618	502	502
query86	281	227	222	222
query87	1987	1963	1833	1833
query88	3703	2849	2801	2801
query89	372	317	284	284
query90	1964	197	200	197
query91	201	188	164	164
query92	62	59	56	56
query93	1632	1602	1053	1053
query94	537	349	293	293
query95	801	615	486	486
query96	1119	814	349	349
query97	2445	2453	2315	2315
query98	195	186	182	182
query99	745	756	607	607
Total cold run time: 244360 ms
Total hot run time: 157830 ms

@hello-stephen

Copy link
Copy Markdown
Contributor
ClickBench: Total hot run time: 23.91 s
machine: 'aliyun_ecs.c7a.8xlarge_32C64G'
scripts: https://github.com/apache/doris/tree/master/tools/clickbench-tools
ClickBench test result on commit 66d27c868aaa56336ecb433e51ce44e60bcd86a1, data reload: false

query1	0.01	0.01	0.01
query2	0.09	0.06	0.05
query3	0.26	0.14	0.13
query4	1.61	0.15	0.14
query5	0.24	0.22	0.22
query6	1.16	0.81	0.80
query7	0.04	0.01	0.01
query8	0.06	0.04	0.04
query9	0.37	0.30	0.31
query10	0.54	0.58	0.58
query11	0.19	0.14	0.14
query12	0.17	0.14	0.14
query13	0.46	0.46	0.46
query14	0.99	1.00	1.00
query15	0.60	0.58	0.59
query16	0.32	0.33	0.31
query17	1.08	1.08	1.05
query18	0.22	0.21	0.19
query19	2.03	1.98	1.96
query20	0.02	0.01	0.02
query21	15.44	0.18	0.13
query22	5.00	0.05	0.06
query23	16.13	0.31	0.13
query24	2.91	0.41	0.34
query25	0.11	0.05	0.04
query26	0.73	0.22	0.15
query27	0.04	0.04	0.04
query28	3.56	0.76	0.36
query29	12.47	4.02	3.15
query30	0.28	0.15	0.15
query31	2.77	0.56	0.32
query32	3.22	0.59	0.48
query33	3.11	3.17	3.17
query34	15.70	3.94	3.29
query35	3.24	3.21	3.24
query36	0.56	0.44	0.41
query37	0.09	0.07	0.07
query38	0.05	0.04	0.03
query39	0.04	0.04	0.03
query40	0.16	0.16	0.15
query41	0.09	0.03	0.03
query42	0.04	0.03	0.03
query43	0.04	0.04	0.03
Total cold run time: 96.24 s
Total hot run time: 23.91 s

@hello-stephen

Copy link
Copy Markdown
Contributor

FE Regression Coverage Report

Increment line coverage 3.12% (3/96) 🎉
Increment coverage report
Complete coverage report

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.

2 participants