firewall-auditor — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited firewall-auditor (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You audit the firewall configuration on a UniFi network. Your job is to dispatch the right MCP tool calls, evaluate the results against a documented rubric, score the audit deterministically, and present prioritised findings.
The work is split between you and one tiny CLI:
unifi-network MCP tools, evaluate each benchmark, and write findings.There is no Python script doing the audit for you. There is no HTTP sidecar. You drive the audit; the CLI does the math.
This skill requires the unifi-network MCP server. If unifi_tool_index is unavailable, stop and direct the user to the unifi-network-setup skill.
Dispatch these tool calls in a single batch (multiple tool uses in one assistant turn — they are independent and you should not serialise them):
unifi_list_firewall_policiesunifi_list_firewall_zonesunifi_list_networksunifi_list_firewall_groupsunifi_list_devicesunifi_get_dpi_stats (optional but useful for HYG-05 / EGR-03 context)If a tool returns success=false, stop the audit and surface the error. Do not partial-report.
For richer per-policy detail (needed by HYG-02 conflict detection and HYG-05 shadowing), follow up with unifi_get_firewall_policy_details for each policy returned by unifi_list_firewall_policies. Batch these calls in parallel as well.
Walk through each benchmark in references/security-benchmarks.md in order: SEG-01 → SEG-04, EGR-01 → EGR-03, HYG-01 → HYG-05, TOP-01 → TOP-04. For each benchmark, the reference document specifies:
critical, warning, or info)fix template you can include in the findingA benchmark may produce zero, one, or many findings — one per offending instance. For example, TOP-02 (firmware updates) produces one finding per device with upgradeable=true, not one finding total. Per-instance counting is what makes the score reflect real exposure (rubric §"Why per-instance deductions").
For each instance, build a finding object:
{
"benchmark_id": "SEG-01",
"severity": "critical",
"message": "No rule blocks IoT VLAN traffic to private networks.",
"fix": {
"tool": "unifi_create_firewall_policy",
"params": { "name": "Block IoT to Internal", "action": "REJECT", ... }
}
}The fix block is optional but include it whenever the benchmark reference shows a remediation template.
Pipe the findings through the scoring CLI. This is the only part of the audit where math happens — keep it that way so trend tracking stays comparable.
# Resolve scripts/unifi-firewall-score relative to this skill directory.
echo '{"findings": [...]}' | "<firewall-auditor-skill-dir>/scripts/unifi-firewall-score"The CLI returns:
{
"rubric_version": 1,
"overall_score": 73,
"overall_status": "needs_attention",
"categories": {
"segmentation": {"score": 14, "max": 25, "deduction": 11, "count": 4},
"egress_control": {"score": 23, "max": 25, "deduction": 2, "count": 1},
"rule_hygiene": {"score": 15, "max": 25, "deduction": 10, "count": 5},
"topology": {"score": 21, "max": 25, "deduction": 4, "count": 2}
}
}Do not compute the score yourself. The CLI is stable across versions; your arithmetic is not.
Maintain a single audit history file at ${UNIFI_SKILLS_STATE_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/unifi-mcp/skills}/audit-history.json. The file is a JSON array of {timestamp, overall_score, overall_status, rubric_version} entries.
STATE_DIR="${UNIFI_SKILLS_STATE_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/unifi-mcp/skills}"
mkdir -p "$STATE_DIR"
HIST="$STATE_DIR/audit-history.json"
[ -f "$HIST" ] || echo "[]" > "$HIST"
# Compose the new entry from the score CLI output ($SCORE_JSON) and append.
ENTRY=$(echo "$SCORE_JSON" | python3 -c "
import json, sys, datetime
s = json.load(sys.stdin)
print(json.dumps({
'timestamp': datetime.datetime.now(datetime.timezone.utc).isoformat(),
'overall_score': s['overall_score'],
'overall_status': s['overall_status'],
'rubric_version': s['rubric_version'],
}))
")
python3 -c "
import json, sys
hist = json.load(open('$HIST'))
hist.append(json.loads('''$ENTRY'''))
json.dump(hist[-50:], open('$HIST', 'w'), indent=2)
"Keep the last 50 entries (enough for ~a year of weekly audits).
Compare against the previous entry in the history file. Report:
previous_score — the prior entry's score, or null if this is the first auditchange — signed integer delta (e.g., +5, -3)If rubric_version differs from the prior entry, do not compute a trend — the scoring model changed and historical scores are not comparable. Tell the user the rubric was updated and a fresh trend baseline starts now.
Format depends on user intent:
Default (interactive): human-readable summary
fix tool nameOn request ("give me JSON" / "machine-readable"): emit the full report as JSON with this shape:
{
"timestamp": "...",
"overall_score": 73,
"overall_status": "needs_attention",
"categories": { ... from CLI ... },
"findings": [ ... all per-instance findings ... ],
"trend": { "previous_score": 68, "change": "+5" }
}references/scoring-rubric.md)| Score | Rating | Meaning |
|---|---|---|
| 80–100 | Healthy | Follows best practices with minor gaps |
| 60–79 | Needs Attention | Notable gaps; address on a planned schedule |
| 0–59 | Critical | Significant exposure requiring immediate remediation |
For each finding, do not call mutating tools yourself. The auditor reads; the firewall-manager skill writes. For each remediation:
fix.tool and fix.params from the report.Priority order: critical findings (SEG-01 / SEG-02 / SEG-03 / HYG-02 / TOP-01) first, then warnings, then info. Use this same order when summarising the report — never bury a critical finding under a long info list.
references/security-benchmarks.md is authoritative; do not invent new checks. If you encounter a real-world issue not covered by the 16 benchmarks, report it as a freeform observation outside the scored categories — do not invent a new benchmark_id.unifi-firewall-score.rubric_version mismatch with the prior history entry means the math changed; report the new baseline and explain why no trend is shown.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.