Install
$ agentstack add skill-fastrevmd-lab-fwskillsshare-parsing-fortinet-configs ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Parsing Fortinet FortiGate Configurations
Overview
Use this skill to parse Fortinet FortiGate / FortiOS backup or show full-configuration output into the shared vendor-neutral firewall intermediate schema. It focuses on nested config / edit / set / next / end blocks, including VDOMs, interfaces, zones, firewall addresses and services, policies, central SNAT, VIPs, routes, VPN, HA, profiles, and system settings.
FortiOS behavior is version- and feature-dependent. Preserve unknown blocks in residual_raw, capture VDOM context, and flag policy/NAT/profile constructs that cannot be mapped cleanly to the intermediate schema.
Scope and routing
Use only for FortiGate or FortiOS block syntax. Hand off ASA/FTD access-list, nameif, or object network input to parsing-cisco-configs, PAN-OS XML or set deviceconfig to parsing-palo-configs, and Junos hierarchy or set security to parsing-srx-configs. Verify production-bound results against current device documentation and output. Downstream consumers are the audit, conversion, and diff skills.
Input Format
FortiOS configs use a hierarchical block format:
config
edit
set
set
config
edit
set
next
end
next
edit
...
next
end
Key syntax rules:
- Values with spaces are quoted:
set comment "Allow web traffic" - Multi-value fields use space-separated values:
set srcaddr "addr1" "addr2" - Full block-syntax rules:
references/config-format.md
Building the Config Tree
Parse the block format into a nested object tree:
- Track a stack of current context (section path + edit name)
config→ push section nameedit→ push entry name (strip quotes)set→ store key-value at current depthnext→ pop entryend→ pop section
Extraction Pipeline
1. Zones and Interfaces
Zones: config system zone → edit with set interface Interfaces: config system interface → edit with set vdom, set ip, set type, set vlanid Additional interface fields to extract:
set ip6(inside nestedconfig ipv6sub-block) — IPv6 addressset mtu— MTUset type aggregate→ type: "lag" (withset memberfor LAG members)set type loopback→ type: "loopback"set type tunnel→ type: "tunnel"set mode dhcp— DHCP client (no static IP)set dhcp-relay-ip— DHCP relay server IPsset allowaccess— management access protocolsset fortilink enable— FortiLink interface (exclude from output along with child interfaces)set description- Subinterface detection: dot-notation (
port1.100→ parent=port1) or VLAN-bound (set interface+set vlanid) - Management interface detection: names matching
/^(mgmt\d*|management\d*)/i→is_mgmt: true - After all interfaces parsed, back-populate
lag_memberson aggregate interfaces
Critical: Interface-as-Zone Merging FortiGate can use interface names directly as zones in policies (via srcintf/dstintf). If a policy references an interface name not in any zone, treat that interface as its own zone. Merge zones and interfaces: create a zone entry for each interface used as a zone.
Zone Building Priority 3: Unzoned Interfaces After explicit zones and policy-referenced interfaces, create auto-zones for any interface that has an IP address (or is a DHCP client) but was not yet assigned to a zone.
Allowaccess Classification: Classify allowaccess values into management services (ssh, https, http, telnet, ping, snmp, netconf, fgfm, fmg-access, ftm, radius-acct, security-fabric, fabric, capwap, speed-test) and routing protocols (ospf, bgp, rip, isis, bfd). Attach to zones as host_inbound data.
2. Address Objects
Path: config firewall address → edit
Types — detect from set type or infer from fields:
set type ipmask+set subnet→ type: "subnet" (convert mask to CIDR); promote a /32 (or IPv6 /128) result to type: "host"set type iprange+set start-ip/set end-ip→ type: "range", value: "start-end"set type fqdn+set fqdn→ type: "fqdn"set type geography+set country→ type: "geo" (warn: limited cross-platform support)set type wildcard+set wildcard→ type: "wildcard" (preserve thewildcard value; "network" is NOT a valid schema type) with info warningset type wildcard-fqdn+set wildcard-fqdn→ type: "fqdn" (convert from wildcard-fqdn with info warning)
Also extract: set comment, set associated-interface. Convert subnet mask notation (255.255.255.0) to CIDR (/24). Auto-detect IP version.
IPv6 Address Objects: config firewall address6 → edit
set ip6→ type: "subnet" (or "host" if /128)
IPv6 Address Groups: config firewall addrgrp6 → edit
set member
3. Address Groups
Path: config firewall addrgrp → edit Extract: set member (space-separated quoted names)
4. Service Objects
Path: config firewall service custom → edit Extract from:
set protocol TCP/UDP/SCTP+set tcp-portrange/set udp-portrange/set sctp-portrangeset protocol ICMP+set icmptype/set icmpcodeset protocol IP+set protocol-number→ preserve the IP protocol number `(e.g. GRE=47, ESP=50) as the service object's protocol (the numeric value, or via a warning). Only emit protocol: "any" whenset protocol IPgenuinely means all IP protocols (noprotocol-number, orprotocol-number 0`).set protocol ICMP6→ protocol: "icmpv6"- Port range format:
80or80-443or80:1024-65535(dst:src) - Note: A single custom service can set ANY combination of
tcp-portrange,udp-portrange, andsctp-portrangesimultaneously. Split into separate service objects — one TCP, one UDP, and/or one SCTP — according to which ranges are present.
5. Service Groups
Path: config firewall service group → edit Extract: set member
6. Security Policies
Path: config firewall policy → edit
For each policy extract:
- name —
set name(FortiGate uses numeric IDs as primary key, name is optional) - src_zones —
set srcintf(interface or zone names) - dst_zones —
set dstintf - src_addresses —
set srcaddr - dst_addresses —
set dstaddr - services —
set service - applications —
set application(application control IDs/names) - action —
set action accept→ "allow",set action deny→ "deny" - log_start —
set logtraffic-start enable(start logging is controlled separately fromlogtraffic) - logend —
set logtraffic all.set logtraffic utmlogs UTM/security events only, NOT end-of-session traffic — map to logend: false and note UTM-only logging inmetadata.warnings - disabled —
set status disable - description —
set comments - schedule —
set schedule - source_users —
set groups(FSSO groups)
Policy NAT (do NOT emit a policy nat field — the policy schema has no nat field): FortiGate per-policy source NAT (set nat enable, optionally with set ippool enable + set poolname ) must be translated into a nat_rules[] source-NAT entry, NOT a flag on the policy:
set nat enablealone → source-NAT (interface/egress overload) on the policy'sdstintf, scoped to the policy'ssrcaddr/dstaddr.set nat enable+set ippool enable+set poolname→ source-NAT using the named IP pool `(cross-referenceconfig firewall ippool`).- If the source-NAT intent cannot be resolved to a concrete
nat_rules[]entry, preserve it as ametadata.warnings/residual_rawnote rather than inventing a policy field.
Default values when fields are omitted from config:
actiondefaults toaccept(→ "allow")logtrafficdefaults toutmon accept policies (→ log_end: false; UTM-event logging only)statusdefaults toenable(→ disabled: false)
UTM / Security Profiles — when set utm-status enable:
set av-profile→ antivirusset webfilter-profile→ URL filteringset ips-sensor→ IPS/IDPset application-list→ application control (do NOT emit anapplication-listsecurity-profile key — it is not a schema-supported profile key; signal app-control presence viasecurity_services.app_idat device level and/or store the profile reference insecurity_profile_objects/metadata.warnings)set ssl-ssh-profile→ SSL inspectionset dnsfilter-profile→ DNS filteringset emailfilter-profile→ email filteringset dlp-profile→ DLPset profile-group→ profile group (overrides individual profiles)
7. NAT Rules
Source NAT (IP Pools): config firewall ippool → edit Extract: set startip, set endip, set type (overload, one-to-one, fixed-port-range), set associated-interface — binds pool to specific egress interface
Central SNAT: config firewall central-snat-map → edit Extract the full FortiOS central-SNAT field set so real rules are not missed:
set srcintf— source interface(s)set dstintf— destination/egress interface(s)set orig-addr— original (pre-NAT) source addressesset dst-addr— destination addresses the rule matchesset nat enable|disable— whether this entry performs NAT (a disabled entry = no-NAT exemption; preserve it)set nat-ippool(alsoset natippoolvariant) — translated source pool; absent → egress-interface overloadset protocolandset orig-port/set nat-portwhere present — protocol/port scoping
Map to a nat_rules[] source-NAT entry (or a no-NAT exemption when nat disable).
Destination NAT (VIPs): config firewall vip → edit Extract: set extip (original dest), set mappedip (translated dest), set extintf, set portforward enable + set extport / set mappedport Note: VIPs are referenced in policies via set dstaddr
8. Schedules
Recurring: config firewall schedule recurring → edit Extract: set day, set start, set end One-time: config firewall schedule onetime → edit Extract: set start, set end Group: config firewall schedule group → edit Extract: set member
9. Application Mapping (L7 → Canonical)
FortiGate supports L7 application control via set application on policies. These reference FortiOS application IDs or names from the application control database.
Extracting application references from policies:
set application— space-separated application IDs or namesset application-list— references an application control list profile (separate from direct app match)
Resolving FortiOS application names to canonical:
| FortiOS Name | Canonical App | Category | |-------------|---------------|----------| | HTTPS | https | web | | HTTP | http | web | | SSH | ssh | remote-access | | RDP | rdp | remote-access | | DNS | dns | network-mgmt | | SMTP | smtp | email | | NTP | ntp | network-mgmt | | SNMP | snmp | network-mgmt | | FTP | ftp | file-transfer | | TFTP | tftp | file-transfer | | SIP | sip | voip | | LDAP | ldap | auth | | Kerberos | kerberos | auth | | SMB | smb | file-transfer | | MySQL | mysql | database | | MSSQL | mssql | database | | PostgreSQL | postgresql | database | | MongoDB | mongodb | database | | Zoom | zoom | collaboration | | Microsoft.Teams | ms-teams | collaboration | | Slack | slack | collaboration | | YouTube | youtube | streaming | | Netflix | netflix | streaming |
On policy output: When set application values are resolved, populate the policy's apps array with { vendor_name: "HTTPS", canonical: "https", confidence: 1.0, category: "web" }. The services array keeps any set service matches separately.
Application control list profiles (config application list) define grouped app-control policies. These do not map 1:1 to application groups — they are UTM profiles that filter applications by category, risk, or specific app ID. The schema has no application-list profile key — represent app-control presence via security_services.app_id (device-level) and store the profile reference in security_profile_objects and/or metadata.warnings. Do not try to decompose the list into individual apps.
Unresolvable apps: FortiOS numeric app IDs without a known name mapping → set confidence: 0.0, preserve the ID as vendor_name, and warn.
9b. Application Groups
FortiOS does not have explicit application groups in the same way PAN-OS does. The closest equivalent is config application group which groups application control signatures.
Path: config application group → edit Extract: set application — member application IDs/names. Resolve each member to canonical. Store in application_groups array.
If a group contains a mix of L7 apps and port-based services, split them appropriately.
10. Security Profile Definitions
Parse full profile objects for reference:
config antivirus profileconfig webfilter profileconfig ips sensorconfig application listconfig firewall ssl-ssh-profile
11. Routing
- Static routes (IPv4):
config router static→editwithset dst,set gateway,set device,set distance - Static routes (IPv6):
config router static6→editwith same fields using IPv6 prefixes - BGP:
config router bgp— extract: set as,set router-id, globalset keepalive-timer/set holdtime-timer- Per-neighbor (in
config neighbor):remote-as,description,update-source,password(record presence only — redact the value, never emit it), per-neighbor timers (override global),next-hop-self,soft-reconfiguration,route-reflector-client,status enable|disable config networkentries (prefix advertisements)config redistributewithset status enable|disable- Warn: route-map/prefix-list references are not converted
- OSPF:
config router ospf— extract: set router-id,set auto-cost-reference-bandwidthconfig area: area ID, type (stub/nssa with no-summary), default-cost, authenticationconfig ospf-interface: area assignment, passive flag, cost, priority, hello/dead intervals, network-type (point-to-point/broadcast), MD5 authentication with key ID (record key presence only — redact the key value)config redistribute: source, status, metric, metric-type- Warn: MD5 keys in cleartext in source config (key values are never emitted in output)
- OSPFv3:
config router ospf6— same structure but usesconfig ospf6-interface(notospf-interface) - Policy routing:
config router policy→ PBF rules
12. Infrastructure
- Version: Extract from
#config-version=:comment line at top of config - System Global:
config system global→ extractset hostname - DNS:
config system dns→ extractset primary,set secondary,set domain - NTP:
config system ntpwith nestedconfig ntpserver→ extract server entries - Admin Users:
config system admin→ extract access profile (superadmin→super-admin, profadmin→admin), SSH public keys (ssh-public-key1/2/3). Warn when users lack SSH keys. - HA:
config system ha—set mode(a-p/a-a),set group-id,set priority,
set hbdev, set monitor
- Screen/DoS:
config firewall DoS-policy+ IPS sensor definitions - Syslog:
config log syslogd setting - DHCP Server:
config system dhcp server— extract top-level fields (set default-gateway,set netmask,set interface,set domain,set lease-time,set dns-server1/dns-server2) plus nestedconfig ip-range(start-ip/end-ip) andconfig reserved-address(mac, ip, description). Derive network CIDR from gateway + netmask.
FortiOS compound proposal parsing for VPN: FortiOS encodes IKE/IPsec proposals as compound strings. Do NOT assume every proposal is a simple encryption-integrity pair
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: fastrevmd-lab
- Source: fastrevmd-lab/fwskillsshare
- License: Apache-2.0
- Homepage: https://mechub.org
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.