mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-06-06 03:37:29 +02:00
Fix critical issues from follow-up security audit
A second-pass audit surfaced three severe issues missed by the previous review, each a sibling code path of a bug class that was only partially fixed before: - auth: JWT session login (jwtSession.go) registered its authenticator even when CROSS_LOGIN_JWT_HS512_KEY was unset, leaving an empty HMAC key. golang-jwt verifies any HS256/HS512 signature against an empty key, allowing unauthenticated admin token forgery. Init() now refuses to register without a key, with a defense-in-depth empty-key guard in the keyfunc. - repository: metric names from GraphQL ([String!]) were interpolated raw into json_extract(footprint, "$.<name>") SQL. SQLite parses double-quoted strings as literals, enabling SQL injection by any authenticated user. Validate metric names against ^[a-zA-Z0-9_]+$ in jobsMetricStatisticsHistogram and buildFloatJSONCondition. - metricstore: cluster/host line-protocol tags flowed unvalidated into path.Join(RootDir, cluster, host) for checkpoint/WAL files, allowing arbitrary file write outside the checkpoint root via NATS (unauthenticated) or POST /api/write. Reject path-traversal sequences in DecodeLine before the tags become path components. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: b57246993ec1
This commit is contained in:
@@ -909,6 +909,13 @@ func (r *JobRepository) jobsMetricStatisticsHistogram(
|
||||
filters []*model.JobFilter,
|
||||
bins *int,
|
||||
) (*model.MetricHistoPoints, error) {
|
||||
// The metric name is interpolated into the json_extract() path of the SQL
|
||||
// below. SQLite parses double-quoted strings as literals, so reject anything
|
||||
// that is not a plain metric identifier to prevent SQL injection.
|
||||
if !validMetricName.MatchString(metric) {
|
||||
return nil, fmt.Errorf("invalid metric name: %q", metric)
|
||||
}
|
||||
|
||||
// Peak value defines the upper bound for binning: values are distributed across
|
||||
// bins from 0 to peak. First try to get peak from filtered cluster, otherwise
|
||||
// scan all clusters to find the maximum peak value.
|
||||
|
||||
Reference in New Issue
Block a user