fix: mask tokens and passwords in logs (#25514)

Full session tokens were written to logs in policy.go, mcclient auth,
oidc handler and the webconsole session manager; guest root passwords
were logged by the linux fsdriver and the nbdkit mount command; MCP
tool arguments and full JSON-RPC bodies (which may contain
server-reset-password passwords) were logged by the llm agent.

Truncate tokens in log messages, drop or mask password values and
log only the tool/method name for MCP calls.

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Jian Qiu
2026-09-03 19:27:34 +08:00
committed by GitHub
parent 2b0d3d4362
commit add8d8381f
8 changed files with 16 additions and 9 deletions

View File

@@ -33,6 +33,7 @@ import (
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/httputils"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apigateway/clientman"
"yunion.io/x/onecloud/pkg/apigateway/options"
@@ -396,7 +397,7 @@ func handleOIDCUserInfo(ctx context.Context, w http.ResponseWriter, req *http.Re
}
token, err := decodeOIDCClientToken(tokenHdr)
if err != nil {
log.Errorf("decodeOIDCClientToken %s fail %s", tokenHdr, err)
log.Errorf("decodeOIDCClientToken %s fail %s", utils.TruncateString(tokenHdr, 16), err)
httperrors.InvalidCredentialError(ctx, w, "Token in header invalid")
return
}

View File

@@ -28,6 +28,7 @@ import (
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/netutils"
"yunion.io/x/pkg/util/rbacscope"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis"
identity_api "yunion.io/x/onecloud/pkg/apis/identity"
@@ -334,7 +335,7 @@ func (manager *SPolicyManager) allowWithoutCache(policies rbacutils.TPolicySet,
user = userCred.GetUserName()
token = userCred.GetTokenString()
}
log.Warningf("no policies fetched for scope %s user %s token %s key %s", scope, user, token, policyKey(userCred))
log.Warningf("no policies fetched for scope %s user %s token %s key %s", scope, user, utils.TruncateString(token, 16), policyKey(userCred))
} else {
matchRules = policies.GetMatchRules(service, resource, action, extra...)
if consts.IsRbacDebug() {

View File

@@ -152,7 +152,9 @@ func (vd *NbdkitDisk) ExecProg() error {
args = append(args, fmt.Sprintf("password=%s", vd.Passwd))
}
cmd := NewCommand("nbdkit", args...)
log.Debugf("command to mount: %s", cmd)
// mask the password in the log, do not print it verbatim
safeCmd := strings.Replace(cmd.String(), "password="+vd.Passwd, "password=******", 1)
log.Debugf("command to mount: %s", safeCmd)
vd.Proc = cmd
vd.NbdURI = ""
err := vd.Proc.Start()

View File

@@ -234,10 +234,10 @@ func (l *sLinuxRootFs) checkInputPasswd(rootFs IDiskPartition, config *pwquality
err := config.Validate(password, account)
if err != nil && errors.Cause(err) == pwquality.ErrPasswordTooWeak {
log.Infof("password %s too weak, try regenerate password", password)
log.Infof("password too weak, try regenerate password")
npassword := config.GeneratePassword(seclib2.RandomPassword2)
if len(npassword) > 0 {
log.Infof("regenerate password %s", npassword)
log.Infof("regenerate password (not logged)")
password = npassword
}
}

View File

@@ -857,7 +857,7 @@ func processToolCalls(
arguments = make(map[string]interface{})
}
log.Infof("Calling tool: %s with arguments: %v", toolName, arguments)
log.Infof("Calling tool: %s", toolName)
// 独立超时 + WithoutCancel避免父请求短 deadline如 60s掐断公有云 create 等待
toolCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), mcpToolCallTimeout())

View File

@@ -334,7 +334,9 @@ func (c *MCPClient) sendRequest(ctx context.Context, req mcp.JSONRPCRequest) (*r
}
reqBody := jsonutils.Marshal(req)
log.Infof("MCP request: %s", reqBody.String())
// log the method only, tool parameters may contain sensitive data
method, _ := reqBody.GetString("method")
log.Infof("MCP request: %s", method)
cli := auth.Client()
if cli == nil {

View File

@@ -28,6 +28,7 @@ import (
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/cache"
"yunion.io/x/pkg/util/httputils"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/syncman"
@@ -123,7 +124,7 @@ func (c *TokenCacheVerify) Verify(ctx context.Context, cli *mcclient.Client, adm
return cred, nil
} else {
c.DeleteToken(token)
log.Infof("Remove expired cache token: %s", token)
log.Infof("Remove expired cache token: %s", utils.TruncateString(token, 16))
}
}

View File

@@ -93,7 +93,7 @@ func (man *SSessionManager) Get(accessToken string) (*SSession, bool) {
protocol := s.GetProtocol()
if protocol != SPICE && time.Since(s.AccessedAt) < AccessInterval {
if !(protocol == WS && o.Options.KeepWebsocketSession) {
log.Warningf("Protol: %q, Token: %s, Session: %s can't be accessed during %s, last accessed at: %s", s.GetProtocol(), accessToken, s.Id, AccessInterval, s.AccessedAt)
log.Warningf("Protol: %q, Token: %s, Session: %s can't be accessed during %s, last accessed at: %s", s.GetProtocol(), utils.TruncateString(accessToken, 16), s.Id, AccessInterval, s.AccessedAt)
return nil, false
}
}