Module development · commixproject/commix Wiki · GitHub
Skip to content

Module development

stasinopoulos edited this page Sep 14, 2026 · 3 revisions

Commix supports a modular design, making it easy to extend its capabilities by adding custom Python modules. This is useful for penetration testers, researchers, and developers who want to cover a vulnerability class that the standard techniques do not reach, without touching the core engine.

Modules versus techniques

A technique is one of the ways commix proves and drives command execution through an injectable parameter - classic, dynamic code evaluation, time-based, file-based, tempfile-based. Techniques are selected with --technique/--skip-technique and are tested against every injection point commix finds.

A module is a self-contained check for a vulnerability class that does not fit that model, usually because the injection point is not a parameter at all. It gets its own switch, runs instead of the normal detection flow, and never goes through --technique. The bundled --shellshock module is the reference implementation: it injects through HTTP headers, not parameters.

Out-of-band is deliberately not one of the --technique letters for this reason - it is the --oob switch, so that it can serve the modules too. A module can therefore offer OAST detection and command execution of its own; shellshock.py does exactly that.


Creating a new module

Assume we want to add a module named new_module, driven by a --new-module switch.

Step 1: Create the module package

Each module is its own package under src/core/modules/:

src/core/modules/new_module/
├── __init__.py
└── new_module.py

The __init__.py may be empty. Placing a bare .py file directly in src/core/modules/ is not enough - the loader imports a module path, so the package must exist.

Step 2: Define the handler

The entry point is a handler function, not main(). Its signature is fixed:

def new_module_handler(url, http_request_method, filename):
    # url                 : the target URL currently being tested
    # http_request_method : the HTTP method in use (e.g. 'GET', 'POST')
    # filename            : the session/output file, passed to the shared checks helpers
    ...

The handler is responsible for the whole lifecycle of its check: detection, reporting the injection point, and post-exploitation. When it is done it should end the run the same way the core engine does, rather than returning into the normal detection flow.

Step 3: Register the module

Open src/core/modules/modules_handler.py and add an entry to the MODULES registry. The key is the CLI switch name, and the value is the import path paired with the handler's name:

MODULES = {
  "shellshock": ("src.core.modules.shellshock.shellshock", "shellshock_handler"),
  "new_module": ("src.core.modules.new_module.new_module", "new_module_handler"),
}

load_modules() walks this registry and runs the first module whose switch is set, so no import or call has to be hand-written into the loader.

Step 4: Add the CLI switch

Open src/core/parse/cmdline.py and add the switch to the modules option group. The dest must match the MODULES key exactly - that is how the loader tells whether the module was requested:

modules.add_option("--new-module",
                action="store_true",
                dest="new_module",
                default=False,
                help="The 'new_module' injection module.")

Reusing the core building blocks

A module should reuse the shared core building blocks instead of reimplementing them. Rolling your own request or output-recovery logic means losing session resume, tamper scripts, WAF handling and the --os-shell modes for free. The pieces most modules need:

What you need Use
Sending requests src.core.requests.requests
Detection helpers, payload tails, OOB proof checks src.core.injections.controller.checks
--file-read/--file-write support checks.run_file_access(execute_cmd, filename)
Offering the interactive shell checks.suggest_os_shell()
The os_shell/reverse_tcp/bind_tcp modes src.core.injections.controller.shell_options
Storing and resuming injection points src.utils.session_handler
Ending the run cleanly checks.quit(filename, url, hard_exit=False)

Most of these are reached through a single callback your module provides - a execute_cmd(cmd) -> output function that runs one command on the target and returns its output. Once that exists, the shared helpers handle enumeration, file access and the shell modes without the module knowing how any of them work.


Summary

To add a new module to commix:

  1. Create src/core/modules/<name>/ with an __init__.py and <name>.py.
  2. Define <name>_handler(url, http_request_method, filename) as the entry point.
  3. Register it in the MODULES dict in src/core/modules/modules_handler.py.
  4. Add a matching switch to the modules group in src/core/parse/cmdline.py, with dest equal to the registry key.
  5. Reuse the shared helpers rather than reimplementing requests, file access or the shell modes.

Read shellshock.py as the worked reference - it covers header-based injection, session resume, OAST detection and command execution, file access and post-exploitation in the shape described above.

Example use cases for custom modules

  • Vulnerability classes injecting through something other than a parameter (headers, cookies, protocol fields)
  • Target-specific fingerprinting before the standard techniques run
  • CVE-specific checks with their own payload set
  • Integration with external tools or platforms
  • Automated post-exploitation routines

By leveraging this extensibility, users can adapt commix to fit specialized workflows or research requirements.

Contents

User's manual

Exploitation

Miscellaneous

  • Presentations - Conference talks, demos, and public presentations where commix has been featured or discussed.
  • Screenshots - Visual examples of commix in action
  • Third party references - References to commix in books, articles, research papers, blog posts, etc
  • Command injection testbeds - A curated list of intentionally vulnerable web applications and platforms for safely testing commix

Clone this wiki locally