Skip to content

Add MCP file deletion and webhook creation detections to Suspicious MCP Activities - #4128

Open
eeee2345 wants to merge 2 commits into
splunk:developfrom
eeee2345:detections/mcp-suspicious-activities-expansion
Open

eeee2345 wants to merge 2 commits into
splunk:developfrom
eeee2345:detections/mcp-suspicious-activities-expansion

Conversation

@eeee2345

@eeee2345 eeee2345 commented Jun 15, 2026 •

Copy link
Copy Markdown

Details

Adds two TTP detections and two supporting macros to the Suspicious MCP Activities story. Both use the existing MCP Server data source (mcp:jsonrpc), and their unit tests use the mcp.log dataset in splunk/attack_data.

  • MCP Webhook Persistence Creation (T1546): inbound create_webhook calls where the destination host is not in mcp_trusted_webhook_domains, the URL uses plain http, or the host is a raw IP address. By default the macro matches nothing, so every new webhook shows up until someone fills it in.
  • MCP Suspicious File Deletion (T1485): inbound delete_file calls where a deleted path matches mcp_security_relevant_deletion_targets (SECURITY.md, audit and access logs, .github/ and other CI config, key and secret files), or where one host makes 10 or more deletions.

An earlier revision also included MCP Source Code Secret Search. I removed it because it overlaps with the is_secret_hunting branch of MCP Github Suspicious Operation: same data source, same search_code method, and six of the same keywords.

Checklist

  • Validate name matches <platform>_<mitre att&ck technique>_<short description> nomenclature. The new files use the same mcp_<short description> naming as the existing detections in this story.
  • CI/CD jobs passed
  • Validated SPL logic. (Reproduced in Python against mcp.log, not run in Splunk; see below.)
  • Validated tags, description, and how to implement.
  • Verified references match analytic.
  • Confirm updates to lookups are handled properly. (No lookup changes.)

Local testing

  • contentctl-ng build passes with contentctl-ng 1.1.1, the version pinned in requirements.txt.
  • scripts/validate_yaml.py and the pre-commit hooks pass.
  • I couldn't run contentctl-ng test locally, so I reproduced both searches in Python against mcp.log. The webhook search matches 5 create_webhook events to http://attacker.com/hook. The deletion search matches 5 delete_file events on SECURITY.md. Each search returns one result row.

@nasbench nasbench added this to the V6.2.0 milestone Jun 16, 2026
@eeee2345

Copy link
Copy Markdown
Author

@patel-bhavin thanks, fair call — you're right it was firing on any delete_file and leaning on the empty filter macro to do the narrowing. Pushed (22cb9e9): the search logic now does the work. It keys off an editable macro of security-relevant deletion targets (SECURITY.md, audit/access logs, .github/ CI config, IaC/pipeline, key/secret files) OR a deletion burst (count >= 10), via where is_security_relevant=1 OR is_deletion_burst=1, so routine single deletions no longer surface. I applied the same in-search narrowing to the over-broad webhook detection (untrusted-domain allowlist + plaintext http + raw-IP host), and left the secret-search one as-is since it already narrows in-query. contentctl-ng build passes locally.

One note on the red unit-testing check: it's the fork-PR Splunkbase-credentials gate — contentctl-ng install needs APPINSPECTUSERNAME/PASSWORD, and GitHub doesn't expose repo secrets to fork PRs, so the Splunkbase app download fails in CI. Not related to these detections; a maintainer run with creds should clear it.

@patel-bhavin

Copy link
Copy Markdown
Contributor

@eeee2345 Thank you for proposing the fix. We are working on getting unit-testing to work on forks and will merge this MR once that feature has been implemented likely in ESCU 6.3.0

@patel-bhavin patel-bhavin modified the milestones: V6.2.0, V6.3.0 Jul 6, 2026
@patel-bhavin

Copy link
Copy Markdown
Contributor

Apologies regarding this delay but we are still waiting on some tooling updates to have forks tested via our unit-testing pipeline!

@patel-bhavin patel-bhavin removed this from the V6.3.0 milestone Jul 24, 2026
@nasbench nasbench added this to the v6.9.0 milestone Oct 15, 2026
@eeee2345
eeee2345 force-pushed the detections/mcp-suspicious-activities-expansion branch from 22cb9e9 to b57749c Compare October 15, 2026 20:17
@eeee2345 eeee2345 changed the title Add three MCP detections to the Suspicious MCP Activities story Add MCP file deletion and webhook creation detections to Suspicious MCP Activities Oct 15, 2026
@eeee2345

Copy link
Copy Markdown
Author

@nasbench @patel-bhavin I force-pushed an update. The search logic and macros for the two remaining detections are unchanged from 22cb9e9.

  • Rebased onto current develop as a single commit.
  • Removed MCP Source Code Secret Search. It overlaps with the is_secret_hunting branch of MCP Github Suspicious Operation (added in MCP detections #3895): same data source, same search_code method, and six of the same keywords.
  • Changed the references to follow the other MCP detections in this story: the MCP TA on Splunkbase, then MITRE T1485 (deletion) or the GitHub webhook docs (webhook), then the Splunk MCP blog post.

I also updated the PR title and description to match.

@nasbench nasbench modified the milestones: v6.9.0, v6.10.0 Oct 15, 2026
@nasbench

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T11:12:18.743991Z b57749c Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b57749c1ff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

| eval webhook_url='params.url'
| eval target_repo='params.repo'
| eval target_owner='params.owner'
| rex field=webhook_url "^(?<url_scheme>https?)://(?<webhook_host>[^/:]+)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Parse URL userinfo before trusting the host

Once mcp_trusted_webhook_domains is populated, a valid HTTPS URL such as https://hooks.example.com:x@evil.test/hook is sent to evil.test because the prefix is URL userinfo, but this rex stops at the first colon and records hooks.example.com as webhook_host. An exact allowlist entry then sets is_trusted_domain=1, while both risk flags remain 0, so the where at line 22 drops this attacker-controlled webhook; parse the authority's host after userinfo (or reject userinfo) before applying the allowlist.

Useful? React with 👍 / 👎.

modification_date: '2026-06-29'
author: Adam Lin
description: Editable regular expression of security-relevant deletion targets used by the MCP Suspicious File Deletion detection to narrow file deletions to data-destruction and defense-evasion candidates. Matches security policy files (SECURITY.md), audit and log paths, CI and workflow configuration under .github/, infrastructure-as-code and pipeline definitions, and common security control files. Edit this macro to add or remove paths that are security-relevant in your environment.
definition: '"(?i)(^|/)(security\.md|codeowners|\.github/|\.gitlab-ci\.yml|\.circleci/|jenkinsfile|\.pre-commit-config\.yaml|dependabot\.ya?ml)|(^|/)(audit|access|secure|auth|security)[^/]*\.log$|(^|/)(audit|logs?|var/log|history)/|\.(pem|key|crt|p12|pfx|kdbx)$|(^|/)(\.env|secrets?\.ya?ml|credentials|\.aws/|\.ssh/|known_hosts|authorized_keys)"'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Recognize backslashes as path separators

For MCP events from Windows—the source definition itself shows a backslash-delimited path at data_sources/mcp_server.yml:178—this regex only recognizes ^ or / before target names and only / inside directory patterns. A deletion such as C:\repo\SECURITY.md or C:\repo\.github\workflows\ci.yml therefore leaves is_security_relevant=0 and is suppressed unless ten deletions happen in the same search window; normalize separators or include backslashes in the boundary patterns.

Useful? React with 👍 / 👎.

@nasbench nasbench modified the milestones: v6.10.0, v6.11.0 Oct 22, 2026
eeee2345 and others added 2 commits October 26, 2026 17:28
Two TTP detections for the Suspicious MCP Activities story on the
mcp:jsonrpc source:

- MCP Suspicious File Deletion: delete_file calls whose target matches the
  editable mcp_security_relevant_deletion_targets macro, or 10 or more
  deletions from one host.
- MCP Webhook Persistence Creation: create_webhook calls to a domain outside
  the editable mcp_trusted_webhook_domains macro, over plain HTTP, or to a
  raw IP address.
@eeee2345

Copy link
Copy Markdown
Author

@nasbench I addressed both Codex findings in a separate commit on top, rebased onto current develop.

  • Webhook host (P1): the rex now skips any userinfo@ before taking the host, using the last @ in the authority as browsers do. https://hooks.example.com:x@evil.test/hook gives evil.test, https://user:pw@hooks.example.com:8443/x gives hooks.example.com, and an @ in the path, query or fragment (https://evil.test/p@hooks.example.com) still gives evil.test. A URL with a backslash in the authority (https://hooks.example.com\@evil.test/) is parsed differently by browsers and by Python's urllib, so it no longer matches and is never treated as trusted.
  • Windows paths (P2): the search converts backslashes to / into a new normalized_path field before matching it against mcp_security_relevant_deletion_targets, so the macro stays a single, readable regex. C:\repo\SECURITY.md, C:\repo\.github\workflows\ci.yml and C:\logs\audit.log now match; C:\repo\src\main.py still does not. target_path in the output keeps the original value.

The events in the mcp.log test dataset are unaffected. contentctl-ng build (1.1.1) passes locally.

@eeee2345
eeee2345 force-pushed the detections/mcp-suspicious-activities-expansion branch from b57749c to b54a292 Compare October 27, 2026 06:05
@nasbench nasbench modified the milestones: v6.10.0, v6.11.0 Nov 2, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants