prep for release v3.104.0 - #2007
Conversation
Co-authored-by: panther-bot-automation <github-service-account-automation@panther.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: panther-bot-automation <github-service-account-automation@panther.io>
Co-authored-by: panther-bot-automation <github-service-account-automation@panther.io>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: panther-bot-automation <github-service-account-automation@panther.io>
PR SummaryMedium Risk Overview Adds new correlation & scheduling artifacts: adds correlation rules for S3 security-control disabling, S3 exfiltration-followed-by-deletion, and Azure blob upload followed by CPK encryption error; adds disabled Okta AD-agent PantherFlow baseline scheduled queries (30/90/180 day windows) for lookup-table generation. Tuning/enablement changes: marks several GAIA/Google Workspace scheduled rules and the Written by Cursor Bugbot for commit 529acff. This will update automatically on new commits. Configure here. |
📐 Style Guide ReviewAnalyzing commit: Style Compliance: GOOD 📋 Style Findings✅ Compliant Areas
|
🐍 Python Logic ReviewAnalyzing commit: Logic Quality: GOOD 🔍 Logic Analysis✅ Well-Implemented
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Databricks pack missing all detection rule IDs
- Added all 37 Databricks detection rule IDs to the pack definition alongside the existing global helper.
- ✅ Fixed: Excluded path substring matching causes false positive filtering
- Replaced simple substring matching with proper path segment boundary checking to prevent paths like /users/status-update from incorrectly matching /status.
Or push these changes by commenting:
@cursor push 1236854883
Preview (1236854883)
diff --git a/global_helpers/panther_databricks_helpers.py b/global_helpers/panther_databricks_helpers.py
--- a/global_helpers/panther_databricks_helpers.py
+++ b/global_helpers/panther_databricks_helpers.py
@@ -381,9 +381,16 @@
Boolean indicating if this path should be excluded
"""
path = event.deep_get("requestParams", "path", default="")
- # Check if any excluded path is a segment in the full path
- # This avoids matching "status" in paths like "/users/status-update"
- return any(excluded in path for excluded in EXCLUDED_PATHS)
+ # Check if any excluded path is a complete segment in the full path
+ # This avoids matching "/status" in paths like "/users/status-update"
+ for excluded in EXCLUDED_PATHS:
+ idx = path.find(excluded)
+ if idx != -1:
+ end_idx = idx + len(excluded)
+ # Check if the match ends at a path boundary (end of string or followed by '/')
+ if end_idx == len(path) or path[end_idx] == "/":
+ return True
+ return False
def is_config_change(event, config_category=None):
diff --git a/packs/databricks.yml b/packs/databricks.yml
--- a/packs/databricks.yml
+++ b/packs/databricks.yml
@@ -5,4 +5,42 @@
IDs:
# Globals
- panther_databricks_helpers
+ # Rules
+ - Databricks.Audit.AccessToMultipleWorkspaces
+ - Databricks.Audit.AccessTokenRevoked
+ - Databricks.Audit.AccountAdminPrivilegedRoleAssignment
+ - Databricks.Audit.AttemptedLogonFromDeniedIP
+ - Databricks.Audit.ConfigChangesAccountLevel
+ - Databricks.Audit.ConfigChangesHighPriority
+ - Databricks.Audit.ConfigChangesWorkspaceLevel
+ - Databricks.Audit.DataDownloadsFromControlPlane
+ - Databricks.Audit.DataMovementExplicitCredentials
+ - Databricks.Audit.DeltaSharingIPAccessFailures
+ - Databricks.Audit.DeltaSharingRecipientWithoutIPACLs
+ - Databricks.Audit.DestructiveActivities
+ - Databricks.Audit.EmployeeLogon
+ - Databricks.Audit.GlobalInitScriptChanges
+ - Databricks.Audit.GroupCreated
+ - Databricks.Audit.GroupDeleted
+ - Databricks.Audit.InstallLibraryAllClusters
+ - Databricks.Audit.LongLifetimeTokenGenerated
+ - Databricks.Audit.MetastoreAdminPrivilegeGranted
+ - Databricks.Audit.MFAKeyChange
+ - Databricks.Audit.MountPointCreation
+ - Databricks.Audit.NonSSOLogin
+ - Databricks.Audit.PotentialPrivilegeEscalation
+ - Databricks.Audit.PrincipalRemovedFromGroup
+ - Databricks.Audit.RepeatedAccessToSecrets
+ - Databricks.Audit.RepeatedFailedLoginAttempts
+ - Databricks.Audit.RepeatedUnauthorizedUCDataRequests
+ - Databricks.Audit.RepeatedUnauthorizedUCRequests
+ - Databricks.Audit.SSOConfigChanged
+ - Databricks.Audit.TermsOfServiceChanges
+ - Databricks.Audit.TrufflehogScanDetected
+ - Databricks.Audit.UserAccountCreated
+ - Databricks.Audit.UserAccountDeleted
+ - Databricks.Audit.UserPasswordChanged
+ - Databricks.Audit.UserRoleModified
+ - Databricks.Audit.VerboseAuditLoggingDisabled
+ - Databricks.Audit.WorkspaceAdminPrivilegedRoleAssignment
DisplayName: "Panther Databricks Pack"This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| IDs: | ||
| # Globals | ||
| - panther_databricks_helpers | ||
| DisplayName: "Panther Databricks Pack" |
There was a problem hiding this comment.
Databricks pack missing all detection rule IDs
Medium Severity
The packs/databricks.yml describes itself as "Group of all Databricks detections" but only includes panther_databricks_helpers — none of the ~35 new Databricks rules are listed. Every other pack in the codebase (AWS, Azure, GSuite) includes all their detection rule IDs alongside globals. Users subscribing to this pack would get only the helper module with no actual detections.
| path = event.deep_get("requestParams", "path", default="") | ||
| # Check if any excluded path is a segment in the full path | ||
| # This avoids matching "status" in paths like "/users/status-update" | ||
| return any(excluded in path for excluded in EXCLUDED_PATHS) |
There was a problem hiding this comment.
Excluded path substring matching causes false positive filtering
Medium Severity
The is_excluded_path function uses simple substring matching (excluded in path) despite comments claiming it uses "path segment matching to avoid false positives." For example, EXCLUDED_PATHS includes "/status", which will incorrectly match paths like /users/status-update or /api/status-check, causing legitimate security events to be silently filtered out via filter_noise.
| matched = _waf_rule_group_matched_id(group) | ||
| if matched: | ||
| return matched | ||
| return event.get("terminatingRuleId", "unknown") |
There was a problem hiding this comment.
waf_get_matched_rule misses event-level non-terminating matches
Low Severity
waf_rule_group_matches checks three locations for matches: terminatingRuleId, event-level nonTerminatingMatchingRules, and ruleGroupList. But waf_get_matched_rule only checks ruleGroupList and falls back to terminatingRuleId, skipping event-level nonTerminatingMatchingRules. When a match is found via the event-level path, title() will display the wrong rule (e.g., Default_Action instead of the actual matched rule group).
Additional Locations (1)
📄 YAML Metadata ReviewAnalyzing commit: Metadata Quality: NEEDS IMPROVEMENT 📊 Metadata Analysis✅ Well-Documented
|
🧪 Testing ReviewAnalyzing commit: Test Quality: GOOD 🔬 Test Analysis✅ Good Test Coverage
|
🔍 Query ReviewAnalyzing commit: Query Quality: NEEDS IMPROVEMENT 📊 Query Analysis✅ Good Practices
|
🏗️ Architecture Compliance ReviewAnalyzing commit: Architecture: GOOD 🔧 Architecture Analysis✅ Architectural Strengths
|



No description provided.