Skip to content

Migrating from BBOT 3.0 to 3.1

BBOT 3.1 is a minor release, but it includes a handful of changes that can affect existing presets, configs, custom modules, and anything that consumes scan output. This page lists them so you can check your setup before upgrading.

If a change is missing here, please open an issue.


Config and Presets

Custom module folders (module_dirs)

module_dirs is now only honored as a top-level preset key, loaded with -p:

module_dirs:
  - /home/user/my_modules
3.0 3.1
config.module_dirs (in bbot.yml, under config: in a preset, or -c module_dirs=...) loaded custom modules deprecated and ignored, with a warning at scan start
custom modules loaded without asking BBOT asks before loading each custom module folder
a custom module could replace a built-in module with the same name refused with an error
-S / --silent implied -y, auto-trusting custom module folders -S no longer implies -y; a silent run refuses an untrusted folder (with a visible error) unless -y is also passed

Loading custom modules now works like this:

  • Before anything in a custom module folder is read, BBOT lists its modules and asks Do you trust this folder? [y/N]. Without a terminal (CI, cron, pipes), it refuses unless -y is passed.
  • A folder, parent folder, or module file that is world-writable is refused, with the chmod command to fix it. Sticky parents like /tmp are allowed. Folders or files writable by a group are noted in the prompt.
  • If the folder is owned by another user (common with sudo, or folders mounted into the Docker image), the prompt says so.
  • A custom module can't reuse the name of an existing module, built-in or custom. Rename it and leave the original off.
  • A custom module folder can't be named modules (it collides with BBOT's built-in module package).
  • Custom modules are loaded from source, not from any cached bytecode (__pycache__).

-y trusts custom module folders

-y / --yes answers the trust prompt automatically. The warning still prints, but the modules load. Only pass -y with presets you trust. -S / --silent does not answer the prompt: a silent run without -y stops with an error.

See Custom Modules for details.

Preset conditions are read-only

Preset conditions can now only read the preset and config (plus warn() / abort()); they can no longer modify the preset or call its methods. A condition that changed the preset (like the old {{ preset.exclude_module("webbrute") }} example) now errors. Conditions that check config and warn or abort are unaffected.

version and home are validated

Because they're interpolated into dependency install commands, a module's version option and the global home option are now validated when the preset is checked: version must be a version-like string, and home can't contain shell metacharacters. A value that doesn't fit stops the scan before it starts instead of ending up in a shell command.

Deprecated retries options

The retries option on slack, discord, teams, and shodan_idb no longer does anything. Retries and rate limits are now handled by the shared API request logic. The option is still accepted, but it's ignored and BBOT warns about it at scan start.

Nuclei options are validated up front

modules.nuclei.severity, exclude_severity, and protocol_types are now checked when the preset is validated. A typo that used to fail partway into a scan now stops the scan before it starts.


CDN/WAF Port Filtering

CDN/WAF port filtering moved out of the portfilter module and into the core, and it's now on by default.

3.0 3.1
portfilter module (opt-in, enabled by some presets) removed; filtering is built in and on by default
modules.portfilter.cdn_tags cdn_port_filter.tags
modules.portfilter.allowed_cdn_ports cdn_port_filter.allowed_ports
--exclude-cdn / -ec deprecated, does nothing
(no equivalent) --allow-cdn-ports / cdn_port_filter.enabled: false turns the filter off

By default, open ports other than 80 and 443 are dropped on hosts tagged cdn or waf. If you relied on seeing every port on CDN hosts, pass --allow-cdn-ports.

Remove portfilter from presets

Presets that list portfilter under modules need to be updated, since the module no longer exists.


Modules

dnsdumpster requires an API key

dnsdumpster no longer has a keyless mode. Set modules.dnsdumpster.api_key, or the module is disabled at setup.

waf_bypass only targets scan targets by default

modules.waf_bypass.scan_targets_only now defaults to true, so bypasses are only attempted against hosts named in the scan's targets or seeds. Set it to false for the old behavior.

wayback checks hosts before emitting URLs

With urls: true, wayback now probes each host once and drops URLs on hosts that don't respond. Expect fewer, but live, URLs from wayback.


Event Output

CPE-based technology names

TECHNOLOGY events from shodan_idb, shodan_enterprise, and censys_ip that come from a CPE now use the product name (e.g. jquery) instead of the raw CPE string. The CPE moves to a new cpe field. Anything that matched on the CPE string in technology should match on cpe instead.

No affiliate tag on in-scope events

In-scope events are no longer tagged affiliate. Filters that relied on that tag for in-scope events will need updating.

wayback HTTP_RESPONSE events

HTTP_RESPONSE events from wayback are now built the same way as those from http, so some keys in their data have changed. They also no longer include cert_info, which described archive.org's certificate rather than the target's.


Python API / Custom Modules

3.0 3.1
self.helpers.response_to_json(response) removed; use response_to_event_dict() from bbot.core.helpers.web.response_event