Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
676d567
better filtering
TheTechromancer Jun 13, 2025
ec79a42
fix tests
TheTechromancer Jun 13, 2025
185ddb4
improvements on technology filtering
TheTechromancer Jul 3, 2025
4e159b8
hot reload bbot server
TheTechromancer Jul 3, 2025
d30650a
fix conflicts
TheTechromancer Jul 3, 2025
b76b8a6
fix conflicts
TheTechromancer Jul 3, 2025
47ccb8d
fix tests
TheTechromancer Jul 3, 2025
a9ccc8d
ruffed
TheTechromancer Jul 3, 2025
5e1ba45
fix target_id filtering for technologies and findings listing when us…
bWlrYQ Jul 10, 2025
30f60fa
update uvicorn
TheTechromancer Jul 15, 2025
1d4f79d
tests tweak
TheTechromancer Jul 15, 2025
a99d599
Merge pull request #58 from blacklanternsecurity/update-uvicorn
TheTechromancer Jul 15, 2025
1720883
tests tweak
TheTechromancer Jul 15, 2025
a13cc6d
fix asset import error
TheTechromancer Jul 15, 2025
7e22280
Merge pull request #61 from blacklanternsecurity/fix-import-error
TheTechromancer Jul 16, 2025
1235344
Surprisingly simple convert from Motor to PyMongo's Async.
ausmaster Jul 16, 2025
2212ce4
Fix test_asset_indexes.py.
ausmaster Jul 16, 2025
35e0307
Missed some Motor references.
ausmaster Jul 16, 2025
b61097a
update readme, some debugging
TheTechromancer Jul 16, 2025
9015f9f
fix archival errors
TheTechromancer Jul 16, 2025
1dfdb00
fix str comparison error
TheTechromancer Jul 16, 2025
2dbc58f
Merge pull request #63 from blacklanternsecurity/motor-to-pymongo-asy…
TheTechromancer Jul 16, 2025
bbe7017
Fix API Endpoint param.
ausmaster Jul 17, 2025
f5dee34
Merge pull request #64 from blacklanternsecurity/fix-cancelscan-signa…
TheTechromancer Jul 17, 2025
de82dc8
fix test
TheTechromancer Jul 17, 2025
5ee3bbe
ruffed
TheTechromancer Jul 17, 2025
80d1a21
better authentication
TheTechromancer Jul 17, 2025
ade99fe
Merge pull request #55 from blacklanternsecurity/tech-improvements
TheTechromancer Jul 17, 2025
051118c
improve tests
TheTechromancer Jul 17, 2025
d35b21d
ruffed
TheTechromancer Jul 17, 2025
2a9dc92
more stable tests
TheTechromancer Jul 17, 2025
c9c4815
ruffed
TheTechromancer Jul 17, 2025
ed804b2
ruffed
TheTechromancer Jul 17, 2025
26cae88
ruffed
TheTechromancer Jul 18, 2025
7199895
Merge pull request #57 from bWlrYQ/fix-target-id-filtering
TheTechromancer Jul 21, 2025
45775f0
fix uuids
TheTechromancer Jul 28, 2025
2edc90b
ruffed
TheTechromancer Jul 28, 2025
48b2e08
ruffed
TheTechromancer Jul 28, 2025
84d3148
Merge pull request #66 from blacklanternsecurity/uuid-fix
TheTechromancer Jul 28, 2025
8296494
better filtering by target
TheTechromancer Jul 29, 2025
7e2025a
technology summarization, lots of tests
TheTechromancer Jul 30, 2025
1fc78c4
cleanup
TheTechromancer Jul 30, 2025
88eb3ad
Merge pull request #67 from blacklanternsecurity/better-target-filtering
TheTechromancer Jul 31, 2025
222e209
Merge branch 'dev' into misc-fixes
TheTechromancer Jul 31, 2025
6f7d042
fix preset merge order
TheTechromancer Jul 31, 2025
48354db
fix .gz cleartext log
TheTechromancer Jul 31, 2025
56addb0
fix async generator bug with | head, associate activities with scans
TheTechromancer Jul 31, 2025
55ae89d
Merge pull request #68 from blacklanternsecurity/misc-fixes
TheTechromancer Oct 3, 2025
8e530dc
todo
TheTechromancer Oct 8, 2025
31f8bd3
asset querying
TheTechromancer Oct 8, 2025
c7357d6
query endpoint
TheTechromancer Oct 8, 2025
9441b30
ruffed
TheTechromancer Oct 8, 2025
434e8a2
better tests
TheTechromancer Oct 8, 2025
e64f7c4
If type and host are set in the MongoDB query, do not override them.
ausmaster Oct 9, 2025
1d4e244
Oopsies.
ausmaster Oct 9, 2025
fe6b3d6
Merge pull request #71 from blacklanternsecurity/fix-findings-querying
TheTechromancer Oct 10, 2025
70a6f03
aggregation
TheTechromancer Oct 11, 2025
c05bc55
more querying
TheTechromancer Oct 14, 2025
5d2eb96
no self hosted
TheTechromancer Oct 14, 2025
19ca143
fix tests
TheTechromancer Oct 14, 2025
7295efc
querying reorg
TheTechromancer Oct 14, 2025
0cacb14
fix tests
TheTechromancer Oct 14, 2025
031e390
tests and things
TheTechromancer Oct 15, 2025
6c4507d
cleanup
TheTechromancer Oct 15, 2025
e4a2173
no cloud test
TheTechromancer Oct 15, 2025
73ed73e
typing
TheTechromancer Oct 16, 2025
df6c4dc
typing
TheTechromancer Oct 16, 2025
e6444d1
delete lots of code
TheTechromancer Oct 16, 2025
0314974
wip tests passing
TheTechromancer Oct 16, 2025
3d98c88
cloud providers
TheTechromancer Oct 17, 2025
f0015c9
Merge pull request #73 from blacklanternsecurity/event-reorg
TheTechromancer Oct 17, 2025
fbad63c
fix conflict
TheTechromancer Oct 17, 2025
178e7d4
limit, skip
TheTechromancer Oct 17, 2025
b7909e9
add pagination tests
TheTechromancer Oct 17, 2025
733cb49
Merge pull request #70 from blacklanternsecurity/better-asset-querying
ausmaster Oct 17, 2025
8f2cd17
query improvements
TheTechromancer Oct 21, 2025
3d5d7ef
ruffed
TheTechromancer Oct 21, 2025
a528351
fix log
TheTechromancer Oct 21, 2025
13d7749
Merge pull request #74 from blacklanternsecurity/better-asset-querying
ausmaster Oct 21, 2025
c417037
count endpoints, tests
TheTechromancer Oct 23, 2025
3420b7e
sig
TheTechromancer Oct 23, 2025
9df09e2
Merge pull request #76 from blacklanternsecurity/count-endpoints
ausmaster Oct 23, 2025
d5425b0
chore: doc config typo and indentation
TrebledJ Oct 30, 2025
b9a962a
host parts
TheTechromancer Oct 30, 2025
776abb6
tests
TheTechromancer Oct 30, 2025
c8254f5
more tests
TheTechromancer Oct 30, 2025
2a2d298
disable cloud provider functionality until such a time as it is actua…
TheTechromancer Oct 30, 2025
2e46051
Merge pull request #81 from blacklanternsecurity/host-parts
TheTechromancer Oct 30, 2025
7aca66b
Merge pull request #79 from TrebledJ/en/doc
TheTechromancer Oct 31, 2025
c94300d
re.escape domain
TheTechromancer Oct 31, 2025
63023fb
Merge pull request #82 from blacklanternsecurity/host-parts
TheTechromancer Oct 31, 2025
b22337b
better search
TheTechromancer Nov 3, 2025
17379c0
Merge pull request #85 from blacklanternsecurity/better-search
TheTechromancer Nov 4, 2025
52c7ace
fix re escape bug
TheTechromancer Nov 5, 2025
05ff026
Update base.py
TheTechromancer Nov 5, 2025
3e25ccc
Update base.py
TheTechromancer Nov 5, 2025
fb8373a
Merge pull request #86 from blacklanternsecurity/better-search
ausmaster Nov 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ concurrency:

jobs:
docker-test:
runs-on: self-hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ concurrency:

jobs:
test:
runs-on: self-hosted
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -42,7 +42,7 @@ jobs:
poetry run ruff format --check
- name: Run tests
run: |
NO_COLOR=true poetry run pytest --disable-warnings --log-cli-level=INFO --cov-report xml:cov.xml --cov=bbot_server .
NO_COLOR=true poetry run pytest --reruns 2 --disable-warnings --log-cli-level=INFO --cov-report xml:cov.xml --cov=bbot_server .
- name: Upload Code Coverage
uses: codecov/codecov-action@v3
with:
Expand Down
122 changes: 95 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,45 +136,48 @@ To start a scan in BBOT server, you need to first create a **Preset** and **Targ

1. Create Preset

The preset defines which flags, modules, API keys, etc. will be used for the scan. It typically looks something like this:
The preset defines which flags, modules, API keys, etc. will be used for the scan. It typically looks something like this:

**`my_preset.yml`**:
```yaml
include:
- subdomain-enum
- cloud-enum
- code-enum
**`my_preset.yml`**:
```yaml
include:
- subdomain-enum
- cloud-enum
- code-enum

modules:
- nuclei
modules:
- nuclei

config:
- virustotal:
api_key: deadbeef
```
config:
modules:
virustotal:
api_key: deadbeef
```

```bash
# create a new scan preset
bbctl scan preset create my_preset.yml
```
```bash
# create a new scan preset
bbctl scan preset create my_preset.yml
```

For more guidance and examples on presets, check out the [bbot docs](https://www.blacklanternsecurity.com/bbot/Stable/scanning/presets/).

2. Create Target

A target defines what's in-scope for the scan. They can also be used when filtering assets.
A target defines what's in-scope for the scan. They can also be used when filtering assets.

```bash
# create a new scan target
bbctl scan target create --seeds evilcorp.txt --name "my_target"
```
```bash
# create a new scan target
bbctl scan target create --seeds evilcorp.txt --name "my_target"
```

3. Start Scan

Now that we've created a preset and target, we can start the scan:
Now that we've created a preset and target, we can start the scan:

```bash
# start the scan
bbctl scan start --preset my_preset --target my_target --name "demonic_jimmy"
```
```bash
# start the scan
bbctl scan start --preset my_preset --target my_target --name "demonic_jimmy"
```

## Monitor scan progress

Expand Down Expand Up @@ -325,6 +328,71 @@ The SSE server listens at `http://localhost:8807/v1/mcp/`

After connecting your AI client to BBOT Server, you can ask it sensible questions like, "Use MCP to get all the bbot findings", "what are the top open ports?", "what else can you do with BBOT MCP?", etc.

## As a Python Library

You can interact fully with BBOT Server as a Python library. It supports either local or remote connections, and the interface to both is identical:

### Asynchronous

```python
import asyncio
from bbot_server import BBOTServer

async def main():
# talk directly to local MongoDB + Redis
bbot_server = BBOTServer(interface="python")

# or to a remote BBOT Server instance (config must contain a valid API key)
bbot_server = BBOTServer(interface="http", url="http://bbot:8807/v1/")

# one-time setup
await bbot_server.setup()

hosts = await bbot_server.get_hosts()
print(f"hosts: {hosts}")

if __name__ == "__main__":
asyncio.run(main())
```

### Synchronous

```python
from bbot_server import BBOTServer

if __name__ == "__main__":
# talk directly to local MongoDB + Redis
bbot_server = BBOTServer(interface="python", synchronous=True)

# or to a remote BBOT Server instance (config must contain a valid API key)
bbot_server = BBOTServer(interface="http", url="http://bbot:8807/v1/", synchronous=True)

# one-time setup
bbot_server.setup()

hosts = bbot_server.get_hosts()
print(f"hosts: {hosts}")
```

## Running Tests

When running tests, first start MongoDB and Redis via Docker:

```bash
docker run --rm -p 27017:27017 mongo
docker run --rm -p 6379:6379 redis
```

Then execute `pytest`:

```bash
# run all tests
poetry run pytest -v

# run specific tests
poetry run pytest -v -k test_applet_scans
```

## Screenshots

*Tailing activities in real time*
Expand Down
3 changes: 2 additions & 1 deletion bbot_server/api/mcp.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import logging
from fastapi_mcp import FastApiMCP

MCP_ENDPOINTS = {}

log = logging.getLogger("bbot_server.api.mcp")


def make_mcp_server(fastapi_app, config, mcp_endpoints=None):
from fastapi_mcp import FastApiMCP

if mcp_endpoints is None:
mcp_endpoints = MCP_ENDPOINTS
log.debug(f"Creating MCP server with endpoints: {','.join(mcp_endpoints)}")
Expand Down
18 changes: 4 additions & 14 deletions bbot_server/applets/_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
class RootApplet(BaseApplet):
name = "Root Applet"

attach_to = ""

_nested = False

_route_prefix = ""
Expand All @@ -28,26 +26,18 @@ async def setup(self):
if self.is_native:
# set up asset store, user store, and gridfs buckets
if self.asset_store is None:
from bbot_server.store.user_store import UserStore
from bbot_server.store.asset_store import AssetStore
from bbot_server.store import UserStore, AssetStore, EventStore

self.asset_store = AssetStore()
await self.asset_store.setup()
self.asset_db = self.asset_store.db
self.asset_fs = self.asset_store.fs

self.user_store = UserStore()
await self.user_store.setup()
self.user_db = self.user_store.db
self.user_fs = self.user_store.fs

# set up event store
from bbot_server.event_store import EventStore

self.event_store = EventStore()
await self.event_store.setup()
self.event_store = EventStore()
await self.event_store.setup()

# set up NATS client
# set up message queue
from bbot_server.message_queue import MessageQueue

self.message_queue = MessageQueue()
Expand Down
2 changes: 1 addition & 1 deletion bbot_server/applets/_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from contextlib import suppress
from fastapi.responses import StreamingResponse
from starlette.websockets import WebSocketDisconnect

import bbot_server.config as bbcfg
from bbot_server.api.mcp import MCP_ENDPOINTS
from bbot_server.utils.misc import smart_encode


log = logging.getLogger("bbot_server.applets.routing")

ROUTE_TYPES = {}
Expand Down
Loading