Jun 18, 2026·6 min read·5 visits
A local symlink-following vulnerability in BBOT's github_workflows module allows an attacker sharing the scan directory to overwrite arbitrary local files when a victim scans a targeted repository.
The github_workflows module in BBOT (Black Lantern Security OSINT framework) versions 2.0.0 through 2.8.4 constructs local directory paths from user-controlled repository and owner names without validating for symbolic links. A local attacker sharing the scan directory can pre-plant a symlink at the predictable output path, forcing BBOT to write downloaded workflow artifacts or run logs to an arbitrary location on the filesystem.
BBOT is an active OSINT and reconnaissance framework used to gather threat intelligence and map external attack surfaces. The github_workflows module within BBOT retrieves workflow run logs and artifacts from a target GitHub repository. This functionality is exposed to the local filesystem through automatic directory creation and file storage procedures.
To store these gathered resources locally, the module organizes downloads based on the target repository owner and repository name. Because these names are determined dynamically during a scan, they serve as user-controlled variables. When configuring directories to save these files, the framework relies on path construction techniques that do not verify the underlying file types.
This lack of verification introduces an attack surface classified as CWE-59: Improper Link Resolution Before File Access ('Link Following'). A local adversary who has write access to the shared scan directory or a predictable public path (e.g., /tmp) can create symbolic links targeting sensitive system resources. When the victim initiates a scan, the framework resolves these links blindly, allowing arbitrary file writes to occur.
The root cause of CVE-2026-12567 lies in the omission of path-sanitization checks prior to invoking directory creation and file-write calls. Specifically, the framework constructs target paths by joining a trusted base directory with variables retrieved from GitHub API responses or user configurations.
The vulnerable execution flow follows this sequence:
folder = self.output_dir / owner / repo
self.helpers.mkdir(folder)
file_destination = folder / filenameThe self.helpers.mkdir utility creates the requested folder structure recursively. However, it fails to verify whether any intermediate directory component (such as owner or repo) is an existing symbolic link pointing outside the designated output_dir boundary.
By leveraging this behavioral gap, a local attacker can exploit predictable paths. Because the framework organizes output directories using the format {output_dir}/{owner}/{repo}, the exact layout of the target directory is known beforehand. This allows the pre-creation of symlinks that route the eventual file creation payloads toward sensitive locations, bypassing normal filesystem organizational limits.
In BBOT versions prior to 2.8.5, paths were created directly using the pathlib division operator without path-element inspection. The fix introduced in commit 16d9c42b6c591c07ee94d260cb0588e72d4eae2b mitigates this weakness by recursively inspecting each subdirectory component starting from the safe base path.
Below is the comparison between the vulnerable and patched file operations:
# Vulnerable Path construction (bbot/modules/github_workflows.py)
async def download_run_logs(self, owner, repo, run_id):
folder = self.output_dir / owner / repo
self.helpers.mkdir(folder) # Vulnerable: Creates path recursively without link checks
filename = f"run_{run_id}.zip"
file_destination = folder / filenameThe patch introduces the _check_output_path helper function to validate path components individually:
# Patched Implementation (bbot/modules/github_workflows.py)
def _check_output_path(self, folder):
try:
# Ensure the target folder is a child of the output_dir
rel = folder.relative_to(self.output_dir)
except ValueError:
return False
current = self.output_dir
# Walk down the relative components and verify none are symlinks
for part in rel.parts:
current = current / part
if current.is_symlink():
self.warning(f"Refusing to write through symlink: {current}")
return False
return TrueWhile this fix successfully blocks basic symlink redirection, a critical analysis reveals two limitations:
Time-of-Check to Time-of-Use (TOCTOU): The framework performs the validation in Python before invoking the mkdir and file-write commands. In an active, multi-user shared filesystem, an attacker could monitor directory modifications. Using tools like inotify, the attacker can swap the verified directory with a symlink immediately after _check_output_path returns True but before the write operation finishes.
Unchecked Base Directory: The validation assumes self.output_dir itself is secure and not a symlink. If the parent or base scan output directory is compromised, the logic can be subverted.
Hardlink Attacks: The check depends on is_symlink(), which ignores hardlinks. If hardlink protection (fs.protected_hardlinks) is not enabled at the operating system level, an attacker might still attempt link attacks on files sharing the same physical partition.
To successfully execute a symlink attack against a BBOT instance using the github_workflows module, the following conditions must be met:
/tmp or a shared group folder.The attack flow is visualized below:
An attacker begins by pre-creating the target directory structure. For example, if the victim is expected to scan a repository named testrepo owned by testowner, the attacker constructs the path inside the target scan folder:
mkdir -p /tmp/bbot_output/testowner
ln -s /home/victim/.ssh/authorized_keys /tmp/bbot_output/testowner/testrepoWhen the victim runs BBOT, the module queries the GitHub API, retrieves run logs, and writes them to the target destination. Because the symlink points to /home/victim/.ssh/authorized_keys, the written data (in this case, compressed zip logs or text log formats) is directed into the SSH configuration file, corrupting it or appending uncontrolled text.
The impact of CVE-2026-12567 is limited compared to remote code execution bugs, resulting in a CVSS v3.1 score of 2.2 (Low). The vector breakdown is CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:N/I:L/A:N.
The attack vector is restricted to local system access (AV:L), and requires high attack complexity (AC:H) due to the timing and naming coordination required. The attacker must anticipate the exact GitHub repository and owner configuration targeted by the victim.
While the integrity impact is rated Low (I:L), successful exploitation results in writing user-controlled GitHub artifacts and logs into administrative or target files. An attacker could overwrite configuration files, system scripts, or security keys. This could potentially disrupt local services or allow the attacker to manipulate environmental variables or access credentials in subsequent phases of an intrusion.
CVSS:3.1/AV:L/AC:H/PR:L/UI:R/S:U/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
BBOT Black Lantern Security | >= 2.0.0, <= 2.8.4 | 2.8.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-59 |
| Attack Vector | Local |
| CVSS v3.1 Score | 2.2 |
| EPSS Score | 0.0009 (Percentile: 0.60%) |
| Impact | Low Integrity Impact (Unsanitized local file write) |
| Exploit Status | Proof of Concept (PoC) available in official test suite |
| KEV Status | Not listed in CISA KEV |
The software attempts to access a file based on a filename, but it does not properly associate the name with the intended file entity, which can allow an attacker to substitute a different file (e.g. via symbolic links).
CVE-2026-12565 is a medium-severity path traversal (Zip-Slip) vulnerability within the internal unarchive module of the BBOT (Black Lantern Security) OSINT framework. The vulnerability exists due to a failure to validate target paths before extracting archives using host-level command-line utilities. This allows remote, unauthenticated attackers to write arbitrary files outside of the target extraction folder on environments running legacy versions of GNU tar.
A Server-Side Request Forgery (SSRF) vulnerability exists in the docker_pull module of Black Lantern Security BBOT. By returning a maliciously crafted WWW-Authenticate header from a rogue Docker registry or executing a Man-in-the-Middle (MitM) attack, an attacker can coerce the BBOT scanner into making arbitrary HTTP requests to internal system services or external infrastructure, potentially disclosing sensitive authorization tokens and host metadata.
CVE-2026-12568 is a path traversal vulnerability (CWE-22) in the postman_download module of BBOT (Babbage Border Obsession Tool) version 2.1.0 through 2.8.5. The vulnerability allows an attacker to perform arbitrary file writes on the local machine running the BBOT scan via a maliciously named remote Postman workspace.
An unauthenticated remote memory exhaustion vulnerability in the JLine3 Telnet server allows attackers to crash the host Java Virtual Machine (JVM). The flaw exists in the processing of the NEW-ENVIRON option, where the server accepts an arbitrary number of environment variables without limits, storing them in an unconstrained HashMap. Sending as little as 3.25 MB of payload data can exhaust a standard JVM heap and trigger an OutOfMemoryError. This vulnerability affects applications integrating the remote-telnet module of JLine3.
CVE-2026-49975 describes a high-severity remote Denial of Service (DoS) vulnerability in the Apache HTTP Server's mod_http2 module. Unauthenticated attackers can exploit the HPACK compression and cookie-merging behavior to trigger severe, quadratic memory allocation. This resource exhaustion is maintained by manipulating the HTTP/2 flow-control window, ultimately forcing an Out-of-Memory condition on the server host.
CVE-2026-5038 is a critical denial of service vulnerability in the Node.js Multer middleware. When utilizing the diskStorage engine, connection termination or validation failures leave partial files orphaned on the local filesystem due to stream-destruction signal propagation failures in Node's piping mechanism. Remote unauthenticated attackers can exploit this to fill server disks and induce system crashes.