Skip to content

CSV Import

The Batch Import tab supports CSV file upload for bulk-validating up to 500 firewall rules at once.

CSV import and bulk validation walkthrough

CSV format

Each row describes one flow in 4 or 5 columns, in this order:

ColumnRequiredDescriptionExample
sourceYesSource IP or CIDR subnet, or any10.0.0.0/8
destinationYesDestination IP or CIDR subnet, or any8.8.8.8
protocolYesTCP, UDP, ICMP, or ANY (any case)TCP
portYesPort number, range, quoted list, or any. For ICMP: type number(s) or all443, 8080-8090, "80,443"
purposeNoBusiness justification / application nameWeb proxy egress

Columns are read by position, so the header names do not matter (app_name, application_business_purpose and purpose all work for the fifth column).

Example CSV:

source,destination,protocol,port,application_business_purpose
10.0.1.0/24,172.16.5.10,TCP,443,Payment gateway HTTPS
10.0.1.0/24,172.16.5.11,TCP,"80,443",Web frontend
192.168.0.0/16,0.0.0.0/0,ANY,any,Default outbound
10.10.0.5,10.10.0.6,ICMP,"0,8",Monitoring ping

Header row

The header row is optional. The first row (after comments and blank lines) is treated as a header when both of these are true:

  • its first cell does not look like an address (it does not start with a digit or :, and is not any or all);
  • its third cell is not a protocol name (TCP, UDP, ICMP or ANY).

Every valid data row fails this test, so a data row is never skipped by mistake. Headers such as source,destination,protocol,port, Source IP,Destination IP,Protocol,Port, src_ip,dst_ip,proto,port and From,To,Proto,Port are all recognised. Only the first row can be a header; a header-like row further down is shown as an error row.

Accepted syntax

  • Lines starting with # (also after leading spaces) are comments and are ignored.
  • Blank lines and rows of empty cells (such as ,,,, from a spreadsheet) are ignored. Empty cells after the fifth column are ignored too.
  • Quoted fields follow RFC 4180: a quoted field may contain commas and line breaks, and "" inside quotes is a literal quote.
  • A UTF-8 byte-order mark and Windows (CRLF), Unix (LF) or old Mac (CR) line endings are accepted.
  • Semicolon- and tab-separated files are detected automatically from the first non-comment line. It is read as semicolon (or tab) separated when it has at least three semicolons (or tabs) outside quotes and either fewer than three commas, or the semicolon (tab) split puts a protocol name in the third column while the comma split does not. So semicolons in an unquoted purpose do not turn a comma file into a semicolon file. An Excel sep=; (or sep= followed by a tab) first line is also honoured.

Quote port lists and ICMP type lists

A comma inside an unquoted port list splits the row into extra columns. Put lists in double quotes: "80,443" or, for ICMP, "0,8". Rows that look like an unquoted list are rejected instead of being silently misread:

  • more than 5 columns, for example 10.0.0.1,10.0.0.2,TCP,80,443,Web;
  • exactly 5 columns where the fifth column is a number or a number range, for example 10.0.0.1,10.0.0.2,TCP,80,23 (this would otherwise hide Telnet on port 23). A purely numeric purpose is not meaningful; add some text, such as Ticket 4711.

Rows that cannot be read

A row that cannot be read is kept as an error row: it appears in the results table and in the export with its error message, and it is not analysed. Messages name the line in the file:

ProblemMessage
Too few columnsLine 7: 3 columns found, expected 4 or 5 (source, destination, protocol, port, optional purpose).
Too many columnsLine 6: 6 columns found, expected at most 5. Put port lists and ICMP type lists in double quotes, e.g. "80,443" or "0,8".
Numeric fifth columnLine 5: the 5th column "23" looks like a port. Put port lists in double quotes, e.g. "80,23".
Unclosed quoteLine 4: a quoted field is not closed (missing "). (the rest of the file belongs to this row)

Rows with an invalid value, such as a malformed IP address, an unknown protocol or an empty port, are also shown as error rows, with the validation message.

Uploading

  • Drag and drop a file onto the upload area, or click to browse for a file. Accepted extensions are .csv, .txt and .md, plus the cloud formats.
  • A template CSV is available for download from the import tab. It lists the rules above as # comments and contains example rows, including a quoted port list.
  • Maximum of 500 rows per import. Rows beyond the limit are ignored, and the status line says how many.
  • For zone-aware analysis, define zones in the Zones tab (or load a saved session) before uploading.

Import status

The status line under the upload area reports what happened:

ColourMeaningExample
GreenEvery row was analysed12 rows analysed from flows.csv.
AmberSome rows had errors, rows were ignored over the limit, or the parser reported warnings10 of 12 rows analysed from flows.csv - 2 rows had errors.
RedNothing could be analysed, or the file could not be read0 of 3 rows analysed from flows.csv - 3 rows had errors. / No data rows found in empty.csv. ...

Every new upload replaces the previous file's results, even when the upload fails, so the table and the export never show results from an older file. A results table from manually entered flows is kept when an upload fails.

A .json, .yaml, .yml or .tf file that is not a supported cloud format gets a specific error (for example data.json: JSON structure not recognised. ...) instead of being read as CSV. A .csv, .txt or .md file gets that error only if its whole content is valid JSON; anything else, including a header such as [source],[destination],[protocol],[port], is read as CSV.

Results table

After validation completes, results appear in a sortable table with the following columns:

ColumnDescription
#Row number (data rows only, in file order)
SourceSource IP/subnet from the CSV
DestinationDestination IP/subnet from the CSV
Src Zone / Dst ZoneMatched zone names (shown when zones are configured)
Protocol / PortProtocol and port(s), e.g. TCP / 443
Risk ScoreComposite risk score (0-100) with its severity label; hover for the breakdown
Zone PolicyALLOW, REVIEW, DENY or NO MATCH (shown when zones are configured)
Top RecommendationThe most important built-in observation for the flow
PCI / CIS / NIST / NIS2 / DORA / ATT&CK IssuesNumber of findings per framework
CustomNumber of custom rule findings

Error rows show their message in place of the score and recommendation. Click any column header to sort, and click a row to expand its full findings. Large result sets are paginated automatically.

Exporting results

Click Export CSV ↓ to download the results as netbobr-results.csv, with one row per flow (error rows included):

  • The header row is always line 1. There is no comment or preamble line, so the file loads directly with spreadsheet tools, pandas.read_csv or Python's csv.DictReader.
  • UTF-8 without a byte-order mark, one \n after every row. In Excel, use Data → From Text/CSV if non-ASCII characters (for example in zone names) display incorrectly.
  • Spreadsheet formula protection (OWASP CSV injection): a cell that starts with =, +, -, @ (or their full-width forms =, +, -, @, which some spreadsheet locales also evaluate), a tab or a line break is prefixed with a single quote ('=1+1), so a spreadsheet shows it as text instead of evaluating it. Cells containing commas, semicolons, tabs, quotes or line breaks are quoted.
  • Several values in one cell are joined with ; (other_observations uses |).

Export columns

ColumnDescription
rowRow number, as in the table's # column
source, destinationSource and destination as entered
src_zone, dst_zoneZone names as shown in the table; empty when no zones are defined
zone_policyALLOW, REVIEW, DENY or NO MATCH, as in the table; empty when no zones are defined
protocol_portProtocol and port(s) as shown in the table, e.g. TCP / 443
risk_scoreComposite risk score, 0-100 (the number in the table's Risk Score badge)
risk_levelLabel of the risk score: Low, Medium, High or Critical
overall_riskHighest single-factor level among source, destination, protocol and port: LOW, MEDIUM, MEDIUM-HIGH, HIGH or CRITICAL. It is not derived from risk_score: internal Telnet (port 23) is CRITICAL here while its score is 36 (Medium)
src_scope, src_riskSource breadth (e.g. Single host (/32)) and its level
dst_scope, dst_riskDestination breadth and its level
port_scope, port_riskPort exposure and its level (for ICMP, the protocol)
other_observationsBuilt-in observations as [SEVERITY] text, joined with |
pci_count, pci_rulesNumber of PCI-DSS findings and the findings as RULE-ID (SEVERITY): finding
cis_count, cis_rulesThe same for CIS Controls
nist_count, nist_rulesThe same for NIST 800-53
nis2_count, nis2_rulesThe same for NIS2
dora_count, dora_rulesThe same for DORA
mitre_count, mitre_rulesThe same for MITRE ATT&CK, as RULE-ID [technique] (SEVERITY): finding
custom_count, custom_rulesThe same for custom rules; deny overrides end with [FORCE DENY]
errorWhy the row was not analysed; empty for analysed rows. On error rows, the score, scope, observation and count columns are empty
disabled_rulesIDs of the rules disabled in the Rules tab at export time, sorted and joined with ; ; the same on every row, empty when none

Counts are 0 (not empty) when an analysed flow has no findings for a framework.

Scripts written for older exports: the first line used to be a # Disabled rules: ... comment (now the disabled_rules column), the # column is now row, and the risk column is now overall_risk. zone_policy, risk_score, risk_level and error are new.

Cloud format imports

For importing native cloud firewall configurations (AWS Security Groups, Azure NSG, GCP Firewall Rules, Terraform, Kubernetes NetworkPolicy), see Cloud Imports. Cloud formats are auto-detected -- just drag and drop the exported JSON, YAML or .tf file. Cloud imports use the same status line, results table and export.