documentation/blog/2025-06-02-goose-panther-mcp/index.md
Detection engineering stands at the forefront of cybersecurity, yet it’s often a tangled web of complexity. Traditional detection writing involves painstaking manual processes encompassing log format and schema comprehension, intricate query creation, threat modeling, and iterative manual detection testing and refinement, leading to time expenditure and reliance on specialized expertise. This can lead to gaps in threat coverage and an overwhelming number of alerts. At Block, we face the relentless challenge of evolving threats and intricate system complexities. To stay ahead, we've embraced AI-driven solutions, notably Goose, Block’s open-source AI agent, and Panther MCP, to allow the broader organization to contribute high-quality rules that are contextual to their area of expertise. This post delves into how we're transforming complicated detection workflows into streamlined, AI-powered, accessible processes for all stakeholders.
<!-- truncate -->Historically, creating effective detections has been a niche skill, requiring deep technical knowledge and coding proficiency. This has created significant obstacles such as:
We envision a future where anyone at Block can effortlessly create and deploy security detections, revolutionizing our defenses through intelligent automation and empowering a democratized security posture.
Panther MCP is an open-source model context protocol server born from the collaboration between Panther and Block to democratize security operations workflows. By tightly integrating with Goose as an extension, Panther MCP allows security teams at Block to translate natural language instructions into precise, executable SIEM detection logic, making threat detection contributions easier and faster than ever.
This integration empowers analysts and engineers across Block to interact with Panther’s security analytics platform seamlessly. It shifts detection development from a coding-heavy process into an intuitive workflow accessible to everyone, regardless of technical background. Goose serves as an intermediary agent, coordinating calls to Panther MCP, reviewing the output, creating rule content, testing it, and making necessary edits for correctness or style. This AI-driven feedback loop saves countless hours of time.
Panther MCP offers dozens of tools that enhance and accelerate detection engineering workflows powered by Goose:
Goose significantly accelerates security detection creation by using AI to automate traditionally manual tasks like log analysis and rule generation. This drastically reduces effort, improves the speed of developing and deploying threat coverage, and enhances agility against evolving threats.
Panther MCP functions as a Goose extension, seamlessly embedding its capabilities within the Goose environment through the following process:
.goosehintsThe integration between Panther MCP and Goose is enhanced through the use of the .goosehints file—a Goose feature that supplies additional context like rule examples and best practices. This enriched context enables Goose to generate more accurate and efficient detections, aligned with Block’s standards and requirements.
Let's illustrate this with an example: creating a rule to detect users adding themselves to privileged Okta groups, a common privilege escalation technique.
Traditionally, creating this detection would require:
With Goose and Panther MCP, this becomes as simple as:
“Write a detection rule for users adding themselves to privileged Okta groups.”
When a natural language request like "Write a detection rule for users adding themselves to privileged Okta groups" is received, Goose leverages a sophisticated, multi-stage process powered by Panther MCP to generate production-ready detection logic. This automated approach mirrors the workflow of an experienced detection engineer, encompassing threat research, relevant log identification, detection goal definition, logic outlining, sample log analysis, rule development, false positive consideration, severity/context assignment, thorough testing, refinement/optimization, and documentation. However, Goose executes these steps with the speed and scalability afforded by AI and automation.
Goose first parses the natural language input to understand the core intent and requirements. It identifies key entities like "users", "privileged Okta groups", and the action "adding themselves". This understanding forms the basis for outlining the detection's objective, the necessary log source (Okta.SystemLog), and the fundamental logic: identifying events where the actor (user initiating the action) is the same as the target user (the user being added to the group), and the group being joined is designated as privileged. Goose also considers potential false positives (e.g., legitimate automated processes) and assigns a preliminary severity level based on the potential impact of the detected activity (privilege escalation).
To ensure the generated logic is accurate and operates on valid data, Goose interacts with Panther MCP to retrieve the schema of the specified log source (Okta.SystemLog). This provides Goose with a structured understanding of the available fields and their data types within Okta logs. Furthermore, Goose utilizes Panther MCP's querying capabilities to fetch sample log events related to group membership changes. This step is crucial for:
group.user_membership.add).The interaction with Panther MCP at this stage involves API calls to retrieve schema information and execute analytical queries, enabling Goose to ground its reasoning in actual log data.
Goose doesn't operate in isolation; it accesses a repository of existing Panther detection rules to identify similar logic or reusable components. This promotes consistency across the detection landscape, encourages the reuse of well-tested helper functions (like okta_alert_context), and ensures adherence to established rule standards within our security ecosystem. Learning from existing detections is a core component of Goose’s intelligence, allowing it to build upon prior knowledge and avoid reinventing the wheel.
Based on the understanding of the detection goal, the analysis of log data, and the knowledge gleaned from existing detections facilitated by Panther MCP, Goose generates the complete Panther detection rule in Python. This includes:
rule()): This function contains the core logic for evaluating each log event. In the example, it checks for the group.user_membership.add event type, verifies that the actor and target user IDs (or emails) are the same, and confirms that the target group's display name contains keywords indicative of a privileged group (defined in the PRIVILEGED_GROUPS set).title(), alert_context(), severity(), destinations()): These functions provide crucial context and operational information for triggered alerts.from panther_okta_helpers import okta_alert_context
# Define privileged Okta groups - customize this list based on your organization's needs
PRIVILEGED_GROUPS = {
"_group_admin", # Administrator roles
"admin",
"administrator",
"application-admin",
"aws_", # AWS roles can be privileged
"cicd_corp_system", # CI/CD admin access
"grc-okta",
"okta-administrators",
"okta_admin",
"okta_admin_svc_accounts", # Admin roles
"okta_resource-set_", # Resource sets are typically privileged
"security-admin",
"superadministrators",
}
def rule(event):
"""Determine if a user added themselves to a privileged group"""
# Only focus on group membership addition events
if event.get("eventType") != "group.user_membership.add":
return False
# Ensure both actor and target exist in the event
actor = event.get("actor", {})
targets = event.get("target", [])
if not actor or len(targets) < 2:
return False
actor_id = actor.get("alternateId", "").lower()
actor_user_id = actor.get("id")
# Extract target user and group
target_user = targets[0]
target_group = targets[1] if len(targets) > 1 else {}
# The first target should be a user and the second should be a group
if target_user.get("type") != "User" or target_group.get("type") != "UserGroup":
return False
target_user_id = target_user.get("id")
target_user_email = target_user.get("alternateId", "").lower()
group_name = target_group.get("displayName", "").lower()
# Check if the actor added themselves to the group
is_self_add = (actor_user_id == target_user_id) or (actor_id == target_user_email)
# Check if the group is privileged
is_privileged_group = any(priv_group in group_name for priv_group in PRIVILEGED_GROUPS)
return is_self_add and is_privileged_group
def title(event):
"""Generate a descriptive title for the alert"""
actor = event.get("actor", {})
targets = event.get("target", [])
actor_name = actor.get("displayName", "Unknown User")
actor_email = actor.get("alternateId", "[email protected]")
target_group = targets[1] if len(targets) > 1 else {}
group_name = target_group.get("displayName", "Unknown Group")
return (f"User [{actor_name} ({actor_email})] added themselves "
f"to privileged Okta group [{group_name}]")
def alert_context(event):
"""Return additional context for the alert"""
context = okta_alert_context(event)
# Add specific information about the privileged group
targets = event.get("target", [])
if len(targets) > 1:
target_group = targets[1]
context["privileged_group"] = {
"id": target_group.get("id", ""),
"name": target_group.get("displayName", ""),
}
return context
def severity(event):
"""Calculate severity based on group name - more sensitive groups get higher severity"""
targets = event.get("target", [])
if len(targets) <= 1:
return "Medium"
target_group = targets[1]
group_name = target_group.get("displayName", "").lower()
# Higher severity for direct admin groups
if any(name in group_name for name in ["admin", "administrator", "superadministrators"]):
return "Critical"
return "High"
def destinations(_event):
"""Send to staging destination for review"""
return ["staging_destination"]
Beyond the Python code, Goose also generates the corresponding YAML-based rule configuration file. This file contains essential metadata about the detection:
AnalysisType: rule
Description: Detects when a user adds themselves to a privileged Okta group, which could indicate privilege escalation attempts or unauthorized access.
DisplayName: "Users Adding Themselves to Privileged Okta Groups"
Enabled: true
DedupPeriodMinutes: 60
LogTypes:
- Okta.SystemLog
RuleID: "goose.Okta.Self.Privileged.Group.Add"
Threshold: 1
Filename: goose_okta_self_privileged_group_add.py
Reference: >
https://developer.okta.com/docs/reference/api/system-log/
https://attack.mitre.org/techniques/T1078/004/
https://attack.mitre.org/techniques/T1484/001/
Runbook: >
1. Verify if the user should have access to the privileged group they added themselves to
2. If unauthorized, revoke the group membership immediately
3. Check for other group membership changes made by the same user
4. Review the authentication context and security context for suspicious indicators
5. Interview the user to determine intent
Reports:
MITRE ATT&CK:
- TA0004:T1078.004 # Privileged Accounts: Cloud Accounts
- TA0004:T1484.001 # Domain Policy Modification: Group Policy Modification
Severity: High
Tags:
- author:tomasz
- coauthor:goose
Tests:
- Name: User adds themselves to privileged group
ExpectedResult: true
Log:
actor:
alternateId: [email protected]
displayName: Jane Doe
id: 00u1234abcd5678
type: User
authenticationContext:
authenticationStep: 0
externalSessionId: xyz1234
client:
device: Computer
geographicalContext:
city: San Francisco
country: United States
geolocation:
lat: 37.7749
lon: -122.4194
postalCode: "94105"
state: California
ipAddress: 192.168.1.100
userAgent:
browser: CHROME
os: Mac OS X
rawUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
zone: "null"
debugContext:
debugData:
requestId: req123456
requestUri: /api/v1/groups/00g123456/users/00u1234abcd5678
url: /api/v1/groups/00g123456/users/00u1234abcd5678
displayMessage: Add user to group membership
eventType: group.user_membership.add
legacyEventType: group.user_membership.add
outcome:
result: SUCCESS
published: "2023-07-15 14:25:30.811"
request:
ipChain:
- geographicalContext:
city: San Francisco
country: United States
geolocation:
lat: 37.7749
lon: -122.4194
postalCode: "94105"
state: California
ip: 192.168.1.100
version: V4
securityContext:
asNumber: 12345
asOrg: Example ISP
domain: example.com
isProxy: false
isp: Example ISP
severity: INFO
target:
- alternateId: [email protected]
displayName: Jane Doe
id: 00u1234abcd5678
type: User
- alternateId: unknown
displayName: okta_admin_person_role_super_admin
id: 00g5678abcd1234
type: UserGroup
transaction:
detail: {}
id: transaction123
type: WEB
uuid: event-uuid-123
version: "0"
p_event_time: "2023-07-15 14:25:30.811"
p_parse_time: "2023-07-15 14:26:00.000"
p_log_type: "Okta.SystemLog"
- Name: User adds another user to privileged group
ExpectedResult: false
Log:
actor:
alternateId: [email protected]
displayName: Admin User
id: 00u5678abcd1234
type: User
authenticationContext:
authenticationStep: 0
externalSessionId: xyz5678
client:
device: Computer
geographicalContext:
city: San Francisco
country: United States
geolocation:
lat: 37.7749
lon: -122.4194
postalCode: "94105"
state: California
ipAddress: 192.168.1.100
userAgent:
browser: CHROME
os: Mac OS X
rawUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
zone: "null"
debugContext:
debugData:
requestId: req789012
requestUri: /api/v1/groups/00g123456/users/00u9876fedc4321
url: /api/v1/groups/00g123456/users/00u9876fedc4321
displayMessage: Add user to group membership
eventType: group.user_membership.add
legacyEventType: group.user_membership.add
outcome:
result: SUCCESS
published: "2023-07-15 14:30:45.123"
request:
ipChain:
- geographicalContext:
city: San Francisco
country: United States
geolocation:
lat: 37.7749
lon: -122.4194
postalCode: "94105"
state: California
ip: 192.168.1.100
version: V4
securityContext:
asNumber: 12345
asOrg: Example ISP
domain: example.com
isProxy: false
isp: Example ISP
severity: INFO
target:
- alternateId: [email protected]
displayName: Regular User
id: 00u9876fedc4321
type: User
- alternateId: unknown
displayName: okta_admin_person_role_super_admin
id: 00g5678abcd1234
type: UserGroup
transaction:
detail: {}
id: transaction456
type: WEB
uuid: event-uuid-456
version: "0"
p_event_time: "2023-07-15 14:30:45.123"
p_parse_time: "2023-07-15 14:31:00.000"
p_log_type: "Okta.SystemLog"
Every detection rule generated by Goose undergoes rigorous automated testing and validation. This includes:
The seamless integration of Goose with Panther MCP automates these intricate steps, significantly reducing the time and specialized knowledge required to create and deploy security detections. This democratization empowers more individuals to contribute to Block's security posture, leading to more comprehensive threat coverage and a more resilient security environment.
A typical detection creation workflow now looks like:
rule() checks. Standardized formatting, including brackets for dynamic alert title text, enhances readability and consistency.event.deep_get() and event.deep_walk() instead of importing them manually, ensuring consistency and maintainability within the platform.Block is dedicated to improving its security defenses and supporting its team by leveraging AI. We believe AI holds significant promise for the future of detection and response at Block and are committed to making security more accessible.
<!-- Social Media Meta Tags (edit values as needed) --> <head> <meta property="og:title" content="Democratizing Detection Engineering at Block: Taking Flight with Goose and Panther MCP" /> <meta property="og:type" content="article" /> <meta property="og:url" content="https://goose-docs.ai/blog/2025/06/02/goose-panther-mcp" /> <meta property="og:description" content="A comprehensive overview of how Block leverages Goose and Panther MCP to democratize and accelerate security detection engineering." /> <meta property="og:image" content="https://goose-docs.ai/assets/images/goose-panther-header-25b5891acdd70e6a7bbe6b84e34f08f0.png" /> <meta name="twitter:card" content="summary_large_image" /> <meta property="twitter:domain" content="goose-docs.ai" /> <meta name="twitter:title" content="Democratizing Detection Engineering at Block: Taking Flight with Goose and Panther MCP" /> <meta name="twitter:description" content="A comprehensive overview of how Block leverages Goose and Panther MCP to democratize and accelerate security detection engineering." /> <meta name="twitter:image" content="https://goose-docs.ai/assets/images/goose-panther-header-25b5891acdd70e6a7bbe6b84e34f08f0.png" /> </head>