Writing Script Documentation (NSEDoc)

Scripts are used by more than just their authors, so they require good documentation. NSE modules need documentation so developers can use them in their scripts. NSE's documentation system, described in this section, aims to meet both these needs. While reading this section, you may want to browse NSE's online documentation, which is generated using this system. It is at https://nmap.org/nsedoc/.

NSE uses a customized version of the LuaDoc documentation system called NSEDoc. The documentation for scripts and modules is contained in their source code, as comments with a special form. Example 9.7 is an NSEDoc comment taken from the stdnse.print_debug() function.

Example 9.7. An NSEDoc comment for a function
---
-- Prints a formatted debug message if the current verbosity level is greater
-- than or equal to a given level.
-- 
-- This is a convenience wrapper around
-- <code>nmap.log_write</code>. The first optional numeric
-- argument, <code>level</code>, is used as the debugging level necessary
-- to print the message (it defaults to 1 if omitted). All remaining arguments
-- are processed with Lua's <code>string.format</code> function.
-- @param level Optional debugging level.
-- @param fmt Format string.
-- @param ... Arguments to format.

Documentation comments start with three dashes: ---. The body of the comment is the description of the following code. The first paragraph of the description should be a brief summary, with the following paragraphs providing more detail. Special tags starting with @ mark off other parts of the documentation. In the above example you see @param, which is used to describe each parameter of a function. A complete list of the documentation tags is found in the section called “NSE Documentation Tags”.

Text enclosed in the HTML-like <code> and </code> tags will be rendered in a monospace font. This should be used for variable and function names, as well as multi-line code examples. When a sequence of lines start with the characters * , they will be rendered as a bulleted list. Each list item must be entirely on one physical line.

It is good practice to document every public function and table in a script or module. Additionally every script and module should have its own file-level documentation. A documentation comment at the beginning of a file (one that is not followed by a function or table definition) applies to the entire file. File-level documentation can and should be several paragraphs long, with all the high-level information useful to a developer using a module or a user running a script. Example 9.8 shows documentation for the comm module (with a few paragraphs removed to save space).

Example 9.8. An NSEDoc comment for a module
---
-- Common communication functions for network discovery tasks like
-- banner grabbing and data exchange.
--
-- These functions may be passed a table of options, but it's not required. The
-- keys for the options table are <code>"bytes"</code>, <code>"lines"</code>,
-- <code>"proto"</code>, and <code>"timeout"</code>. <code>"bytes"</code> sets
-- a minimum number of bytes to read. <code>"lines"</code> does the same for
-- lines. <code>"proto"</code> sets the protocol to communicate with,
-- defaulting to <code>"tcp"</code> if not provided. <code>"timeout"</code>
-- sets the socket timeout (see the socket function <code>set_timeout</code>
-- for details). 
--
-- @author Kris Katterjohn 04/2008
-- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html

There are some special considerations for documenting scripts rather than functions and modules. In particular, scripts have special variables for some information which would otherwise belongs in @-tag comments (script variables are described in the section called “Script Format”). In particular, a script's description belongs in the description variable rather than in a documentation comment, and the information that would go in @author and @copyright belong in the variables author and license instead. NSEDoc knows about these variables and will use them in preference to fields in the comments. Scripts should also have @output and @xmloutput tags showing sample output, as well as @args and @usage where appropriate. Example 9.9 shows proper form for script-level documentation, using a combination of documentation comments and NSE variables.

Example 9.9. An NSEDoc comment for a script
description = [[
Maps IP addresses to autonomous system (AS) numbers.

The script works by sending DNS TXT queries to a DNS server which in
turn queries a third-party service provided by Team Cymru
(team-cymru.org) using an in-addr.arpa style zone set up especially for
use by Nmap. The responses to these queries contain both Origin and Peer
ASNs and their descriptions, displayed along with the BGP Prefix and
Country Code. The script caches results to reduce the number of queries
and should perform a single query for all scanned targets in a BGP
Prefix present in Team Cymru's database.

Be aware that any targets against which this script is run will be sent
to and potentially recorded by one or more DNS servers and Team Cymru.
In addition your IP address will be sent along with the ASN to a DNS
server (your default DNS server, or whichever one you specified with the
<code>dns</code> script argument).
]]

---
-- @usage
-- nmap --script asn-query [--script-args dns=<DNS server>] <target>
-- @args dns The address of a recursive nameserver to use (optional).
-- @output
-- Host script results:
-- |  asn-query:
-- |  BGP: 64.13.128.0/21 | Country: US
-- |    Origin AS: 10565 SVCOLO-AS - Silicon Valley Colocation, Inc.
-- |      Peer AS: 3561 6461
-- |  BGP: 64.13.128.0/18 | Country: US
-- |    Origin AS: 10565 SVCOLO-AS - Silicon Valley Colocation, Inc.
-- |_     Peer AS: 174 2914 6461

author = "jah, Michael"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"discovery", "external", "safe"}

Compiled NSE modules are also documented with NSEDoc, even though they have no Lua source code. Each compiled module has a file <modulename>.luadoc that is kept in the nselib directory alongside the Lua modules. This file lists and documents the functions and tables in the compiled module as though they were written in Lua. Only the name of each function is required, not its definition (not even end). You must use the @name and @class tags when documenting a table to assist the documentation parser in identifying it. There are several examples of this method of documentation in the Nmap source distribution (including nmap.luadoc, lfs.luadoc, and pcre.luadoc).

NSE Documentation Tags

The following tags are understood by NSEDoc:

@param

Describes a function parameter. The first word following @param is the name of the parameter being described. The tag should appear once for each parameter of a function.

@see

Adds a cross-reference to another function or table.

@return

Describes a return value of a function. @return may be used multiple times for multiple return values.

@usage

Provides a usage example of a function, script, or module. In the case of a function, the example is Lua code; for a script it is an Nmap command line; and for a module it is usually a code sample. @usage may be given more than once. If it is omitted in a script, NSEDoc generates a default standardized usage example.

@name

Defines a name for the function or table being documented. This tag is normally not necessary because NSEDoc infers names through code analysis.

@class

Defines the class of the object being documented: function, table, or module. Like @name, this is normally inferred automatically.

@field

In the documentation of a table, @field describes the value of a named field.

@args

Describes a script argument, as used with the --script-args option (see the section called “Arguments to Scripts”). The first word after @args is the name of the argument, and everything following that is the description. This tag is special to script-level comments.

@output

This tag, which is exclusive to script-level comments, shows sample output from a script.

@xmloutput

Shows what the script's the section called “Structured and Unstructured Output” looks like when written to XML. The XML sample should not include the enclosing <script> and </script> tags and should be indented to show hierarchy.

@author

This tag, which may be given multiple times, lists the authors of an NSE module. For scripts, use the author variable instead.

@copyright

This tag describes the copyright status of a module. For scripts, use the license variable instead.