# How to Add Custom Nmap Scripts to LazyOwn's Tool Library

> Easily add custom Nmap scripts to LazyOwn's extensive tool library. Learn to integrate them temporarily via nmapscript or permanently with .tool JSON files for enhanced scanning.

- Repository: [Grisuno/lazyown](https://github.com/grisuno/lazyown)
- Tags: how-to-guide
- Published: 2026-03-02

---

**You can add custom Nmap scripts to LazyOwn either by using the built-in `nmapscript` command for temporary execution or by creating a `.tool` JSON definition file in `main/tools/` for permanent integration into the tool library.**

LazyOwn is an open-source penetration testing framework that ships with a modular tool library located in `main/tools/`. Adding custom Nmap scripts to LazyOwn allows you to extend its scanning capabilities with your own NSE scripts while maintaining integration with the framework's session management and output handling.

## Two Approaches to Add Custom Nmap Scripts to LazyOwn

LazyOwn provides two distinct methods for incorporating Nmap NSE scripts, depending on whether you need a quick one-off scan or a reusable tool definition.

### Ad-Hoc Execution with the nmapscript Command

For quick tests without persisting the configuration, use the built-in `do_nmapscript` method implemented in [`main/lazyown.py`](https://github.com/grisuno/lazyown/blob/main/main/lazyown.py) (lines 8225-8250). This command constructs and executes:

```bash
nmap -sCV --script <script> -p<port> <rhost> -oN sessions/<script>_<rhost>

```

This approach requires no file creation but does not save the script to the library for future use.

### Permanent Integration via Tool Definitions

To make a custom Nmap script a first-class citizen in LazyOwn's tool library, create a `.tool` JSON definition in `main/tools/`. This method supports placeholders for dynamic values, trigger-based automation, and UI toggling.

## Creating a Permanent Custom Nmap Tool

Follow these steps to register a custom NSE script as a reusable tool.

### Step 1: Create a .tool JSON Definition File

Create a new file in `main/tools/` following the structure used by existing definitions like `smbnmap.tool`:

```json
{
    "toolname": "my_custom_nmap",
    "command": "nmap --script myscript.nse -p {port} {ip} -oN sessions/{script}_{ip}_{port}.nmap --stylesheet sessions/nmap-bootstrap.xsl -oX sessions/{script}_{ip}_{port}.nmap.xml",
    "trigger": ["myservice"],
    "active": true
}

```

Key fields include:
- **toolname**: Unique identifier for the tool.
- **command**: The full Nmap command with placeholders (`{ip}`, `{port}`, `{script}`) replaced at runtime.
- **trigger**: Optional service identifiers for automated tool suggestion logic.
- **active**: Boolean to toggle availability in the UI.

Save the file with a `.tool` extension, for example: `main/tools/my_custom_nmap.tool`.

### Step 2: Add Metadata with a YAML Plugin File (Optional)

For human-readable descriptions, icons, or dependency tracking, create a companion YAML file in `main/plugins/`:

```yaml
name: my_custom_nmap
description: |
  Executes the Nmap vulscan NSE script against a target.
author: "Your Name"
version: "1.0"
enabled: true
tags:
  - nmap
  - vulscan
params: []
permissions: []
requires_root: false
dependencies:
  - nmap
outputs: []

```

The [`main/plugins/init_plugins.lua`](https://github.com/grisuno/lazyown/blob/main/main/plugins/init_plugins.lua) file auto-registers these YAML definitions with the CLI, making metadata available to the UI.

### Step 3: Reload LazyOwn to Activate the Tool

LazyOwn monitors the `tools/` directory for changes. After saving your files, either:
- Restart the LazyOwn CLI or UI.
- Execute the `reload` command if your session supports hot-reloading.

The new tool appears under the "Scanning" category with the `toolname` you specified.

## Using the Built-In nmapscript Command for Quick Tests

For immediate execution without file creation, use the interactive `nmapscript` command:

```text
nmapscript <script-name> <port>

```

Example usage within the LazyOwn shell:

```text
> set rhost 10.10.10.10
> nmapscript ssl-heartbleed 443

```

LazyOwn constructs and displays the resulting command:

```bash
nmap -sCV --script ssl-heartbleed -p443 10.10.10.10 -oN sessions/ssl-heartbleed_10.10.10.10

```

This method references the `do_nmapscript` implementation in [`main/lazyown.py`](https://github.com/grisuno/lazyown/blob/main/main/lazyown.py) (lines 8225-8250) and requires no persistent configuration.

## Practical Code Examples

### Example 1: Adding a Vulnerability Scanning Tool

The following bash commands create a complete custom tool definition for the `vulscan` NSE script:

```bash

# Create the tool definition

cat > main/tools/vulscan_nmap.tool <<'EOF'
{
    "toolname": "vulscan_nmap",
    "command": "nmap --script vulscan.nse -p {port} {ip} -oN sessions/vulscan_{ip}_{port}.nmap",
    "trigger": ["vuln", "scan"],
    "active": true
}
EOF

# Create optional metadata plugin

cat > main/plugins/vulscan_nmap.yaml <<'EOF'
name: vulscan_nmap
description: |
  Executes the Nmap vulscan NSE script against a target for vulnerability detection.
author: "Security Team"
version: "1.0"
enabled: true
tags:
  - nmap
  - vulscan
  - vulnerability
dependencies:
  - nmap
EOF

```

Execute from the LazyOwn prompt:

```text
> run_tool vulscan_nmap 192.168.1.42 443

```

LazyOwn expands the placeholders and launches:

```bash
nmap --script vulscan.nse -p 443 192.168.1.42 -oN sessions/vulscan_192.168.1.42_443.nmap

```

### Example 2: Running One-Off Scripts Interactively

For immediate testing of a new NSE script without persistence:

```text
> set rhost 10.10.10.10
> nmapscript http-enum 80

```

This generates and executes:

```bash
nmap -sCV --script http-enum -p80 10.10.10.10 -oN sessions/http-enum_10.10.10.10

```

## Key Files and Implementation Details

Understanding the repository structure helps when adding custom Nmap scripts to LazyOwn:

| Path | Role |
|------|------|
| `main/tools/*.tool` | JSON definitions that map tool names to executable command lines (e.g., **smbnmap.tool**). |
| `main/plugins/*.yaml` | Optional metadata files providing descriptions, dependencies, and tags for tools (e.g., **run_nuclei_on_nmap_files.yaml**). |
| [`main/lazyown.py`](https://github.com/grisuno/lazyown/blob/main/main/lazyown.py) (lines 8225-8250) | Contains the `do_nmapscript` method for ad-hoc Nmap script execution. |
| [`main/plugins/init_plugins.lua`](https://github.com/grisuno/lazyown/blob/main/main/plugins/init_plugins.lua) | Auto-registers YAML plugin definitions with the CLI framework. |
| [`main/README.md`](https://github.com/grisuno/lazyown/blob/main/main/README.md) & [`main/COMMANDS.md`](https://github.com/grisuno/lazyown/blob/main/main/COMMANDS.md) | Documentation references for available commands and plugin architecture. |

Both approaches—ad-hoc and permanent—reuse the host's installed `nmap` binary and output to the `sessions/` directory for result persistence.

## Summary

- **Ad-hoc execution** requires no file changes; use `nmapscript <script> <port>` for immediate scans.
- **Permanent integration** involves creating a `.tool` JSON file in `main/tools/` with proper placeholders (`{ip}`, `{port}`, `{script}`).
- **Optional metadata** can be added via YAML files in `main/plugins/` for better UI integration and documentation.
- **Activation** requires reloading LazyOwn or restarting the CLI to pick up new tool definitions.
- All methods reference the `do_nmapscript` implementation in [`main/lazyown.py`](https://github.com/grisuno/lazyown/blob/main/main/lazyown.py) and output results to the `sessions/` directory.

## Frequently Asked Questions

### Where does LazyOwn store its tool definitions?

LazyOwn stores tool definitions as JSON files with the `.tool` extension in the `main/tools/` directory. Each file maps a tool name to a command line template using placeholders like `{ip}` and `{port}`. The UI automatically discovers and loads these files on startup or when the `reload` command is executed.

### Can I use custom Nmap scripts without restarting LazyOwn?

Yes. While creating a permanent tool requires a `.tool` file, you can execute any Nmap NSE script immediately without file creation by using the built-in `nmapscript` command. This command, implemented in [`main/lazyown.py`](https://github.com/grisuno/lazyown/blob/main/main/lazyown.py) at lines 8225-8250, constructs the full Nmap command and executes it against the current `rhost` setting without persisting the configuration to the library.

### What placeholders are available in .tool files?

LazyOwn's tool engine recognizes several placeholders that it substitutes at runtime: `{ip}` (or `{rhost}`) for the target IP address, `{port}` for the target port number, and `{script}` for the script name. You can also use custom placeholders that map to environment variables or session settings. The engine performs string replacement on the `command` field before executing the resulting shell command.

### How do I verify my custom script is properly registered?

After creating your `.tool` file in `main/tools/` and optionally the YAML metadata in `main/plugins/`, restart LazyOwn or run the `reload` command if available. Then list the available tools or attempt to run your tool using `run_tool <toolname> <ip> <port>`. If the tool appears in the listing or executes without a "command not found" error, it is properly registered. Check the `sessions/` directory for output files to confirm execution completed successfully.