BBOT
Purpose
Ingests completed BBOT JSON scans into SubImage. BBOT discovers internet-facing assets and security findings; SubImage reads the report and correlates those observations with the rest of the graph.
SubImage does not run BBOT or hold its scan credentials. Run the open-source scanner in infrastructure you control, against targets you are authorized to assess, and publish its output.json to Amazon S3, Google Cloud Storage, or Azure Blob Storage.
Required Fields
| Field | Description |
|---|---|
bbot_source |
Cloud prefix containing reports: s3://bucket/bbot/, gs://bucket/bbot/, or azblob://account/container/bbot/. |
bbot_aws_account_id |
12-digit AWS account ID that owns the report bucket. Required only when bbot_source uses S3; GCS and Azure reuse their corresponding SubImage integrations. |
Setup Steps
1. Grant read access
Choose the provider that owns the report bucket.
Amazon S3
Create the BBOT report-reader role in the bucket's AWS account. The default role name is SubImageBbotRole; your SubImage deployment can configure a different name. The role must trust your tenant's SubImage role with the tenant-specific external ID subimage-bbot- and have only <TENANT_ID>s3:ListBucket and s3:GetObject access to the configured prefix.
This CloudFormation example expects the report at bbot/output.json:
AWSTemplateFormatVersion: "2010-09-09"
Description: Read-only BBOT report access for SubImage
Resources:
SubImageBbotRole:
Type: AWS::IAM::Role
Properties:
RoleName: SubImageBbotRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: arn:aws:iam::<ACCOUNT_ID>:role/<TENANT_ID>-subimage-readonly
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: subimage-bbot-<TENANT_ID>
Policies:
- PolicyName: ReadBbotReports
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: ListBbotReports
Effect: Allow
Action: s3:ListBucket
Resource: arn:aws:s3:::{{BUCKET_NAME}}
Condition:
StringLike:
s3:prefix: bbot/*
- Sid: ReadBbotReports
Effect: Allow
Action: s3:GetObject
Resource: arn:aws:s3:::{{BUCKET_NAME}}/bbot/*If the bucket uses a customer-managed KMS key, also grant this role kms:Decrypt on that key.
Google Cloud Storage
Configure the GCP integration in Modules first. BBOT reuses its service account or Workload Identity Federation credentials. Grant that principal roles/storage.objectViewer on the report bucket.
Azure Blob Storage
Configure the Azure integration in Modules first. BBOT reuses its service principal. Grant that principal Storage Blob Data Reader on the report container.
2. Run BBOT and publish the completed report
BBOT supports pipx and Docker. The smallest scheduled runner is a shell script invoked by cron, systemd, or your existing job platform:
#!/bin/sh
set -eu
output_dir=$(mktemp -d)
trap 'rm -rf "$output_dir"' EXIT
bbot -t example.com -p subdomain-enum -n subimage -o "$output_dir" -y
aws s3 cp \
"$output_dir/subimage/output.json" \
s3://{{BUCKET_NAME}}/bbot/output.json \
--only-show-errorsReplace the final upload command with gcloud storage cp or az storage blob upload when using GCS or Azure Blob Storage. Keep scan API keys in BBOT's own secrets file or your job platform's secret store, not in the script.
Upload only after BBOT exits successfully. Replacing output.json keeps each SubImage sync constant-cost. If you need report history, copy reports to a separate archive prefix; do not place an unbounded archive under the configured ingestion prefix.
3. Enable BBOT in SubImage
- In Modules → BBOT, set
bbot_sourceto the provider URI for your report prefix. - For S3 only, set
bbot_aws_account_idto the bucket owner's AWS account ID. - Save the module and run a sync.
Cartography validates the scan's own completion event and selects the newest completed scan under the prefix. No date-based filename is required. Incomplete scans are ignored, and a report read or parse failure preserves the previously ingested graph snapshot.
Troubleshooting
- S3 AssumeRole failed — verify the configured role name, tenant principal ARN, external ID, and AWS account ID.
- GCS access failed — verify the GCP module is enabled and its principal has
roles/storage.objectVieweron the bucket. - Azure Blob access failed — verify the Azure module is enabled and its service principal has Storage Blob Data Reader on the container.
- No completed BBOT report — confirm the object is named
.jsonor.jsonland contains a finalSCANevent with statusFINISHED.