Summary
when running [[Blint]] sbom --src . --stdout on Linux specifically it’ll crash giving a specific runtime report about a TypeError: expected str, bytes or os.PathLike object, not TextIOWrapper.
This error indicates that you’re trying to use a string method or an operation (like —stdout) that expects a file path on a file object.
Steps to reproduce
- Run
[[Blint]] sbom --src . --stdouton any binary (C, Rust, Go, Windows etc (i did test it on windows exe since i use virtualboxes)) - Observe the generated error
Traceback (most recent call last):
File "/home/bay/Developer/test_c/blint-py/bin/blint", line 6, in <module>
sys.exit(main())
~~~~^^
File "/home/bay/Developer/test_c/blint/blint/cli.py", line 255, in main
run_sbom_mode(blint_options)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^
File "/home/bay/Developer/test_c/blint/blint/lib/runners.py", line 45, in run_sbom_mode
return generate(blint_options, exe_files, android_files)
File "/home/bay/Developer/test_c/blint/blint/lib/sbom.py", line 172, in generate
return create_sbom(
components,
...<4 lines>...
symbols_purl_map,
)
File "/home/bay/Developer/test_c/blint/blint/lib/sbom.py", line 205, in create_sbom
output_dir = os.path.split(output_file)[0]
~~~~~~~~~~~~~^^^^^^^^^^^^^
File "<frozen posixpath>", line 103, in split
TypeError: expected str, bytes or os.PathLike object, not TextIOWrapperRoot cause
in sbom.py, the following function create_sbom
# line 203 of sbom.py
def create_sbom(
components: list[Component],
dependencies: list[dict],
output_file: str,
sbom: CycloneDX,
deep_mode: bool,
symbols_purl_map: dict,
) -> CycloneDX:
output_dir = os.path.split(output_file)[0]
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Populate the components
sbom.components = trim_components(components)
# If we have only one parent component then promote it to metadata.component
if sbom.metadata.component.components:
if len(sbom.metadata.component.components) == 1:
sbom.metadata.component = sbom.metadata.component.components[0]
else:
root_depends_on = [
ac.bom_ref.model_dump(mode="python")
for ac in sbom.metadata.component.components
]
dependencies.append(
{
"ref": sbom.metadata.component.bom_ref.model_dump(mode="python"),
"dependsOn": root_depends_on,
}
)
# Populate the dependencies
sbom.dependencies = dependencies
LOG.debug(
f"SBOM includes {len(sbom.components)} components and {len(sbom.dependencies)} dependencies"
)
file_write(
output_file,
sbom.model_dump_json(
indent=None if deep_mode else 2,
exclude_none=True,
exclude_defaults=True,
warnings=False,
by_alias=True,
),
log=LOG,
)
return sbom
- The issue lies within the function handling and assuming the output_file is a string.
- when running with —stdout flag enabled, if you print the current contents it shows this
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
Solution
I’ve made a fork of the project that can be accessed here: betim - blint
The update I’ve made changes the function a bit and adds a new import sys into sbom.py.
Instead of assuming the filename to be a string, we first just populate our sbom content variable., then populate the dependencies.
After that we check if the output_file is set to stdout, if it is, we just print to the terminal with print(). else we go on normally and create our custom named sbom.json object
if output_file is sys.stdout:
print(sbom.model_dump_json(indent=2, exclude_none=True, exclude_defaults=True, warnings=False, by_alias=True))
else:
output_dir = os.path.split(output_file)[0]
if not os.path.exists(output_dir):
os.makedirs(output_dir)
file_write(
output_file,
sbom.model_dump_json(
indent=None if deep_mode else 2,
exclude_none=True,
exclude_defaults=True,
warnings=False,
by_alias=True,
),
log=LOG,
)
return sbom
as I’m inspecting this, the -o and --output-file isn’t working either (will be a seperate issue)
Result after Fix
with updating the program, you can see it prints out the sbom in stdout, this will be useful with other unix-like command line utilities.

- (note in final PR the io.TextIOWrapper will not appear (it’s a print statement) I’ve also tested it with various binaries to ensure nothing was broken in the process of this:
- PE (dll, x86, x64, dotnet)
- Go
- Rust