원클릭으로
threat-model-tnf
Analyze a PR for TNF (Two-Node Fencing) security threats with STRIDE/DFD analysis, MITRE ATT&CK and OWASP mapping
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Analyze a PR for TNF (Two-Node Fencing) security threats with STRIDE/DFD analysis, MITRE ATT&CK and OWASP mapping
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Surface your daily task list — QA-ready tickets, sprint backlog, carry-over items, open PRs, RHEL verification queue, and quarterly reminders. Use at the start of your day to see what needs attention.
Show detailed info about a specific TODO task — its tracked links, notes, and live Jira/PR status. Use when the user asks about a task, wants context to resume work on it, or asks what's needed to finish a ticket. Not for listing all tasks (read the TODO file directly or use edge-ic:sprint-status for sprint-wide views)
End-of-week automation - review active work and prepare next week's TODO
Run the full Prow CI release testing workflow — create PR, trigger jobs, check status, merge PR, download and upload artifacts
Generate interactive PCP performance dashboard from a Prow job URL
Download Prow job artifacts, identify root cause of failure, and produce a structured error report
| name | threat-model:tnf |
| description | Analyze a PR for TNF (Two-Node Fencing) security threats with STRIDE/DFD analysis, MITRE ATT&CK and OWASP mapping |
| disable-model-invocation | true |
| allowed-tools | Read, Grep, Glob, Write, Edit, Bash, WebFetch |
| argument-hint | <PR-number | GitHub-URL | repo PR-number> |
Analyze a pull request for security threats against the TNF (Two-Node Fencing) topology, map to MITRE ATT&CK, and generate a formal report.
This skill focuses on TNF-specific DFD elements, trust boundaries, and code paths. For TNA analysis, use /threat-model:tna.
Bundled with this skill:
dfd-elements-tnf.md — TNF DFD element catalog (P1-P8, DS1-DS5, DF1-DF12, TB1-TB6)Shared references (in $PLUGIN_DIR/references/):
mitre-reference.md — MITRE ATT&CK lookup with DFD element mappingsowasp-reference.md — OWASP Top 10:2025 mapping with DFD element cross-referencesmitre-findings-template.md — Template for cumulative findings trackerDiscovered at runtime from the workspace:
$THREAT_MODEL_DIR/TNF-THREAT-MODEL.md — TNF formal threat model with DFD and per-element STRIDE analysis$FINDINGS_FILE — TNF findings tracker (created from template on first use)Before starting analysis, discover the workspace layout.
Find workspace root: Walk upward from $PWD until a directory containing repos/ is found. If no parent qualifies, fall back to checking whether the current git repo sits inside a repos/ directory:
d="$PWD"
while [ "$d" != "/" ]; do
if [ -d "$d/repos" ]; then
echo "$d"
break
fi
d="$(dirname "$d")"
done
if [ "$d" = "/" ]; then
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
if [ -n "$repo_root" ] && [ "$(basename "$(dirname "$repo_root")")" = "repos" ]; then
echo "$(dirname "$(dirname "$repo_root")")"
fi
fi
Set workspace paths: Once the workspace root (WORKSPACE) is found:
$WORKSPACE/repos/TNF-THREAT-MODEL.md in:
$WORKSPACE/repos/two-node-toolbox/docs/$WORKSPACE/docs/$REPORT_DIR is already set in the environment, use it directly. Otherwise, write reports to the same directory where the threat model is found. If not found, write to $WORKSPACE/reports/ (create if needed).$WORKSPACE/.claude/skills/threat-model/mitre-findings-tnf.md — initialized from $PLUGIN_DIR/references/mitre-findings-template.md on first use.Validate workspace: Warn the user if:
repos/ directory is found| Variable | Description | Example |
|---|---|---|
$WORKSPACE | Root directory containing repos/ | /home/user/Projects/tnf-dev-env |
$REPOS | Repos directory | $WORKSPACE/repos |
$THREAT_MODEL_DIR | Directory containing formal threat model | $REPOS/two-node-toolbox/docs |
$REPORT_DIR | Directory for generated reports | Same as $THREAT_MODEL_DIR or $WORKSPACE/reports |
$FINDINGS_FILE | TNF findings tracker | $WORKSPACE/.claude/skills/threat-model/mitre-findings-tnf.md |
Each threat-model skill writes to its own findings file (mitre-findings-tnf.md, mitre-findings-tna.md, mitre-findings-sno.md, mitre-findings-lvms.md), so no file locking is required during concurrent execution.
Append protocol (use in step 12):
FINDINGS_FILE="$WORKSPACE/.claude/skills/threat-model/mitre-findings-tnf.md"
mkdir -p "$(dirname "$FINDINGS_FILE")"
cp -n "RESOLVED_TEMPLATE_PATH" "$FINDINGS_FILE"
cat >> "$FINDINGS_FILE" <<'FINDINGS_BLOCK'
## TNF — REPO PR #NUMBER (YYYY-MM-DD)
| Technique ID | Technique Name | Finding | Severity | Status | Notes |
|--------------|----------------|---------|----------|--------|-------|
| T#### | Name | VULN-# | Severity | Open | Description |
---
FINDINGS_BLOCK
Substitute RESOLVED_TEMPLATE_PATH with the absolute path to $PLUGIN_DIR/references/mitre-findings-template.md (resolved from this skill's directory). Fill in REPO, NUMBER, YYYY-MM-DD, and the table rows from the current analysis.
/threat-model:tnf 2136
Detects the repository from the current working directory. Must be inside a repo under $REPOS/<repo>/.
/threat-model:tnf https://github.com/ClusterLabs/resource-agents/pull/2136
Extracts org, repo, and PR number from the URL automatically.
/threat-model:tnf resource-agents 2136
Specify repo name and PR number explicitly.
If input is a URL (contains github.com):
https://github.com/<org>/<repo>/pull/<PR>If input is a single number:
repos/<repo-name>/ in the working directoryIf input is <repo> <number>:
| Repo | GitHub Org |
|---|---|
| assisted-service | openshift |
| cluster-etcd-operator | openshift |
| machine-config-operator | openshift |
| installer | openshift |
| cluster-baremetal-operator | openshift |
| resource-agents | ClusterLabs |
| origin | openshift |
| dev-scripts | openshift-metal3 |
| release | openshift |
| enhancements | openshift |
| openshift-docs | openshift |
| pacemaker | ClusterLabs |
gh pr view <PR> --repo <org>/<repo> or WebFetchgh pr diff <PR> --repo <org>/<repo> or WebFetchdfd-elements-tnf.md$THREAT_MODEL_DIR/TNF-THREAT-MODEL.md (if found)$PLUGIN_DIR/references/mitre-reference.md)$REPORT_DIR/$FINDINGS_FILEShellCheck is available in RHEL/Fedora repos (dnf install ShellCheck) - no external downloads required.
command -v shellcheck >/dev/null && echo "shellcheck: installed" || echo "shellcheck: NOT installed (run: dnf install ShellCheck)"
shellcheck -f json <script-file>
shellcheck -S warning <script-file>
shellcheck -s bash <script-file>
| Code | Severity | Security Relevance | MITRE |
|---|---|---|---|
| SC2086 | Warning | Unquoted variable - command injection risk | T1059 |
| SC2091 | Warning | Command in $() used as condition - injection | T1059 |
| SC2046 | Warning | Unquoted command substitution | T1059 |
| SC2012 | Info | Parsing ls output - can be exploited | T1059 |
| SC2029 | Warning | ssh command with unescaped variables | T1059 |
| SC2087 | Warning | Unquoted heredoc - variable expansion | T1059 |
| SC2155 | Warning | Declare/assign separately to avoid masking errors | - |
| SC2164 | Warning | cd without error-exit guard - path traversal risk | T1083 |
Add ShellCheck results under Automated Scanner Results:
## Automated Scanner Results
### ShellCheck
**Tool**: ShellCheck (from RHEL repos)
**Version**: X.X.X
| Code | Severity | File | Line | Message |
|------|----------|------|------|---------|
| SC2086 | warning | podman-etcd | 42 | Double quote to prevent globbing and word splitting |
If ShellCheck is not installed, note: Not installed. Install with: dnf install ShellCheck
If no shell scripts in PR, note: No shell scripts in this PR - skipped.
The following scanners provide additional coverage but require external downloads. Use at your own discretion.
| Tool | Source | Risks | Mitigations |
|---|---|---|---|
| Semgrep | pip/GitHub | Fetches rules from semgrep.dev; may send telemetry | Use --offline mode with local rules |
| Gitleaks | GitHub releases | Binary from external source | Verify checksums; use container image |
| gosec | GitHub/go install | Binary from external source | Verify checksums; audit source |
command -v semgrep >/dev/null && echo "semgrep: installed" || echo "semgrep: not installed (external)"
command -v gitleaks >/dev/null && echo "gitleaks: installed" || echo "gitleaks: not installed (external)"
command -v gosec >/dev/null && echo "gosec: installed" || echo "gosec: not installed (external)"
| Category | Patterns | MITRE | Severity |
|---|---|---|---|
| Command Injection | shell exec, os.system, subprocess, fmt.Sprintf with shell | T1059 | Critical |
| Credentials | hardcoded secrets, API keys, tokens, passwords in code | T1552 | Critical |
| Privilege Escalation | setuid, capabilities, privileged containers, sudo, nsenter | T1548 | High |
| Authentication | auth bypass, weak validation, token handling flaws | T1078 | High |
| Crypto Weakness | weak algorithms, hardcoded keys, disabled TLS verify | T1573 | High |
| Path Traversal | unsanitized file paths, symlink attacks | T1083 | Medium |
| Container Escape | host mounts, hostPID, hostNetwork, privileged mode | T1611 | Critical |
| Logging Exposure | sensitive data in logs, credential printing | T1005 | Medium |
| SSRF/Network | unvalidated URLs, exposed internal endpoints | T1046 | Medium |
| Deserialization | unsafe unmarshal, pickle, yaml.load | T1059 | High |
See dfd-elements-tnf.md for the full element catalog.
| Code Path Pattern | DFD Element | STRIDE Focus |
|---|---|---|
assisted-service/internal/installcfg/ | P1 (Installer) | I, T, R |
assisted-service/internal/bminventory/ | P1 (Installer) | I, S, T |
assisted-service/models/fencing* | P1 (Installer), DF1 | I, T |
cluster-etcd-operator/pkg/tnf/operator/ | P2 (CEO Controller) | S, D, E |
cluster-etcd-operator/pkg/tnf/auth/ | P3 (Auth Job) | S, E |
cluster-etcd-operator/pkg/tnf/setup/ | P4 (Setup Job) | T, I, E, D |
cluster-etcd-operator/pkg/tnf/fencing/ | P5 (Fencing Job) | I, T, R, E |
cluster-etcd-operator/pkg/tnf/pkg/pcs/fencing* | P5, DF7, DF9 | I, T |
cluster-etcd-operator/pkg/tnf/pkg/pcs/cluster* | P4, DS3 | T, D |
cluster-etcd-operator/pkg/tnf/pkg/tools/secrets* | DS2, DF4 | I, T |
cluster-etcd-operator/pkg/tnf/pkg/tools/redact* | P5, DF9 | I, R |
cluster-etcd-operator/pkg/tnf/pkg/exec/ | P3-P5 (nsenter) | E |
cluster-etcd-operator/bindata/tnfdeployment/job* | P3-P5 (container spec) | E |
pacemaker/daemons/fenced/ | P6 (fenced) | S, I, D |
resource-agents/heartbeat/podman-etcd | P7 (OCF Agent) | T, D, I |
resource-agents/heartbeat/podman | P7 (OCF Agent) | T, D |
machine-config-operator/templates/*two-node* | DS4 (PCSD setup) | T, E |
installer/pkg/asset/agent/manifests/fencing* | P1, DS1, DF1, DF2 | I, T |
When a PR modifies code that crosses a trust boundary, apply additional scrutiny:
| Boundary Crossing | Code Indicators | Key Threats |
|---|---|---|
| TB2->TB3 (K8s -> Privileged Container) | Job specs, SA tokens, secret reads | E (escape), I (secret leak) |
| TB3->TB4 (Container -> Host) | nsenter calls, hostPID, privileged | E (host access), T (CIB tamper) |
| TB4->TB5 (Host -> BMC) | fence_redfish calls, Redfish URLs | S (MITM), I (credential exposure) |
| TB2->TB4 (Secrets -> CIB) | Secret->pcs command pipeline | I (plaintext creds in XML) |
| TB6 (Inter-Node) | Corosync config, PCSD auth | S (spoofing), D (quorum loss) |
For each affected DFD element, ask these questions:
Processes (all 6 STRIDE categories):
Data Stores (T, I, D):
Data Flows (T, I, D):
External Entities (S, R):
After identifying per-element threats, check against $THREAT_MODEL_DIR/TNF-THREAT-MODEL.md:
PE-<element>-* IDs in the Per-Element STRIDE Analysis sectionIf the formal threat model file is not found, skip cross-referencing and note this in the report.
Use report templates from $PLUGIN_DIR/references/report-templates.md. Set <topology> to TNF when filling in the templates.