Skip to content

Benchmark: grafana PR 79265 - #11

Open
celmis-codereviewer wants to merge 5 commits into
cr-base-79265from
cr-pr-79265
Open

celmis-codereviewer wants to merge 5 commits into
cr-base-79265from
cr-pr-79265

Conversation

@celmis-codereviewer

Copy link
Copy Markdown

Benchmark reproduction of grafana#79265

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

celmis-codereviewer

This comment was marked as outdated.

@celmis-codereviewer celmis-codereviewer left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 COMMENT — findings to consider

Full findings and scope are in the review summary comment on this pull request — one persistent comment, updated in place on every run.

device.UpdatedAt.UTC().Add(-anonymousDeviceExpiration), device.UpdatedAt.UTC().Add(time.Minute),
}
err := s.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
args = append([]interface{}{query}, args...)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: args is declared on line 80 outside the closure and mutated on line 84 via append; if WithDbSession retries the callback, args will retain the previously prepended query string and receive a duplicate, causing dbSession.Exec on line 85 to fail.

🟠 Outer slice variable mutated inside database session closure

The args slice is declared outside WithDbSession at line 80. Inside the closure passed to WithDbSession, line 84 reassigns args = append([]interface{}{query}, args...). If WithDbSession retries the callback (e.g., due to a transient database error or connection retry), args will already contain query at index 0 from the previous execution, leading to duplicate query arguments being passed to dbSession.Exec on line 85 and causing SQL execution failure.

To fix this, avoid mutating the outer args slice inside the closure. Either construct the argument list locally within the closure or pass query directly to dbSession.Exec.

Suggested change
args = append([]interface{}{query}, args...)
result, err := dbSession.Exec(append([]interface{}{query}, args...)...)

agent: defect · rule: defect.state-mutation · confidence: 0.95

if err := a.anonDeviceService.TagDevice(newCtx, httpReqCopy, anonymous.AnonDeviceUI); err != nil {
a.log.Warn("Failed to tag anonymous session", "error", err)
if err := a.anonDeviceService.TagDevice(ctx, httpReqCopy, anonymous.AnonDeviceUI); err != nil {
if errors.Is(err, anonstore.ErrDeviceLimitReached) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: err can be ErrDeviceLimitReached on line 45; returning nil, err blocks anonymous user authentication when the device limit is reached, allowing an unauthenticated attacker to trigger a denial of service for all anonymous users.

🟠 Anonymous authentication failure on device limit causes Denial of Service

When anonymousDeviceLimit is configured, reaching the device limit causes TagDevice to return ErrDeviceLimitReached. Checking for this error and returning nil, err inside Authenticate fails authentication for anonymous requests. An unauthenticated attacker can make requests with different device headers or cookies until anonymousDeviceLimit is reached, preventing any subsequent anonymous user from accessing Grafana.

Suggested change
if errors.Is(err, anonstore.ErrDeviceLimitReached) {
if errors.Is(err, anonstore.ErrDeviceLimitReached) {
a.log.Debug("Anonymous device limit reached", "error", err)
}

agent: security · rule: sec.cwe-400 · confidence: 0.95

var query string

// if device limit is reached, only update devices
if s.deviceLimit > 0 {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why: On line 109, CountDevices reads the current device count outside a lock or transaction before line 118 inserts a new record, allowing concurrent requests to both read a count below s.deviceLimit and create devices that exceed the limit.

🟡 Check-then-act race condition in device limit enforcement

When s.deviceLimit is set, CreateOrUpdateDevice counts active devices on line 109 and checks whether count >= s.deviceLimit on line 113. Because this read and the subsequent insertion on line 118 are not atomic or guarded by a transaction lock, concurrent anonymous authentication requests can both observe count < s.deviceLimit at the same time and create new devices, exceeding the configured limit.

Suggested change
if s.deviceLimit > 0 {
Perform the device count check and device insertion within an isolated database transaction or under a lock to prevent concurrent requests from exceeding `deviceLimit`.

agent: defect · rule: defect.race-condition · confidence: 0.95

@celmis-codereviewer

Copy link
Copy Markdown
Author

🤖 Code Review for PR #11

⚙ ADJUSTED — graph context partial (9 of 11 changed files): 2 of 11 changed files have no symbols in the index; 1 of them is still in the checkout the index was built from (packages/grafana-data/src/types/config.ts) — the index is stale there, or the extractor could not parse it; run analyzer generate or index it from the Repositories page (POST /api/repos/index-all); 1 of them is not in that checkout at all (pkg/api/frontendsettings.go) — this PR's base is older than the indexed revision, so those files were renamed or deleted before it and no re-index can bring them back; there is nothing to fix.

💬 COMMENT — findings to consider

Findings

  • 🟠 Error: 2
  • 🟡 Warning: 1

Scope

  • Files changed: 11
  • Lines: +105 / -37

Performance

  • Analysis time: 146.9s · agents: structural, cve, contract, security, defect · tokens: 29,504/34,653

Powered by Code Analyzer · context: tree-sitter graph + structural, cve, contract, security, defect

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.

3 participants