OWASP Faction is a free opensource tool that you can use to automate pentest reporting and other workflows. We are going to dig into how you using agentic tools like OpenCode to create a tight integration with your CLI penetrating tools and your reporting.
The Faction MCP server exposes your assessments, vulnerabilities, retests, and audit logs directly to any MCP-compatible AI client. No more copy-pasting. No more lost context. Just seamless, automated workflows that let AI handle the heavy lifting while you focus on strategy.
- Integrate any CLI tool into Faction
- Use any AI provider to create create/edit vulnerabilities descriptions and recommendations
- Generate executive summaries that include full detail of all vulnerabilities and observations to summarize and prioritize the risk assessment.
- Integrate Local LLMs into Faction so you are not sharing with 3rd party providers
- Fully Supports OpenCode, ClaudeCode, copilot-cli, LM Studio, and may others.
Step 1: Install in Under 5 Minutes
Getting started is straightforward. All you need is Docker and a Faction API key.
- Clone the MCP server locally and copy the .env template
git clone git@github.com:factionsecurity/faction-mcp.git
cd faction-mcp
cp .env.example .env
- Edit the .env file and add your Faction Hostname and API key.
Click profile and the top right, Your API Key will be disaplayed at the bottom of the profile page.
FACTION_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
FACTION_BASE_URL=https://faction.yourcompany.com
- Done!
Configure and Agent
I’m going to use OpenCode as its currently my favorite.
- Edit the OpenCode Config:
{
"mcp": {
"faction": {
"type" : "local",
"command": [
"docker",
"compose",
"-f", "[YOUR PATH TO FACTION MCP]/faction-mcp/docker-compose.yml",
"run", "--rm", "-T", "faction-mcp"
],
"enabled": true
}
}
- Start OpenCode and type /mcps and you should see faction connected!

Create a nmap Skill.md file
In this example we are going to create skill.md file to instruct the LLM how we want to execute NMAP in our pentests. Skills are how we tame the non-deterministic tendencies of LLMs. This will allow us to automate multistep workflows in a process that is repeatable, accurate, and gives consistant results. If you are new to skills and agent files then check out these links as this feature is really powerful.
- https://agents.md/
- https://openai.com/academy/skills/
For my nmap skill I want to follow this proccess:
- Do a quick scan nmap -Pn — top-ports 100
- Take the open ports and do a vuln scan like nmap -sV — script=vuln -p3. Create a report with Description, Recommendation, and Details showing the command run and evidence of the findings.
I want this to report the same way every time and it can be tedius to create this type of report on every assessment if your doing 100s of assessments a year. But the Skill.md will handle all of this for use and automate the reporting into Faction.
First create the folder to hold the skill .opencode/skills/faction-nmap-scan/
Second Add this file named SKILL.md to this folder path.
---
name: faction-nmap-scan
description: Run nmap vulnerability scans on target IPs and create information findings in Faction with results
license: MIT
---
## What I do
Runs nmap scans against target IP addresses or hostnames to discover open ports and known vulnerabilities, then creates an information-level finding in Faction with the scan results documented in tables.
## When to use me
Use this when the user asks to:
- Run an nmap scan on a target
- Scan an IP address or hostname for open ports and vulnerabilities
- Create an nmap scan finding in Faction
- Discover open ports and weaknesses on a target system
## Prerequisites
Before starting, ask the user for:
1. The **target IP address or hostname** to scan
2. The **assessment ID** in Faction (if they don't know it, have them run `faction_get_assessment_queue` to find it)
3. **Authorization confirmation** — explicitly confirm the user is authorized to scan the target (i.e., it is in scope for the engagement, or it is their own infrastructure). If the target is a third-party system, public IP not owned by the user, or otherwise out of scope, **STOP and refuse**. Unauthorized scanning is illegal in many jurisdictions.
## Steps
1. **Quick port scan**
First, run a fast scan to discover which ports are open:
```bash
nmap -Pn --top-ports 100
This scans the 100 most common ports without host discovery (skips ping). -Pn treats all hosts as online, which is useful when targets filter ICMP.
Timeout: Run with a timeout of at least 180000 ms (3 minutes). If the Bash tool’s default 2-minute timeout would kill the scan, set the timeout explicitly.
If the command requires elevated privileges (raw socket operations), use sudo:
sudo nmap -Pn --top-ports 100
If no ports are open, inform the user and skip to step 3 — create the finding noting the target is not reachable or has no open ports.
-
Vulnerability scan on open ports only From step 1’s output, extract the open port numbers. Then run a targeted vulnerability scan against only those ports:
nmap -sV --script=vuln -pReplace “ with the actual open ports found (e.g.,
-p 22,80,443). If elevated privileges are required, prefix withsudo.This focuses the vuln scan on only the discovered open ports, significantly reducing scan time.
Timeout: Vuln scans can take 5–15+ minutes depending on the number of ports and target responsiveness. Set the Bash timeout to 600000 ms (10 minutes) minimum, or run with
run_in_background: trueand poll with the Monitor tool for very large port sets. Do NOT use the default 2-minute timeout — it will silently kill the scan mid-run.If you must split work, run one port (or a small batch) per nmap invocation rather than truncating the script set.
-
Parse the results From the nmap output, extract:
- All commands that were run (record the exact strings used, including
sudoprefix if applicable) - Open ports and their corresponding services
- Service versions detected
- Vulnerabilities identified by the vuln scripts (look for
VULNERABLE:markers and CVE references) - Any weaknesses or misconfigurations discovered
If the output is very large (>500 lines), summarize per-port rather than pasting raw output into the finding.
- All commands that were run (record the exact strings used, including
-
Create the Faction vulnerability Call
faction_create_vulnerabilitywith the following parameters:- assessment_id: the assessment ID provided by the user
- name:
Nmap Scan Results -(e.g.,Nmap Scan Results - 192.168.1.100) - severity:
Recommended(numeric ID1) - impact:
Recommended(numeric ID1) - likelihood:
Recommended(numeric ID1) - description: Write a clear description that includes details about the vulnerabilities found on the open ports. Include the service names, versions, and specific vulnerabilities identified. If no vulnerabilities were found, state that the scan was completed but no known vulnerabilities were detected.
Example description format:
An nmap scan was performed against to identify open ports, running services, and known vulnerabilities. The scan revealed the following findings:- recommendation: Write recommendations that match the specific issues found. Examples:
- If outdated services are found: recommend upgrading to the latest stable version
- If unnecessary ports are open: recommend closing them or restricting access via firewall rules
- If known vulnerabilities are present: reference vendor patches or mitigations
- If weak protocols are detected: recommend disabling insecure protocols and implementing stronger alternatives
Example recommendation format:
Based on the scan results, the following actions are recommended: - Upgrade from version to the latest stable version to address known vulnerabilities. - Implement firewall rules to restrict access to port and close any unnecessary open ports. - Disable weak cryptographic protocols and enforce strong encryption standards. - Conduct a thorough review of exposed services to ensure they are required and properly secured.-
details: Create a markdown document with two tables:
Table 1 - Commands Run:
Command Description nmap -Pn --top-ports 100Fast port discovery scan (100 most common ports, no ping) nmap -sV --script=vuln -pService version detection and vulnerability scanning on open ports only Table 2 - Open Ports and Weaknesses:
Port Protocol Service Version Vulnerability / Weakness 22 TCP SSH OpenSSH 7.4 80 TCP HTTP Apache 2.4.29 If no vulnerabilities were found, note “No known vulnerabilities detected” in the Vulnerability/Weakness column.
-
Save the vulnerability The
faction_create_vulnerabilitytool will handle saving the vulnerability to the assessment. After it succeeds, report the new Vid back to the user.
Notes
- Severity scoring rule: If
Overall(numerical ID) andOverallStr(text label) conflict, always trustOverall. ID 5 = Critical, ID 4 = High, ID 3 = Medium, ID 2 = Low, ID 1 = Recommended/Info. This is a known data inconsistency in the API — theOverallID is the source of truth. - Severity mapping: Nmap scan findings are always created at the lowest severity tier. Use
Recommended(ID 1) — this is the canonical lowest-tier label used across all faction skills. Do not use “Information” or “Informational” as the API may not accept those aliases consistently. - Always run nmap commands one at a time and capture the full output before proceeding
- Always set an explicit Bash timeout — quick scan ≥180000 ms, vuln scan ≥600000 ms — or use
run_in_background: truefor long scans - If the scan takes a long time, inform the user of progress
- Use the
-sVflag for service version detection and--script=vulnfor vulnerability scripting - If nmap is not installed on the system, inform the user and suggest installing it (e.g.,
brew install nmapon macOS) - If scan results are empty or inconclusive, still create the finding but note that no vulnerabilities were detected
- If multiple targets need to be scanned, ask the user if they want separate findings for each target or combined into one
- Authorization: Never scan a target without explicit user authorization confirming the target is in scope. If the user provides a target that looks like a third-party domain or unfamiliar public IP, ask before proceeding.
## Running our NMAP SKILL.md
In opencode just type: “Do an nmap scan of test.server.com and put the resutls in my current assessment”. The LLM will execute all the steps in the skill and generate an output:

But whats really cool is it created the issue in Faction automatically:\\

Now I just click Generate Report in Faction to get the Docx with all details populated:

[https://www.youtube.com/watch?v=gxTGbphXBNs](https://www.youtube.com/watch?v=gxTGbphXBNs) Originally published on Medium .