Skip to content

Commit dac99ea

Browse files
committed
Initial import of Falcon Fusion Skills
Six AI coding assistant skills for building CrowdStrike Falcon Fusion workflows, coordinated by a single orchestrator: workflows (the orchestrator), authoring, deployment, execution, lookup-files, and setup. What's included: - Live action discovery against the Falcon Workflows API, with a local cache (1-hour TTL, --clear-cache) - Structural validation against the Charlotte JSON schema (no credentials required), plus an optional server-side dry-run via the import API - 20 Content Library workflow examples, generated deterministically into readable YAML by a bundled converter and each verified to import cleanly, including a real parallel-enrichment playbook (AbuseIPDB) demonstrating fan-out and input gating - HTTP Action, Event Query (Inline.QueryEvent), Python Script (Inline.Python), and Charlotte AI LLM Completion action support - Correct Signal-trigger authoring: every Signal trigger carries the required event: field (the trigger category), discoverable via trigger_search.py --events - Parallel fan-out and per-indicator null-gating guidance so multi-indicator enrichment runs concurrently and only calls APIs for indicators that are present, rather than as a naive serial chain - Shared FalconPy authentication with multi-cloud TOML credential profiles and a guided setup skill (secret entered via the user's editor, never the chat) - 13 pattern-matchable use cases: some drawn from published CrowdStrike Tech Hub posts, others grounded directly in the bundled example workflows and the community Workflow Wednesday series (each cites its source and names the sub-skills it needs) - Cross-plugin advisory that redirects Foundry-app-shaped requests (UI, functions, collections, custom API integrations) to foundry-skills instead of authoring a broken workflow - Browser-based verification harness (verify-workflows.sh) that imports, releases, and confirms workflows against a live CID via Playwright, with passwordless-login handling - Hook scripts for intent routing and cross-plugin advisories to foundry-skills - Comprehensive unit tests (93% coverage, 90% gate), plus pylint 10/10, shellcheck, markdownlint, and structural validation — all enforced in CI Works with Claude Code, Codex, Gemini, and Copilot CLI as a plugin or as a standalone markdown reference. Builds on the MIT-licensed security-skills community project by Paul Price (eth0izzle).
1 parent 6cd1e05 commit dac99ea

133 files changed

Lines changed: 24530 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "fusion-marketplace",
3+
"description": "AI coding assistant skills for building CrowdStrike Falcon Fusion workflows",
4+
"owner": {
5+
"name": "CrowdStrike"
6+
},
7+
"plugins": [
8+
{
9+
"name": "crowdstrike-falcon-fusion",
10+
"source": "./",
11+
"description": "CrowdStrike Falcon Fusion SOAR skills for authoring, deploying, and executing Fusion workflows. Includes live action discovery, YAML authoring with schema validation, workflow import and release, execution monitoring, and Falcon Next-Gen SIEM lookup files.",
12+
"version": "1.0.0",
13+
"author": {
14+
"name": "CrowdStrike"
15+
},
16+
"license": "MIT",
17+
"keywords": [
18+
"crowdstrike",
19+
"falcon",
20+
"fusion",
21+
"soar",
22+
"workflow",
23+
"automation",
24+
"security"
25+
]
26+
}
27+
]
28+
}

.claude-plugin/plugin.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "crowdstrike-falcon-fusion",
3+
"description": "CrowdStrike Falcon Fusion SOAR skills for authoring, deploying, and executing Fusion workflows. Includes live action discovery, YAML authoring with schema validation, workflow import and release, execution monitoring, and Falcon Next-Gen SIEM lookup files.",
4+
"version": "1.0.0",
5+
"author": {
6+
"name": "CrowdStrike"
7+
},
8+
"license": "MIT",
9+
"keywords": [
10+
"crowdstrike",
11+
"falcon",
12+
"fusion",
13+
"soar",
14+
"workflow",
15+
"automation",
16+
"security"
17+
]
18+
}

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
See [AGENTS.md](../AGENTS.md) for AI coding assistant instructions for this repository.

.github/dependabot.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
day: "monday"
8+
time: "14:00"
9+
timezone: "UTC"
10+
ignore:
11+
- dependency-name: "actions/checkout"
12+
versions: [">=6.0.3"]
13+
- dependency-name: "actions/setup-node"
14+
versions: [">=6.3.0"]
15+
- dependency-name: "actions/setup-python"
16+
versions: [">=6.3.0"]

.github/workflows/main.yml

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
name: Fusion Skills CI
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
shellcheck:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
17+
- name: Install ShellCheck
18+
run: command -v shellcheck || { sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck; }
19+
- name: Run ShellCheck
20+
run: |
21+
shellcheck hooks/*.sh bin/*.sh
22+
shellcheck --severity=error *.sh
23+
24+
test-hooks:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
29+
with:
30+
python-version: "3.13"
31+
- name: Install dependencies
32+
run: |
33+
python -m venv .venv
34+
source .venv/bin/activate
35+
pip install --upgrade pip
36+
pip install pyyaml crowdstrike-falconpy
37+
- name: Run hook tests
38+
run: |
39+
source .venv/bin/activate
40+
./test-hooks.sh
41+
- name: Run structural validation
42+
run: |
43+
source .venv/bin/activate
44+
./test-validate.sh
45+
46+
pytest:
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
50+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
51+
with:
52+
python-version: "3.13"
53+
- name: Install dependencies
54+
run: |
55+
python -m venv .venv
56+
source .venv/bin/activate
57+
pip install --upgrade pip
58+
pip install -r requirements-test.txt
59+
- name: Run unit tests
60+
run: |
61+
source .venv/bin/activate
62+
pytest tests/ -v \
63+
--cov=common/scripts \
64+
--cov=skills/authoring/scripts \
65+
--cov=skills/deployment/scripts \
66+
--cov=skills/execution/scripts \
67+
--cov=skills/lookup-files/scripts \
68+
--cov=bin \
69+
--cov-report=term-missing \
70+
--cov-fail-under=90
71+
72+
pylint:
73+
runs-on: ubuntu-latest
74+
steps:
75+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
76+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
77+
with:
78+
python-version: "3.13"
79+
- name: Install dependencies
80+
run: |
81+
python -m venv .venv
82+
source .venv/bin/activate
83+
pip install --upgrade pip
84+
pip install pylint crowdstrike-falconpy pyyaml tomli
85+
- name: Run pylint (fail-under=10 enforced by .pylintrc)
86+
run: |
87+
source .venv/bin/activate
88+
pylint --rcfile=.pylintrc \
89+
common/scripts/*.py \
90+
skills/authoring/scripts/*.py \
91+
skills/deployment/scripts/*.py \
92+
skills/execution/scripts/*.py \
93+
skills/lookup-files/scripts/*.py \
94+
bin/*.py
95+
96+
validate:
97+
runs-on: ubuntu-latest
98+
steps:
99+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
100+
- name: Validate JSON files
101+
run: |
102+
for f in \
103+
hooks/hooks.json \
104+
.claude-plugin/plugin.json \
105+
.claude-plugin/marketplace.json \
106+
test-result-schema.json \
107+
verify-result-schema.json; do
108+
echo "Validating $f"
109+
python -m json.tool "$f" > /dev/null
110+
done
111+
- name: Validate SKILL.md frontmatter
112+
run: |
113+
fail=0
114+
for skill in skills/*/SKILL.md; do
115+
for field in name description version; do
116+
if ! head -20 "$skill" | grep -q "^${field}:"; then
117+
echo "FAIL: $skill missing '$field' in frontmatter"
118+
fail=1
119+
fi
120+
done
121+
done
122+
exit $fail
123+
- name: Validate skill size budgets
124+
run: |
125+
fail=0
126+
total_desc_chars=0
127+
max_tokens=5500
128+
129+
for skill in skills/*/SKILL.md; do
130+
name=$(basename "$(dirname "$skill")")
131+
chars=$(wc -c < "$skill")
132+
approx_tokens=$((chars / 4))
133+
pct=$((approx_tokens * 100 / max_tokens))
134+
135+
if [ "$approx_tokens" -gt "$max_tokens" ]; then
136+
echo "FAIL: $name ~${approx_tokens} tokens (${pct}% of ${max_tokens} limit)"
137+
fail=1
138+
elif [ "$approx_tokens" -gt 4500 ]; then
139+
echo "WARN: $name ~${approx_tokens} tokens (${pct}% of ${max_tokens} limit)"
140+
fi
141+
142+
desc=$(sed -n 's/^description: *//p' "$skill")
143+
desc_len=${#desc}
144+
total_desc_chars=$((total_desc_chars + desc_len))
145+
146+
if [ "$desc_len" -gt 1536 ]; then
147+
echo "FAIL: $name description ${desc_len} chars (max 1536)"
148+
fail=1
149+
fi
150+
done
151+
152+
desc_budget=8000
153+
desc_pct=$((total_desc_chars * 100 / desc_budget))
154+
echo ""
155+
echo "Description budget: ${total_desc_chars} / ~${desc_budget} chars (${desc_pct}%) — 1% of 200k context at ~4 chars/token"
156+
exit $fail
157+
- name: Validate hook scripts are executable
158+
run: |
159+
fail=0
160+
for script in hooks/*.sh; do
161+
[ -x "$script" ] || { echo "FAIL: $script is not executable"; fail=1; }
162+
done
163+
exit $fail
164+
- name: Validate Python scripts are syntactically valid
165+
run: |
166+
fail=0
167+
while IFS= read -r py; do
168+
if ! python -c "import ast, sys; ast.parse(open(sys.argv[1], encoding='utf-8').read())" "$py"; then
169+
echo "FAIL: $py has a syntax error"
170+
fail=1
171+
fi
172+
done < <(find . -name '*.py' -not -path '*/__pycache__/*' -not -path '*/.venv/*')
173+
exit $fail
174+
- name: Validate no PLACEHOLDER values in example workflows
175+
run: |
176+
fail=0
177+
while IFS= read -r wf; do
178+
if grep -qE 'PLACEHOLDER_[A-Z_]+' "$wf"; then
179+
echo "FAIL: $wf contains PLACEHOLDER_* values (action IDs must be resolved)"
180+
grep -nE 'PLACEHOLDER_[A-Z_]+' "$wf"
181+
fail=1
182+
fi
183+
done < <(find skills/authoring/examples -name '*.yaml' -o -name '*.yml')
184+
[ $fail -eq 0 ] && echo "No PLACEHOLDER_* values in example workflows"
185+
exit $fail
186+
- name: Validate version consistency
187+
run: |
188+
fail=0
189+
plugin_version=$(jq -r '.version' .claude-plugin/plugin.json)
190+
marketplace_version=$(jq -r '.plugins[0].version' .claude-plugin/marketplace.json)
191+
echo "plugin.json version: $plugin_version"
192+
echo "marketplace.json plugins[0].version: $marketplace_version"
193+
194+
# marketplace.json must match plugin.json
195+
if [ "$marketplace_version" != "$plugin_version" ]; then
196+
echo "FAIL: marketplace.json plugins[0].version '$marketplace_version' != plugin.json '$plugin_version'"
197+
fail=1
198+
fi
199+
200+
# All SKILL.md versions must match plugin.json
201+
for skill in skills/*/SKILL.md; do
202+
skill_version=$(sed -n 's/^version: *//p' "$skill")
203+
if [ "$skill_version" != "$plugin_version" ]; then
204+
echo "FAIL: $skill version '$skill_version' != plugin.json '$plugin_version'"
205+
fail=1
206+
fi
207+
done
208+
209+
# CHANGELOG must have an entry for this version
210+
if ! grep -q "## \[${plugin_version}\]" CHANGELOG.md; then
211+
echo "FAIL: CHANGELOG.md missing entry for version $plugin_version"
212+
fail=1
213+
fi
214+
215+
# README badge must match
216+
if ! grep -q "version-${plugin_version}-blue" README.md; then
217+
echo "FAIL: README.md badge doesn't match version $plugin_version"
218+
fail=1
219+
fi
220+
221+
[ $fail -eq 0 ] && echo "All versions consistent: $plugin_version"
222+
exit $fail
223+
224+
markdownlint:
225+
runs-on: ubuntu-latest
226+
steps:
227+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
228+
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
229+
with:
230+
node-version: 22
231+
- name: Run markdownlint
232+
run: npx markdownlint-cli2 "**/*.md"

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Local action discovery cache (per-user, never shipped)
2+
.action_cache.json
3+
4+
# Python
5+
__pycache__/
6+
*.pyc
7+
8+
# Credentials
9+
.env
10+
11+
# IDE / local tools
12+
.idea/
13+
.playwright-mcp/
14+
15+
# Coverage
16+
.coverage
17+
htmlcov/
18+
working/

.markdownlint.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"MD007": false,
3+
"MD009": false,
4+
"MD012": false,
5+
"MD013": false,
6+
"MD022": false,
7+
"MD024": { "siblings_only": true },
8+
"MD028": false,
9+
"MD031": false,
10+
"MD032": false,
11+
"MD033": false,
12+
"MD034": false,
13+
"MD036": false,
14+
"MD040": false,
15+
"MD041": false,
16+
"MD045": false,
17+
"MD051": false,
18+
"MD059": false,
19+
"MD060": false
20+
}

0 commit comments

Comments
 (0)