Skip to content

Navigation Menu

Sign in
Sign up

CLI Non Interactive

André Henrique edited this page Jun 30, 2026 · 4 revisions

CLI Non-Interactive Mode

IXF can be used without the interactive shell, passing commands directly on the command line. This enables scripting, CI/CD pipelines, automation, scheduled security scans, and one-liner penetration testing workflows — all without requiring a human to drive the interactive shell.


Basic Syntax

ixf <command> [args...]
ixf <command1> <arg1> <command2> <arg2> ...

Commands are separated by spaces and processed sequentially. The IXF shell initializes, runs all commands in order, and exits. Module context is preserved across commands in the same invocation (i.e., after use, subsequent set and run commands target that module).

Installation check:

ixf --version
# IndustrialXPL-Forge v1.0.13
ixf --help
# Shows non-interactive syntax help

20 One-Liner Examples with Full Output

1. Module Statistics

ixf stats
[*] Indexing modules...
[+] 1193 modules indexed.
[i] IXF Module Statistics — IndustrialXPL-Forge v1.0.13
 Total: 1193 | Vendors: 150 | Protocols: 50 | MITRE: 96/103 (93%)
 cve: 486 | exploits: 159 | creds: 34 | scanners: 31 | assessment: 18

2. Search by CVE

ixf search CVE-2021-22681
[*] Indexing modules...
[+] 1193 modules indexed.
[*] Search results for: CVE-2021-22681
 use cve/siemens/cve_2021_22681_s7_1200_hardcoded_key CRITICAL
[*] 1 result(s) found.

3. Load and Simulate a Module

ixf use scanners/ics/modbus_detect set target 192.168.1.100 run
[*] Indexing modules...
[+] 1193 modules indexed.
[*] Module loaded: Modbus TCP Device Detect
[*] target => 192.168.1.100
 [SIMULATE MODE — no packets sent]
 [i] What would happen:
 Phase 1 [TCP Connect]: TCP to 192.168.1.100:502
 Phase 2 [FC04 Probe]: Modbus FC04 Read Input Registers (Unit=1)
 Phase 3 [Fingerprint]: Analyze response for device type
 [i] Payload (hex): 00 01 00 00 00 06 01 04 00 00 00 0A
 [i] MITRE: T0846 (Remote System Discovery)

4. Check Only (Read-Only Probe)

ixf use scanners/ics/modbus_detect set target 192.168.1.100 check
[*] Module loaded: Modbus TCP Device Detect
[*] target => 192.168.1.100
[*] Checking 192.168.1.100:502...
[+] VULNERABLE — Modbus device detected
[+] Device: Schneider Electric Modicon M340 (inferred)

5. MITRE Coverage Report

ixf mitre-coverage
[*] Indexing modules...
 MITRE ATT&CK for ICS Coverage
 Initial Access (TA0108): 9/9 (100%)
 Execution (TA0104): 8/9 (88%)
 ...
 TOTAL: 96/103 (93%)

6. List MITRE Techniques for a Tactic

ixf mitre-list discovery
 MITRE ATT&CK for ICS — Discovery Techniques (TA0102)
 T0840 Network Connection Enumeration 2 modules
 T0842 Network Sniffing 3 modules
 T0846 Remote System Discovery 8 modules
 ...

7. TTP Sweep in Simulate Mode

ixf ttp T0843 192.168.1.100
[*] TTP T0843 (Program Download) — 5 modules — simulate=True
[*] Running module 1/5: cve/siemens/cve_2021_22681_s7_1200_hardcoded_key
 [SIMULATE] CVE-2021-22681 ...
[*] Running module 2/5: cve/siemens/cve_2022_38465_s7_global_key
 [SIMULATE] CVE-2022-38465 ...
[+] T0843 sweep complete: 5 modules (simulate)

8. Vendors List Filtered

ixf vendors japan
 Vendors (7 results — japan)
 Omron 12 CVE | 3 Cred
 Mitsubishi 8 CVE | 1 Cred
 Yokogawa 5 CVE | 1 Cred
 ...

9. Protocols List

ixf protocols
 Protocol Coverage (50 protocols)
 MODBUS TCP 502/TCP 18 modules
 Siemens S7comm 102/TCP 8 modules
 ...

10. Generate JSON Report

ixf use scanners/ics/modbus_detect set target 192.168.1.100 run report json
[*] Module loaded, target set, run complete
[+] Report saved: ixf_report_20260601_153045.json

11. CVE Load and Show Info

ixf cve CVE-2023-6448 show info
[*] Module loaded: CVE-2023-6448 Unitronics UniStream PLC
 name : CVE-2023-6448 Unitronics UniStream PLC
 cvss : 9.8
 impact : CRITICAL
 mitre : T0812, T0859

12. Assessment Module Run

ixf assess risk/ics_risk_scorer
[*] Loading assessment/risk/ics_risk_scorer...
 ICS Risk Score Methodology
 Network exposure: 30% Internet-facing: CRITICAL
 Authentication: 25% No Modbus auth: HIGH
 ...
 Composite Score: 8.7/10 (CRITICAL)

13. TTP List for a Tactic

ixf ttp-list --tactic evasion
 TTP Index — Evasion (TA0103)
 T0838 Modify Alarm Settings 2 modules
 T0844 Program Organization 1 module
 T0849 Masquerading 1 module
 T0851 Rootkit 2 modules
 T0856 Spoof Reporting 2 modules
 T0858 Change Credential 4 modules
 T0872 Indicator Removal 1 module
 T0874 Hooking 1 module

14. MITRE Navigator Layer Export

ixf mitre-report layer
[+] ATT&CK Navigator layer saved: ixf_mitre_layer_20260601_154200.json
[i] Open at: https://mitre-attack.github.io/attack-navigator/

15. NSE Install

ixf nse install
[*] Installing IXF NSE scripts...
[+] ics-sweep.nse → installed
[+] ics-default-creds.nse → installed
...
[+] All 8 IXF NSE scripts installed.

16. LLM Status Check

ixf llm-status
 LLM Provider Status
 gemini configured gemini-2.5-flash
 openai not configured
 ...
 Active: gemini

17. SAST Analysis One-Liner

ixf sast /opt/plc_projects/water_treatment/ --mode sast
[*] Analyzing water_treatment/ (5 files, 245 lines)...
[*] Provider: gemini | Sanitized: 2 credentials, 1 IP
[*] Sending to LLM...
 SAST REPORT: 1 CRITICAL | 2 HIGH | 1 MEDIUM | 1 LOW
 FINDING [CRITICAL]: Unvalidated Chlorine Dosing Setpoint (line 48)
 ...
[+] Report saved: .tmp/sast_results/water_treatment_20260601.md

18. Multiple Modules with Global Target

ixf setg target 10.0.0.100 use scanners/ics/modbus_detect run use scanners/ics/s7_comm_scanner run
[*] Global: target => 10.0.0.100
[*] Module loaded: Modbus TCP Device Detect
 [SIMULATE] Modbus scan on 10.0.0.100:502...
[*] Module loaded: Siemens S7 Scanner
 [SIMULATE] S7comm scan on 10.0.0.100:102...

19. TTP Check (Read-Only Sweep)

ixf ttp-check T0859 192.168.1.100
[*] T0859 (Valid Accounts) check-only on 192.168.1.100...
 creds/siemens/ssh_default_creds → POTENTIAL (port 22 open)
 creds/siemens/telnet_default_creds → NOT VULNERABLE (port 23 closed)
 ...

20. Full MITRE HTML Report After Sweep

ixf mitre-all 192.168.1.100 report html mitre-report layer
[*] Full MITRE sweep on 192.168.1.100 (simulate)...
[+] MITRE sweep complete: 74 techniques
[+] Report saved: ixf_report_20260601_161200.html
[+] Navigator layer saved: ixf_mitre_layer_20260601_161215.json

Multiple Module Chaining in One Command

Chain as many commands as needed. Each use loads a new module; set, check, and run operate on the currently loaded module:

# Three modules, all in sequence, single invocation
ixf \
 use scanners/ics/modbus_detect \
 set target 192.168.1.100 \
 run \
 use scanners/ics/s7_comm_scanner \
 set target 192.168.1.100 \
 run \
 use cve/siemens/cve_2021_22681_s7_1200_hardcoded_key \
 set target 192.168.1.100 \
 run \
 report json
[*] Indexing 1193 modules...
[*] Module loaded: Modbus TCP Device Detect
[*] target => 192.168.1.100
 [SIMULATE] Modbus scan...
[*] Module loaded: Siemens S7 Scanner
[*] target => 192.168.1.100
 [SIMULATE] S7comm scan...
[*] Module loaded: CVE-2021-22681 Siemens S7-1200/1500 PLC
[*] target => 192.168.1.100
 [SIMULATE] CVE-2021-22681 exploit chain...
[+] Report saved: ixf_report_20260601_154500.json

All TTP and MITRE Command Variations

# Execute a single technique
ixf ttp T0843 192.168.1.100
# Execute with rate limiting (500ms between modules)
ixf ttp T0843 192.168.1.100 --rate-limit 500
# Stop on first confirmed hit
ixf ttp T0843 192.168.1.100 --stop-on-first
# Save output to file
ixf ttp T0843 192.168.1.100 --output /tmp/t0843_results.json
# Read-only check (no exploit)
ixf ttp-check T0843 192.168.1.100
# Force simulate for a technique
ixf ttp-simulate T0843 192.168.1.100
# List all TTPs
ixf ttp-list
# List TTPs by tactic
ixf ttp-list --tactic discovery
ixf ttp-list --tactic impact
ixf ttp-list --tactic "initial-access"
# MITRE scan — tactic sweep
ixf mitre-scan discovery 192.168.1.0/24
ixf mitre-scan initial-access 192.168.1.100
ixf mitre-scan impact 192.168.1.100
ixf mitre-scan collection 192.168.1.100
# MITRE scan — single technique
ixf mitre-scan T0843 192.168.1.100
ixf mitre-scan T0836 192.168.1.100
# MITRE scan — TA-ID
ixf mitre-scan TA0102 192.168.1.0/24
# Full MITRE sweep
ixf mitre-all 192.168.1.100
# Coverage
ixf mitre-coverage
ixf coverage
# Reports
ixf mitre-report layer
ixf mitre-report json
ixf mitre-report html
# Specific technique module list
ixf mitre T0843
ixf mitre T0836
ixf mitre T0819
# Technique list by tactic
ixf mitre-list
ixf mitre-list discovery
ixf mitre-list evasion
ixf mitre-list "impair-process-control"

Shell Piping — 15 Examples with grep, jq, awk

IXF output can be piped to standard shell tools for filtering, parsing, and integration with other tooling.

1. Filter for CRITICAL findings

ixf search siemens | grep CRITICAL
│ use cve/siemens/cve_2021_22681_s7_1200_hardcoded_key CRITICAL CVE-2021-22681 │
│ use cve/siemens/cve_2022_38465_s7_global_key CRITICAL CVE-2022-38465 │
│ use cve/siemens/cve_2023_44317_simatic_pcs_rce CRITICAL CVE-2023-44317 │

2. Count modules for a vendor

ixf vendors siemens | grep -c "CVE\|N/A"
# 27

3. Extract module paths from search results

ixf search modbus | grep "^ use " | awk '{print 2ドル}'
exploits/protocols/modbus/modbus_write_single_register
exploits/protocols/modbus/modbus_flood_dos
exploits/protocols/modbus/modbus_read_coils
...

4. Save JSON report and parse with jq

ixf use scanners/ics/modbus_detect set target 192.168.1.100 run report json
cat ixf_report_*.json | jq '.events[] | select(.result == "VULNERABLE")'
{
 "module": "scanners/ics/modbus_detect",
 "target": "192.168.1.100",
 "result": "VULNERABLE",
 "impact": "READ",
 "timestamp": "2026年06月01日T20:15:43Z"
}

5. Extract CVE IDs from stats

ixf search CVE-2021 | grep "CVE-2021" | awk '{print $NF}'

6. Filter protocols by port

ixf protocols | grep "502"
MODBUS TCP 502/TCP 18 modules
PROFIsafe 502/TCP 1 module

7. Monitor MITRE coverage changes

ixf mitre-coverage | grep "TOTAL"
# TOTAL: 96/103 (93%)

8. Extract all vendor names

ixf vendors | awk '/^ [A-Z]/{print 1,ドル 2ドル}'

9. Parse SAST report for critical findings

ixf sast /opt/plc.st 2>&1 | grep "SEVERITY: CRITICAL"
# FINDING [SEVERITY: CRITICAL]: Unvalidated Chlorine Dosing Setpoint

10. Save MITRE layer and check size

ixf mitre-report layer
ls -la ixf_mitre_layer_*.json
wc -l ixf_mitre_layer_*.json

11. JSON report findings count with jq

ixf use scanners/ics/modbus_detect set target 192.168.1.0/24 run report json
jq '.events | length' ixf_report_*.json
# 14

12. Filter TTP list by module count

ixf ttp-list | awk '3ドル >= 5 {print 0ドル}'
# Shows techniques with 5+ modules

13. Combine multiple subnet scans

for subnet in 192.168.1.0/24 10.0.0.0/24 172.16.0.0/24; do
 echo "=== Scanning $subnet ===" 
 ixf use scanners/ics/modbus_detect set target $subnet check 2>&1
done | grep -E "VULNERABLE|NOT VULNERABLE"

14. Extract module paths from ttp output

ixf ttp T0843 192.168.1.100 2>&1 | grep "Running module" | sed 's/.*: //'
cve/siemens/cve_2021_22681_s7_1200_hardcoded_key
cve/siemens/cve_2022_38465_s7_global_key
cve/rockwell/cve_2022_1161_controllogix_modified_fw
exploits/protocols/s7comm/s7_unauthorized_cpu_control
assessment/mitre_ics/t0843_program_upload

15. Automated vendor check with filtered output

ixf vendors | grep -E "(Siemens|Rockwell|Schneider|Honeywell)" | awk '{print 1,ドル 2,ドル $NF}'

Bash Assessment Script (Complete, 100+ Lines)

A complete ICS security assessment script using IXF in non-interactive mode:

#!/usr/bin/env bash
# ixf_assessment.sh — Automated ICS Security Assessment
# Usage: ./ixf_assessment.sh <target_ip> [output_dir]
# Requires: ixf installed (pip install industrialxpl-forge)
# Author: Andre Henrique (@mrhenrike) | União Geek
set -euo pipefail
TARGET="${1:?Usage: 0ドル <target_ip> [output_dir]}"
OUTPUT_DIR="${2:-.tmp/assessment_$(date +%Y%m%d_%H%M%S)}"
LOGFILE="$OUTPUT_DIR/assessment.log"
# Setup
mkdir -p "$OUTPUT_DIR"
echo "=== IXF ICS Security Assessment ===" | tee "$LOGFILE"
echo "Target: $TARGET" | tee -a "$LOGFILE"
echo "Started: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
# Check IXF is available
if ! command -v ixf &>/dev/null; then
 echo "ERROR: ixf not found. Install: pip install industrialxpl-forge" >&2
 exit 1
fi
echo "[Phase 1] Module Index" | tee -a "$LOGFILE"
ixf stats 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 2] Protocol Discovery (Modbus)" | tee -a "$LOGFILE"
ixf use scanners/ics/modbus_detect \
 set target "$TARGET" \
 check 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 3] Protocol Discovery (S7comm)" | tee -a "$LOGFILE"
ixf use scanners/ics/s7_comm_scanner \
 set target "$TARGET" \
 check 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 4] MITRE Discovery Sweep (Simulate)" | tee -a "$LOGFILE"
ixf mitre-scan discovery "$TARGET" 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 5] TTP T0846 — Remote System Discovery" | tee -a "$LOGFILE"
ixf ttp T0846 "$TARGET" 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 6] TTP T0812 — Default Credentials Check" | tee -a "$LOGFILE"
ixf ttp-check T0812 "$TARGET" 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 7] TTP T0819 — Exploit Public-Facing Application (Simulate)" | tee -a "$LOGFILE"
ixf ttp T0819 "$TARGET" 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 8] IEC 62443 Zone/Conduit Assessment" | tee -a "$LOGFILE"
ixf assess iec62443/zone_conduit_audit 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 9] NIST SP 800-82r3 Checklist" | tee -a "$LOGFILE"
ixf assess nist_sp800_82/control_checklist 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 10] MITRE Coverage" | tee -a "$LOGFILE"
ixf mitre-coverage 2>&1 | tee -a "$LOGFILE"
echo "" | tee -a "$LOGFILE"
echo "[Phase 11] Generate Reports" | tee -a "$LOGFILE"
ixf report json 2>&1 | tee -a "$LOGFILE"
ixf report html 2>&1 | tee -a "$LOGFILE"
ixf mitre-report layer 2>&1 | tee -a "$LOGFILE"
# Move generated reports to output dir
mv ixf_report_*.json "$OUTPUT_DIR/" 2>/dev/null || true
mv ixf_report_*.html "$OUTPUT_DIR/" 2>/dev/null || true
mv ixf_mitre_*.json "$OUTPUT_DIR/" 2>/dev/null || true
echo "" | tee -a "$LOGFILE"
echo "=== Assessment Complete ===" | tee -a "$LOGFILE"
echo "Finished: $(date -u +%Y-%m-%dT%H:%M:%SZ)" | tee -a "$LOGFILE"
echo "Output directory: $OUTPUT_DIR" | tee -a "$LOGFILE"
echo "Files:" | tee -a "$LOGFILE"
ls -la "$OUTPUT_DIR/" | tee -a "$LOGFILE"
# Summary: count findings
VULNERABLE_COUNT=$(grep -c "VULNERABLE\|POTENTIAL\|CRITICAL\|HIGH" "$LOGFILE" || true)
echo "" | tee -a "$LOGFILE"
echo "Findings requiring attention: $VULNERABLE_COUNT" | tee -a "$LOGFILE"

Usage:

chmod +x ixf_assessment.sh
./ixf_assessment.sh 192.168.1.100
./ixf_assessment.sh 192.168.1.100 /reports/q2-2026/

Python API — 15 Code Examples

1. Run a module programmatically

import subprocess
import sys
def run_ixf(*args: str) -> str:
 """Run IXF with given arguments and return output."""
 result = subprocess.run(
 ["ixf"] + list(args),
 capture_output=True,
 text=True,
 timeout=120,
 )
 return result.stdout + result.stderr
# Simulate a module
output = run_ixf(
 "use", "scanners/ics/modbus_detect",
 "set", "target", "192.168.1.100",
 "run",
)
print(output)

2. Parse MITRE coverage

import re
output = run_ixf("mitre-coverage")
total_match = re.search(r"TOTAL\s+(\d+)/(\d+)\s+\((\d+)%\)", output)
if total_match:
 covered, total, pct = total_match.groups()
 print(f"MITRE coverage: {covered}/{total} ({pct}%)")

3. Search modules by keyword

def search_modules(keyword: str) -> list[str]:
 output = run_ixf("search", keyword)
 paths = []
 for line in output.splitlines():
 if "use " in line:
 match = re.search(r"use\s+(\S+)", line)
 if match:
 paths.append(match.group(1))
 return paths
siemens_modules = search_modules("siemens")
print(f"Found {len(siemens_modules)} Siemens modules")

4. Run TTP sweep and parse results

def run_ttp(tid: str, target: str) -> dict:
 output = run_ixf("ttp", tid, target)
 return {
 "technique": tid,
 "target": target,
 "output": output,
 "simulated": "[SIMULATE" in output,
 "modules_run": output.count("Running module"),
 }
result = run_ttp("T0843", "192.168.1.100")
print(f"Ran {result['modules_run']} modules for {result['technique']}")

5. Generate report and read JSON

import json
import glob
# Run assessment
run_ixf(
 "use", "scanners/ics/modbus_detect",
 "set", "target", "192.168.1.0/24",
 "run",
 "report", "json",
)
# Parse most recent report
reports = sorted(glob.glob("ixf_report_*.json"))
if reports:
 with open(reports[-1]) as f:
 report = json.load(f)
 print(f"Session events: {len(report.get('events', []))}")

6. Multi-target scan

targets = ["192.168.1.100", "192.168.1.101", "10.0.0.50"]
for target in targets:
 output = run_ixf(
 "use", "scanners/ics/modbus_detect",
 "set", "target", target,
 "check",
 )
 status = "VULNERABLE" if "VULNERABLE" in output else "NOT VULNERABLE"
 print(f"{target}: {status}")

7. SAST analysis with LLM

import os
# Configure API key via environment (never hardcode)
env = os.environ.copy()
env["GOOGLE_AI_STUDIO_API_KEY"] = os.environ["GEMINI_KEY"]
result = subprocess.run(
 ["ixf", "sast", "/opt/plc_projects/", "--mode", "sast"],
 capture_output=True, text=True, env=env, timeout=300,
)
print(result.stdout)

8. Automated daily scan with scheduling

import schedule
import time
def daily_scan():
 """Run daily ICS reconnaissance scan."""
 output = run_ixf("mitre-scan", "discovery", "192.168.1.0/24")
 # Parse and alert on new findings
 if "VULNERABLE" in output or "POTENTIAL" in output:
 alert_security_team(output)
 # Generate report
 run_ixf("report", "json")
schedule.every().day.at("02:00").do(daily_scan)
while True:
 schedule.run_pending()
 time.sleep(60)

9. Load module and get options as dict

def get_module_options(module_path: str) -> dict:
 output = run_ixf("use", module_path, "show", "options")
 options = {}
 for line in output.splitlines():
 # Parse table rows: | option | value | required | description |
 parts = [p.strip() for p in line.split("|") if p.strip()]
 if len(parts) >= 3 and parts[0] not in ("Option", "-"):
 options[parts[0]] = {
 "value": parts[1],
 "required": parts[2].lower() == "yes",
 }
 return options
opts = get_module_options("scanners/ics/modbus_detect")
print(opts)
# {"target": {"value": "", "required": True}, "port": {"value": "502", ...}}

10. Vendor enumeration

def get_vendor_list() -> list[str]:
 output = run_ixf("vendors")
 vendors = []
 for line in output.splitlines():
 # Lines starting with vendor names
 match = re.match(r"\s{2}(\w[\w\s\/]+?)\s{2,}", line)
 if match:
 vendors.append(match.group(1).strip())
 return vendors
vendors = get_vendor_list()
print(f"Total vendors: {len(vendors)}")

11. Check if target has Modbus and return bool

def has_modbus(target: str) -> bool:
 output = run_ixf(
 "use", "scanners/ics/modbus_detect",
 "set", "target", target,
 "check",
 )
 return "[+] VULNERABLE" in output or "Modbus device detected" in output
if has_modbus("192.168.1.100"):
 print("Target has Modbus — checking for CVEs...")
 print(run_ixf("search", "modbus"))

12. TTP coverage report as dict

def get_ttp_coverage() -> dict:
 output = run_ixf("mitre-coverage")
 tactics = {}
 pattern = re.compile(r"(\w[\w\s]+\(TA\d+\))\s+:\s+(\d+)/(\d+)\s+\((\d+)%\)")
 for match in pattern.finditer(output):
 name, covered, total, pct = match.groups()
 tactics[name] = {"covered": int(covered), "total": int(total), "pct": int(pct)}
 return tactics
coverage = get_ttp_coverage()
for tactic, data in coverage.items():
 if data["pct"] < 80:
 print(f"LOW COVERAGE: {tactic} ({data['pct']}%)")

13. Batch CVE check

cve_list = [
 "CVE-2021-22681",
 "CVE-2022-38465",
 "CVE-2023-6448",
 "CVE-2022-29965",
]
for cve in cve_list:
 output = run_ixf("search", cve)
 found = cve in output
 print(f"{cve}: {'COVERED' if found else 'NOT COVERED'}")

14. Assessment module execution

assessments = [
 "iec62443/zone_conduit_audit",
 "nist_sp800_82/control_checklist",
 "risk/ics_risk_scorer",
 "threat_intel/ics_kill_chain",
]
for assess_module in assessments:
 print(f"\n=== {assess_module} ===")
 output = run_ixf("assess", assess_module)
 print(output)

15. Full assessment pipeline with output

from pathlib import Path
from datetime import datetime
def full_assessment(target: str, output_dir: str = ".tmp/assessment") -> Path:
 """Run full ICS assessment and save results."""
 out = Path(output_dir)
 out.mkdir(parents=True, exist_ok=True)
 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
 phases = [
 # (phase_name, ixf_args)
 ("discovery_modbus", ["use", "scanners/ics/modbus_detect", "set", "target", target, "check"]),
 ("discovery_s7", ["use", "scanners/ics/s7_comm_scanner", "set", "target", target, "check"]),
 ("mitre_discovery", ["mitre-scan", "discovery", target]),
 ("ttp_t0846", ["ttp", "T0846", target]),
 ("ttp_t0812", ["ttp-check", "T0812", target]),
 ("assess_iec62443", ["assess", "iec62443/zone_conduit_audit"]),
 ("assess_nist", ["assess", "nist_sp800_82/control_checklist"]),
 ("coverage", ["mitre-coverage"]),
 ]
 all_output = []
 for phase_name, args in phases:
 print(f"[*] Running: {phase_name}")
 out_text = run_ixf(*args)
 all_output.append(f"=== {phase_name} ===\n{out_text}\n")
 # Write full log
 log_path = out / f"assessment_{target.replace('.', '_')}_{timestamp}.log"
 log_path.write_text("\n".join(all_output))
 # Generate reports
 run_ixf("report", "json")
 run_ixf("mitre-report", "layer")
 print(f"[+] Assessment complete. Output: {log_path}")
 return log_path
full_assessment("192.168.1.100", "/reports/assessment_q2/")

GitHub Actions Workflow (Complete)

# .github/workflows/ics_security_scan.yml
name: ICS Security Assessment
on:
 schedule:
 - cron: "0 2 * * 1" # Every Monday at 02:00 UTC
 workflow_dispatch:
 inputs:
 target:
 description: "Target IP or CIDR"
 required: true
 default: "192.168.1.100"
jobs:
 ics-scan:
 name: ICS Security Scan
 runs-on: ubuntu-latest
 timeout-minutes: 30
 steps:
 - name: Checkout
 uses: actions/checkout@v4
 - name: Set up Python
 uses: actions/setup-python@v5
 with:
 python-version: "3.13"
 - name: Install IXF
 run: pip install industrialxpl-forge
 - name: Verify IXF Installation
 run: |
 ixf stats
 ixf mitre-coverage

 - name: Run MITRE Coverage Check
 run: |
 ixf mitre-coverage > coverage_report.txt
 cat coverage_report.txt

 - name: Run Discovery Sweep (Simulate)
 env:
 TARGET: ${{ github.event.inputs.target || '192.168.1.100' }}
 run: |
 ixf use scanners/ics/modbus_detect set target "$TARGET" run > modbus_scan.txt || true
 ixf mitre-scan discovery "$TARGET" > discovery_scan.txt || true

 - name: Run Assessment Modules
 run: |
 ixf assess iec62443/zone_conduit_audit > iec62443_report.txt
 ixf assess nist_sp800_82/control_checklist > nist_report.txt
 ixf assess risk/ics_risk_scorer > risk_report.txt

 - name: Generate Reports
 env:
 TARGET: ${{ github.event.inputs.target || '192.168.1.100' }}
 run: |
 ixf use scanners/ics/modbus_detect set target "$TARGET" run report json
 ixf mitre-report layer
 ixf mitre-report html

 - name: Upload Assessment Artifacts
 uses: actions/upload-artifact@v4
 with:
 name: ics-assessment-${{ github.run_number }}
 path: |
 ixf_report_*.json
 ixf_report_*.html
 ixf_mitre_*.json
 coverage_report.txt
 *_report.txt
 retention-days: 30
 - name: Check for Critical Findings
 run: |
 if grep -q "CRITICAL\|CATASTROPHIC" modbus_scan.txt discovery_scan.txt 2>/dev/null; then
 echo "::warning::Critical findings detected in ICS scan"
 fi
 echo "ICS assessment complete."

Jenkins Pipeline (Complete)

// Jenkinsfile — ICS Security Assessment Pipeline
pipeline {
 agent {
 docker {
 image 'python:3.13-slim'
 args '-u root'
 }
 }
 parameters {
 string(name: 'TARGET', defaultValue: '192.168.1.100', description: 'Target IP or CIDR')
 choice(name: 'SCAN_DEPTH', choices: ['simulate', 'check', 'full'], description: 'Scan depth')
 }
 environment {
 GOOGLE_AI_STUDIO_API_KEY = credentials('gemini-api-key')
 }
 stages {
 stage('Install IXF') {
 steps {
 sh 'pip install industrialxpl-forge'
 sh 'ixf stats'
 }
 }
 stage('Protocol Discovery') {
 steps {
 sh """
 ixf use scanners/ics/modbus_detect \
 set target ${params.TARGET} \
 check > modbus_check.txt || true
 cat modbus_check.txt
 """
 }
 }
 stage('MITRE Sweep') {
 steps {
 sh "ixf mitre-scan discovery ${params.TARGET} > mitre_discovery.txt"
 sh "ixf mitre-coverage"
 }
 }
 stage('TTP Analysis') {
 parallel {
 stage('T0843 - Program Download') {
 steps { sh "ixf ttp T0843 ${params.TARGET}" }
 }
 stage('T0812 - Default Credentials') {
 steps { sh "ixf ttp-check T0812 ${params.TARGET}" }
 }
 stage('T0846 - Remote Discovery') {
 steps { sh "ixf ttp T0846 ${params.TARGET}" }
 }
 }
 }
 stage('Compliance Assessment') {
 steps {
 sh 'ixf assess iec62443/zone_conduit_audit'
 sh 'ixf assess nist_sp800_82/control_checklist'
 sh 'ixf assess risk/ics_risk_scorer'
 }
 }
 stage('Generate Reports') {
 steps {
 sh 'ixf report json'
 sh 'ixf report html'
 sh 'ixf mitre-report layer'
 }
 }
 }
 post {
 always {
 archiveArtifacts artifacts: 'ixf_report_*.json, ixf_report_*.html, ixf_mitre_*.json, *.txt'
 }
 failure {
 echo 'ICS assessment pipeline failed'
 }
 success {
 echo 'ICS assessment complete'
 }
 }
}

GitLab CI (Complete)

# .gitlab-ci.yml — ICS Security Assessment
stages:
 - setup
 - scan
 - assess
 - report
variables:
 TARGET: "192.168.1.100"
 PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
cache:
 key: ixf-pip
 paths:
 - .cache/pip
install-ixf:
 stage: setup
 image: python:3.13-slim
 script:
 - pip install industrialxpl-forge
 - ixf stats
 - ixf mitre-coverage
 artifacts:
 paths:
 - coverage_output.txt
protocol-scan:
 stage: scan
 image: python:3.13-slim
 script:
 - pip install industrialxpl-forge
 - ixf use scanners/ics/modbus_detect set target $TARGET check || true
 - ixf use scanners/ics/s7_comm_scanner set target $TARGET check || true
 - ixf mitre-scan discovery $TARGET > discovery_report.txt
 artifacts:
 paths:
 - discovery_report.txt
 expire_in: 1 week
ttp-analysis:
 stage: scan
 image: python:3.13-slim
 parallel:
 matrix:
 - TTP_ID: T0843
 - TTP_ID: T0812
 - TTP_ID: T0846
 - TTP_ID: T0819
 script:
 - pip install industrialxpl-forge
 - ixf ttp $TTP_ID $TARGET > ttp_${TTP_ID}_results.txt
 artifacts:
 paths:
 - ttp_*.txt
compliance-assess:
 stage: assess
 image: python:3.13-slim
 script:
 - pip install industrialxpl-forge
 - ixf assess iec62443/zone_conduit_audit > iec62443.txt
 - ixf assess nist_sp800_82/control_checklist > nist_report.txt
 - ixf assess risk/ics_risk_scorer > risk_score.txt
 artifacts:
 paths:
 - iec62443.txt
 - nist_report.txt
 - risk_score.txt
generate-reports:
 stage: report
 image: python:3.13-slim
 script:
 - pip install industrialxpl-forge
 - ixf report json
 - ixf report html
 - ixf mitre-report layer
 - ixf mitre-report html
 artifacts:
 paths:
 - ixf_report_*.json
 - ixf_report_*.html
 - ixf_mitre_*.json
 expire_in: 4 weeks

Docker Usage

# Run IXF in Docker
docker run --rm python:3.13-slim bash -c \
 "pip install industrialxpl-forge -q && ixf stats"
# With target network access
docker run --rm --network host python:3.13-slim bash -c \
 "pip install industrialxpl-forge -q && \
 ixf use scanners/ics/modbus_detect set target 192.168.1.100 run"
# Dockerfile for custom IXF image
cat > Dockerfile << 'EOF'
FROM python:3.13-slim
RUN pip install industrialxpl-forge
WORKDIR /assessment
ENTRYPOINT ["ixf"]
EOF
docker build -t ixf:latest .
# Run assessment
docker run --rm -v $(pwd)/reports:/assessment ixf:latest \
 use scanners/ics/modbus_detect \
 set target 192.168.1.100 \
 run \
 report json
# Interactive shell
docker run -it --rm ixf:latest

Exit Codes

Exit Code Meaning When
0 Success All commands executed without error
1 General error Unhandled exception, invalid command
2 Module not found use or cve command with unknown module
3 Validation error Required option not set, invalid value
4 Connection error check/run failed due to network unreachable
5 LLM error SAST command with no configured provider
6 Permission error NSE install without sudo/admin
10 Aborted DestructiveGate confirmation rejected

Check exit code in bash:

ixf use scanners/ics/modbus_detect set target 192.168.1.100 check
EXIT_CODE=$?
case $EXIT_CODE in
 0) echo "Success" ;;
 2) echo "Module not found" ;;
 4) echo "Connection failed — target unreachable" ;;
 *) echo "Error: $EXIT_CODE" ;;
esac

JSON Output Parsing Examples

import json
import glob
# Find latest JSON report
reports = sorted(glob.glob("ixf_report_*.json"))
if not reports:
 print("No reports found. Run: ixf report json")
 exit(1)
with open(reports[-1]) as f:
 report = json.load(f)
# Top-level structure
print(f"Session ID: {report.get('session_id')}")
print(f"Started: {report.get('started_at')}")
print(f"Target: {report.get('target')}")
print(f"Events: {len(report.get('events', []))}")
# Filter events by type
vulnerable = [e for e in report.get("events", []) if e.get("result") == "VULNERABLE"]
simulated = [e for e in report.get("events", []) if e.get("simulated", True)]
print(f"Vulnerable: {len(vulnerable)}")
print(f"Simulated: {len(simulated)}")
# Most severe findings
for event in sorted(report.get("events", []), key=lambda e: e.get("cvss", 0), reverse=True)[:5]:
 print(f"{event.get('module')} — CVSS: {event.get('cvss', 'N/A')}{event.get('result')}")

Previous: Module Development | Next: PolyExploit Runner

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /