fix: resolve all six CodeQL security alerts - #44
Merged
Conversation
CodeQL 在本仓库首次完整扫描后报出 6 条告警(3 high / 2 medium / 1 high), 全部来自既有代码。逐条修复: HttpUtil 的 TLS 校验(#11 high, #9 medium) MyX509TrustManager 的 checkServerTrusted 是空实现、getAcceptedIssuers 返回 null, TrustAnyHostnameVerifier 的 verify 永远返回 true。两者合起来等于把 https 的安全性完全关掉, 任何中间人都能解密和篡改流量。现移除这两个类, 不再覆盖 SSLSocketFactory 与 HostnameVerifier, 交回 JDK 默认实现。 这是行为变更: 面向自签名或过期证书的服务端会开始连接失败。这正是应当暴露的问题, 正确做法是把证书加进信任库而不是关掉校验。 Cookie 缺少 secure(#10 medium) setCookie 只设了 httpOnly。补上 secure(禁止明文链路发送)与 SameSite=Lax(缓解 CSRF)。注意本地用 http 调试时浏览器不会回传该 cookie。 FileUtil 路径注入(#8 high) getNewFileName 用 email 前缀和文件扩展名拼文件名, 两段都来自用户输入。按"最后一个点之后"取扩展名时, a.b/../../evil 这样的文件名会把整段路径带进来。现在两段都只保留 [A-Za-z0-9_-], 落盘再用 normalize + startsWith 限制在 upload 目录内。 顺带修掉同一段代码里 savePath 为空串的问题 —— 原先文件是写进进程工作目录的。 不安全的随机数(#12, #13 high) 根源在 RandomUtil: getTonken / randomPwd / createSalt 都走 RandomStringUtils.random(), 底层是 java.util.Random, 种子只有 48 位且算法公开, 观察到少量输出即可推算后续全部结果。这些值被用作密码盐值和 token, 可预测等于形同虚设。改用 RandomStringUtils.secure()(SecureRandom 支撑)。 CodeQL 把告警报在 UserModel / AdminModel 的 @DaTa 上, 是因为 salt 经由 Lombok 生成的 setter 流入模型字段, 真正的源头在 RandomUtil。 新增 SecurityHardeningTest 覆盖文件名过滤、cookie 标志、盐值与 token 的取值质量。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes all six CodeQL alerts. They are all in pre-existing code — CodeQL had never run on this repository until #43, so this is the first time anyone has seen them.
TrustManagerthat accepts all certificatescore/.../HttpUtil.javacore/.../HttpUtil.javacore/.../HttpUtil.javacore/.../FileUtil.javawebsite/.../UserModel.java,AdminModel.javaTLS validation was switched off entirely
MyX509TrustManagerhad an emptycheckServerTrustedand returnednullfromgetAcceptedIssuers.TrustAnyHostnameVerifier.verifyreturnedtrueunconditionally. Together they disable certificate-chain and hostname validation on every HTTPS request this utility makes — any machine on the path can decrypt and rewrite the traffic.Both classes are removed, and
initHttpsno longer overridesSSLSocketFactoryorHostnameVerifier. The JDK default validates properly.This is a behaviour change. Any server this code talks to that presents a self-signed or expired certificate will now fail to connect. That is the bug becoming visible rather than a new bug: the fix is to add the certificate to the trust store, not to turn validation off.
Cookies lacked the secure flag
setCookiesethttpOnlybut notsecure, so the cookie was sent over plaintext HTTP. AddedsetSecure(true)andSameSite=Lax. Worth knowing when testing locally: browsers will not return asecurecookie over plain HTTP.Path injection in
FileUtilgetNewFileNamebuilds a filename from the email local-part and the file extension, both user-supplied. Taking "everything after the last dot" as the extension means an upload nameda.b/../../evilcontributesb/../../evilto the path. The result was concatenated straight into aFileOutputStreampath.Both components are now filtered to
[A-Za-z0-9_-], and the write resolves throughnormalize()thenstartsWith(root)against a dedicateduploaddirectory — the same canonical guard used in thefileuploadmodule, which CodeQL recognises.While in there:
savePathwas initialised to""and never assigned a directory, so uploads landed in the process working directory. Now they go toupload/.Insecure randomness
The two alerts point at
@DataonUserModelandAdminModel, which is CodeQL following the taint into Lombok-generated setters. The actual source isRandomUtil:getTonken,randomPwdandcreateSaltall calledRandomStringUtils.random(), which is backed byjava.util.Random— a 48-bit seed and a published algorithm, so observing a handful of outputs is enough to predict the rest. These values are used as password salts and cache tokens, where predictability defeats the purpose.Switched to
RandomStringUtils.secure(), which isSecureRandom-backed (available since commons-lang3 3.16; this project is on 3.20).RandomUtil.random(min, max),randomElementandisGenerateare left onThreadLocalRandom. They pick demo data, not secrets, and CodeQL does not flag them.Verification
New
SecurityHardeningTestcovers the parts that can be asserted directly — traversal fragments stripped from both filename components,secureandhttpOnlyboth set on the cookie, salts of the right length with no collisions across 500 draws, and tokens that are all digits.Full build passes across all 21 modules with the existing 24 tests still green.