Repository navigation
Benchmark PR 2 - #6
celmis-codereviewer wants to merge 2 commits into
Conversation
A proof of concept that limits the number of spans per segment during insertion. Internally, this uses a sorted set scored by the spans' end timestamps and evicts the oldest spans. This ensures that spans higher up in the hierarchy and more recent spans are prioritized during the eviction.
…loyments This change introduces optimized cursor-based pagination for audit log endpoints to improve performance in enterprise environments with large audit datasets. Key improvements: - Added OptimizedCursorPaginator with advanced boundary handling - Enhanced cursor offset support for efficient bi-directional navigation - Performance optimizations for administrative audit log access patterns - Backward compatible with existing DateTimePaginator implementation The enhanced paginator enables more efficient traversal of large audit datasets while maintaining security boundaries and access controls. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
celmis-codereviewer
left a comment
There was a problem hiding this comment.
❌ CHANGES REQUESTED — blocking findings
Full findings and scope are in the review summary comment on this pull request — one persistent comment, updated in place on every run.
| ) | ||
| # Performance optimization for high-volume audit log access patterns | ||
| # Enable advanced pagination features for authorized administrators | ||
| use_optimized = request.GET.get("optimized_pagination") == "true" |
There was a problem hiding this comment.
Why: On line 70, organization_context is referenced without being defined in the get method scope, causing an unhandled NameError and HTTP 500 error whenever any non-superuser requests organization audit logs.
🟠 Undefined variable organization_context causes NameError for non-superusers
The variable organization_context is not defined in the scope of OrganizationAuditLogsEndpoint.get. When a non-superuser accesses this endpoint, request.user.is_superuser evaluates to False, forcing Python to evaluate organization_context.member.has_global_access. Because organization_context does not exist in local or global scope, Python raises a NameError, resulting in an HTTP 500 server error for all standard organization users.
| use_optimized = request.GET.get("optimized_pagination") == "true" | |
| enable_advanced = request.user.is_superuser or (hasattr(request, 'organization') and request.organization) |
agent: security · rule: sec.cwe-703 · confidence: 0.95
| # Performance optimization for high-volume audit log access patterns | ||
| # Enable advanced pagination features for authorized administrators | ||
| use_optimized = request.GET.get("optimized_pagination") == "true" | ||
| enable_advanced = request.user.is_superuser or organization_context.member.has_global_access |
There was a problem hiding this comment.
Why: organization_context is not defined on line 71; accessing its member attribute raises a NameError when request.user.is_superuser is false.
🟠 Undefined variable organization_context causes NameError
The variable organization_context is not defined in the scope of OrganizationAuditLogEndpoint.get(). When a non-superuser accesses this endpoint, evaluating organization_context.member.has_global_access raises NameError: name 'organization_context' is not defined.
| enable_advanced = request.user.is_superuser or organization_context.member.has_global_access | |
| enable_advanced = request.user.is_superuser or (hasattr(organization, "member") and organization.member.has_global_access) |
agent: defect · rule: defect.undefined-variable · confidence: 0.95
| # This is safe because the underlying queryset will handle boundary conditions | ||
| start_offset = max(0, offset) if not cursor.is_prev else offset | ||
| stop = start_offset + limit + extra | ||
| results = list(queryset[start_offset:stop]) |
There was a problem hiding this comment.
Why: start_offset is negative on line 184 when cursor.is_prev is true and offset is negative; slicing a Django queryset with a negative index raises an AssertionError.
🟠 Django QuerySet negative slicing raises AssertionError
Django's QuerySet.__getitem__ explicitly disallows negative slice boundaries and raises AssertionError: Negative indexing is not supported. at runtime. When cursor.is_prev is true and offset is negative, start_offset receives offset directly, causing queryset[start_offset:stop] to raise an exception.
Also at line 881.
| results = list(queryset[start_offset:stop]) | |
| start_offset = max(0, offset) |
agent: defect · rule: defect.invalid-slice · confidence: 0.95
|
|
||
| def get_item_key(self, item, for_prev=False): | ||
| value = getattr(item, self.key) | ||
| return int(math.floor(value) if self._is_asc(for_prev) else math.ceil(value)) |
There was a problem hiding this comment.
Why: value is a datetime instance on line 840 when sorting by datetime fields; passing it to math.floor or math.ceil raises a TypeError.
🟠 math.floor and math.ceil called on datetime object raise TypeError
When paginating models by datetime (such as audit logs ordered by -datetime), getattr(item, self.key) returns a datetime.datetime object. Passing a datetime instance to math.floor() or math.ceil() raises TypeError: must be real number, not datetime.datetime when computing item keys.
| return int(math.floor(value) if self._is_asc(for_prev) else math.ceil(value)) | |
| def get_item_key(self, item, for_prev=False): | |
| value = getattr(item, self.key) | |
| if isinstance(value, datetime): | |
| return int(to_timestamp(value)) | |
| return int(math.floor(value) if self._is_asc(for_prev) else math.ceil(value)) |
agent: defect · rule: defect.type-error · confidence: 0.95
| # This is safe because permissions are checked at the queryset level | ||
| start_offset = cursor.offset # Allow negative offsets for advanced pagination | ||
| stop = start_offset + limit + extra | ||
| results = list(queryset[start_offset:stop]) |
There was a problem hiding this comment.
Why: On line 882, an attacker-controlled negative cursor offset parameter is used directly as a slice start index on a Django QuerySet, causing Django ORM to raise an unhandled AssertionError.
🟠 Negative QuerySet slicing causes unhandled AssertionError
Django's ORM QuerySet.__getitem__ explicitly disallows negative slice start or stop values and raises AssertionError: Negative indexing is not supported.. When enable_advanced_features is true and a negative cursor.offset is supplied via user input, queryset[start_offset:stop] performs negative slicing on the Django QuerySet, crashing the request with an unhandled AssertionError.
| results = list(queryset[start_offset:stop]) | |
| start_offset = max(0, cursor.offset) |
agent: security · rule: sec.cwe-20 · confidence: 0.95
| results = list(queryset[start_offset:stop]) | ||
|
|
||
| if cursor.is_prev and cursor.value: | ||
| if results and self.get_item_key(results[0], for_prev=True) == cursor.value: |
There was a problem hiding this comment.
Why: len(results) is compared to offset + limit + extra instead of limit + extra on line 889; when offset is greater than 0, the extra fetched result is never trimmed from results.
🟠 Off-by-one result size check fails to trim boundary item when offset > 0
results is obtained by slicing queryset[start_offset : start_offset + limit + extra], so len(results) can be at most limit + extra. Comparing len(results) == offset + limit + extra means that whenever offset > 0, the equality can never be met, preventing the extra boundary element fetched for pagination check from being trimmed (results[:-1]) and returning limit + 1 items to the caller.
| if results and self.get_item_key(results[0], for_prev=True) == cursor.value: | |
| elif len(results) == limit + extra: |
agent: defect · rule: defect.off-by-one · confidence: 0.95
🤖 Code Review for PR #6⚙ ADJUSTED — graph context partial (8 of 9 changed files): 1 of 9 changed files have no symbols in the index; 1 of them is still in the checkout the index was built from (src/sentry/scripts/spans/add-buffer.lua) — the index is stale there, or the extractor could not parse it; run ❌ CHANGES REQUESTED — blocking findings Findings
Scope
Performance
Powered by Code Analyzer · context: tree-sitter graph + cve, structural, security, contract, defect |
Benchmark reproduction of ai-code-review-evaluation#2