Back to skill

Security audit

BloodHound Narrator

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local BloodHound report generator whose sensitive security terminology and PowerShell use are coherent with its stated purpose.

Install only if you are comfortable running local PowerShell against BloodHound exports and writing Markdown reports. Treat exports as sensitive, use trusted input when possible, and open generated reports in a Markdown viewer that disables raw HTML and remote resource loading until the project escapes untrusted fields.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/NarrativeTemplates.txt:40
Finding

Untrusted BloodHound Data Is Rendered as Raw Markdown and HTML

Content
View full analysis

Vulnerability Details

File Location: scripts/lib/NarrativeTemplates.txt, lines 40–54, 68–76, 482–483, and 540–550
Vulnerability Type: Markdown/HTML content injection
Risk Level: Medium

Vulnerable Code

powershell
$lines.Add("## Executive Summary`n")
$lines.Add("An automated analysis of Active Directory attack paths in **${Domain}** identified **${total} exploitable path(s)** that could allow an attacker to escalate privileges within the environment.`n")
powershell
$lines.Add("### ${emoji} ${label}: $($ClassifiedPath.Description)`n")

$lines.Add("**Source:** ``$($ClassifiedPath.SourceNode)`` | **Target:** ``$($ClassifiedPath.TargetNode)`` | **Hops:** $($ClassifiedPath.HopCount)`n")

$lines.Add("**Attack chain:** ``$($ClassifiedPath.EdgeChain)```n")

$lines.Add("**Business risk:**`n")
foreach ($reason in $ClassifiedPath.Reasons) {
    $lines.Add("- ${reason}")
}
powershell
$lines.Add("### Path: $($ClassifiedPath.PathId) — $($ClassifiedPath.Description)`n")
$lines.Add("**Severity:** $($Script:SeverityLabels[$ClassifiedPath.Severity]) (Score: $($ClassifiedPath.Score)) | **Chain:** ``$($ClassifiedPath.EdgeChain)```n")
powershell
[void]$report.AppendLine("# BloodHound Attack Path Assessment — ${Domain}")
[void]$report.AppendLine("")
[void]$report.AppendLine("**Report generated:** $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')")
if ($ExportDate)  { [void]$report.AppendLine("**Data collected:** ${ExportDate}") }
if ($BHVersion)   { [void]$report.AppendLine("**BloodHound version:** ${BHVersion}") }

Technical Analysis

The report generator interpolates fields originating from the input BloodHound JSON directly into Markdown without contextual escaping or validation. Affected data includes the domain, export date, BloodHound version, path description, path ID, node names, edge labels, and node descriptions incorporated into risk reasons.

Markdown code delimiters do not provide adequate protection because an attacker ca ...[truncated 2458 chars]

Remediation
View remediation

Remediation Suggestions

  1. Implement centralized, context-specific encoding for every value derived from the JSON input:

    • Escape Markdown metacharacters used in ordinary text.
    • Escape pipes and line breaks in table cells.
    • Escape backticks inside inline-code spans or render values in fenced blocks with safe delimiters.
    • Encode HTML-sensitive characters such as &, <, and >.
  2. Normalize or reject dangerous input constructs:

    • Remove disallowed control characters.
    • Reject embedded carriage returns and line feeds where fields should be single-line.
    • Reject or neutralize raw HTML tags.
    • Reject Markdown image and link URI syntax where it is not operationally required.
    • Apply reasonable length limits to metadata, descriptions, names, IDs, and labels.
  3. Separate trusted report templates from untrusted values. Prefer a Markdown-generation library with safe text-node handling rather than constructing the entire report through string interpolation.

  4. Configure the intended report renderer to disable raw HTML and remote-resource loading. Document that generated reports should be opened in a hardened renderer until output encoding is implemented.

  5. Add adversarial regression tests covering:

    • Newlines and injected headings.
    • Backticks and code-fence termination.
    • Markdown links and remote images.
    • Raw HTML, including iframe, img, and event-handler attributes.
    • Table delimiters.
    • ANSI and bidirectional control characters.
    • Excessively long values.
  6. Ensure tests verify that attacker-controlled strings are displayed only as inert literal text and cannot change report structure or produce active links or remote resources.

Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (12)

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · CHANGELOG.md (reported line 16)May include surrounding context.

md
eference.** Truncated exports now render as `<unresolved:id>` instead of failing.
- **Scores could exceed 100.** `path-003` in the bundled fixture scored 105. Capped at 100; `RawScore` and `ScoreCapped` are exposed so the uncapped value is still auditable.
- **`version` in `SKILL.md` frontmatter was stale**, still reading 1.0.0 at the 1.0.1 release.

### Added

- **AD CS detection** — composite BloodHound CE edges `ADCSESC1`, `ADCSESC3`, `ADCSESC4`, `ADCSESC6a/b`, `ADCSESC7`, `ADCSESC9a/b`, `ADCSESC10a/b`, `ADCSESC13`, `GoldenCert`, plus the primitives `ManageCA`, `ManageCertificates`, `WritePKIEnrollmentFlag`, `WritePKINameFlag`, `DelegatedEnrollmentAgent`, `Enroll`. Each carries dedicated remediation guidance.
- **Resource-based constrained delegation** — `AllowedToAct`, `AddAllowedToAct`, `AllowedToDelegate`, with remediation covering the point most often missed: clearing `msDS-AllowedToActOnBehalfOfOtherIdentity` does not close the path if the write permission that set it remai

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The supplied code chunk does not implement the declared reporting functionality. It is only a test harness script for running PowerShell tests: it creates a temporary test file, runs Invoke-Pester, and cleans up. While invoking local PowerShell is consistent with local execution, the primary purpose is materially different from transforming BloodHound exports into dual-layer security reports. Therefore this code chunk does not accurately represent the declared description.

Content

No source excerpt is available for this finding.

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · SKILL.md (reported line 2)May include surrounding context.

md
---
name: BloodHound Narrator
description: Turn BloodHound attack path exports into dual-layer security reports — CISO executive prose on top, technical remediation playbook below. Automates Active Directory audit reporting for pentesters, blue teams, and security consultants. Supports DCSync, Kerberoasting, AD CS abuse (ESC1/3/4/6/7/9/10/13, Golden Certificate), resource-based constrained delegation, shadow credentials, LAPS and gMSA password reads, ACL abuse, GPO takeover, and lateral movement paths. Pure local PowerShell — no API calls, no data leaves your machine. Air-gap compatible.
version: 1.

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/Invoke-BHNarrator.txt (reported line 3)May include surrounding context.

text
<#
.SYNOPSIS
    BloodHound Narrator — local attack-path analysis and dual-layer reporting.

.DESCRIPTION
    Ingests BloodHound Cypher export JSON, classifies every attack path by
    severity (Critical / High / Medium / Low), and generates a Markdown report
    with two layers:
      1. CISO executive prose — risk context, business impact, severity summary.
      2. Technical remediation appendix — step-by-step hardening playbook.

    Pure local PowerShell — no API calls, no data leaves the network.

.PARAMETER InputFile
    Path to the BloodHound Cypher export JSON file.

.PARAMETER OutputFile

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/bh-narrator.sh (reported line 2)May include surrounding context.

sh
#!/usr/bin/env bash
# BloodHound Narrator — bash entry point
# Copies the .txt script to a temp .ps1 so PowerShell can execute it natively.
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MAIN_SCRIPT="$SCRIPT_DIR/Invoke-BHNarrator.txt"

if ! command -v pwsh &>/dev/null; then
    echo "Error: PowerShell (pwsh) is not installed." >&2
    echo "Install via: brew install powershell/tap/powershell" >&2
    exit 1
fi

TEMP="$(mktemp /tmp/bh-narrator-XXXXXX.ps1)"
trap 'rm -f "$TEMP"' EXIT
cp "$MAIN_SCRIPT" "$TEMP"
export BH_NARRATOR_DIR="$SCRIPT_DIR"
pwsh -NoProfile -File "$TEMP" "$@"

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/lib/NarrativeTemplates.txt (reported line 3)May include surrounding context.

text
<#
.SYNOPSIS
    Generates dual-layer Markdown reports from classified BloodHound paths.
    Layer 1: CISO executive prose. Layer 2: Technical remediation appendix.
#>

#region ── Severity Styling ──

$Script:SeverityEmoji = @{
    Critical = [char]::ConvertFromUtf32(0x1F534)   # red circle
    High     = [char]::ConvertFromUtf32(0x1F7E0)   # orange circle
    Medium   = [char]::ConvertFromUtf32(0x1F7E1)   # yellow circle
    Low      = [char]::ConvertFromUtf32(0x1F7E2)   # green circle
}

$Script:SeverityLabels = @{
    Critical = 'CRITICAL'
    High     = 'HIGH'
    Medium   = 'MEDIUM'
    Low      = 'LOW'
}

#endregion

#region ── CISO Narrative He

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · scripts/lib/SeverityClassifier.txt (reported line 3)May include surrounding context.

text
<#
.SYNOPSIS
    Classifies BloodHound attack paths by severity based on edge types,
    target nodes, and path characteristics.

.NOTES
    v1.0.2 — edge scoring is now table-driven. Every edge label the scorer
    understands lives in $Script:EdgeWeights. Labels that are neither weighted
    nor explicitly ignored are collected in $Script:UnknownEdgeLabels so that
    BloodHound schema drift surfaces as a warning instead of a silent zero.
#>

#region ── Tier 0 definitions ──

# Full domain compromise if reached.
$Script:Tier0CoreGroups = @(
    'DOMAIN ADMINS'
    'ENTERPRISE ADMINS'
    'ADMINISTRATORS'

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · tests/Invoke-BHNarrator.Tests.txt (reported line 3)May include surrounding context.

text
<#
.SYNOPSIS
    Pester tests for BloodHound Narrator.
#>

BeforeAll {
    $scriptRoot = Join-Path $PSScriptRoot '..' 'scripts'
    . ([ScriptBlock]::Create((Get-Content -Path (Join-Path $scriptRoot 'lib' 'SeverityClassifier.txt') -Raw)))
    . ([ScriptBlock]::Create((Get-Content -Path (Join-Path $scriptRoot 'lib' 'NarrativeTemplates.txt') -Raw)))

    $testJson   = Join-Path $PSScriptRoot 'synthetic-bloodhound.json'
    $raw        = Get-Content -Path $testJson -Raw | ConvertFrom-Json
    $script:Paths = $raw.paths

    $adcsJson       = Join-Path $PSScriptRoot 'synthetic-adcs.json'
    $adcsRaw        = Get-Content -Path $ad

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · tests/synthetic-adcs.json (reported line 5)May include surrounding context.

json
{
  "meta": {
    "query": "MATCH p=(n)-[:ADCSESC1|ADCSESC4|ADCSESC6a|AddAllowedToAct|AddKeyCredentialLink|ReadLAPSPassword*1..]->(m) RETURN p",
    "exportDate": "2026-07-24T09:12:44Z",
    "bloodhoundVersion": "6.2.0",
    "domain": "YOURBANK.LOCAL",
    "note": "SYNTHETIC AD CS / delegation fixture. No real environment."
  },
  "paths": [
    {
      "id": "adcs-001",
      "description": "ESC1 - enrollee-supplied subject on a client authentication template",
      "nodes": [
        {
          "id": "n-3001",
          "label": "Group",
          "props": {
            "name": "DOMAIN USERS@YOURBANK.LOCAL",
            "description": "All domain users",
            "admincount": false
          }
        },
        {
          "id": "n-3002",
          "label": "CertTemplate",

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Confidence
70% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · tests/synthetic-bloodhound.json (reported line 5)May include surrounding context.

json
{
  "meta": {
    "query": "MATCH p=shortestPath((n)-[*1..]->(m)) WHERE m.name ENDS WITH 'ADMINS@YOURBANK.LOCAL' OR m.objectid ENDS WITH '-516' RETURN p",
    "exportDate": "2026-03-22T14:37:09Z",
    "bloodhoundVersion": "5.4.1",
    "domain": "YOURBANK.LOCAL"
  },
  "paths": [
    {
      "id": "path-001",
      "description": "Kerberoastable SVC account to Domain Admins via DCSync",
      "nodes": [
        {
          "id": "n-1001",
          "label": "User",
          "props": {
            "name": "SVC-SQLREPORT@YOURBANK.LOCAL",
            "displayname": "SQL Reporting Service",
            "enabled": true,
            "hasspn": true,
            "serviceprincipalnames": ["MSSQLSvc/SQLRPT01.YOURBANK.LOCAL:1433"],
            "pwdlastset": "2024-06-11T08:22:00Z",
            "descript

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 34)May include surrounding context.

brew install powershell/tap/powershell

Linux (Ubuntu/Debian)

sudo apt-get install -y powershell

Windows — already included

text

Excessive Permissions

Low
Category
Privilege Escalation
Confidence
80% confidence
Finding

Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.

Content

Scanner excerpt · scripts/lib/NarrativeTemplates.txt (reported line 41)May include surrounding context.

text
$lines = [System.Collections.Generic.List[string]]::new()
    $lines.Add("## Executive Summary`n")
    $lines.Add("An automated analysis of Active Directory attack paths in **${Domain}** identified **${total} exploitable path(s)** that could allow an attacker to escalate privileges within the environment.`n")

    if ($critCount -gt 0) {
        $lines.Add("> **Immediate action required.** ${critCount} path(s) reach Domain Admin or equivalent Tier 0 assets with techniques that are well-documented and actively exploited in the wild.`n")

Static analysis

No suspicious patterns detected.