Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
213 commits
Select commit Hold shift + click to select a range
2516013
feat(sbom): build fs_tree from installPath and track filesystem symlinks
willis89pr Jul 17, 2025
5b60e7b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 17, 2025
1b4e496
Disable pylint W0621 (redefined-outer-name) in test files
willis89pr Jul 24, 2025
2324471
Merge.
willis89pr Jul 24, 2025
3bf77b7
Merge.
willis89pr Jul 24, 2025
45c1d1c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
8e8ff11
Add detailed docstring and safety checks to _add_software_to_fs_tree
willis89pr Jul 24, 2025
1a1f518
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
e9e8fad
feat(fs): unify path normalization via utility in SBOM and dotnet_rel…
willis89pr Jul 24, 2025
c3dffdf
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
d696606
fix(utils): normalize_path handles backslashes consistently
willis89pr Jul 24, 2025
cc5e19b
Merge.
willis89pr Jul 24, 2025
ffaab6b
fix(dotnet): normalize all probe paths for consistent assembly resolu…
willis89pr Jul 24, 2025
845b539
Add regressions.py back in
willis89pr Jul 24, 2025
d02cdaf
test(relationships): record symlink mapping and add edge-case symlink…
willis89pr Jul 24, 2025
2d12cc9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
b1b587a
fix(tests): correct _record_symlink usage in ELF relationship test an…
willis89pr Jul 24, 2025
37b334a
Merge.
willis89pr Jul 24, 2025
7a3ae62
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
e4a7381
fix(tests): prevent NetworkXError in symlink heuristic test by condit…
willis89pr Jul 24, 2025
fcb52ef
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 24, 2025
2c8666c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
f3395ae
refactor(pe_relationship): migrate to fs_tree resolution with fallbac…
willis89pr Jul 24, 2025
ca00c1a
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 24, 2025
d34e3d5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
4c53b43
test(pe_relationship): add unit tests for PE relationship resolution
willis89pr Jul 24, 2025
96bafaa
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 24, 2025
8ead00e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
6348cfe
refactor(java_relationship): adopt 3-phase resolution strategy and ad…
willis89pr Jul 24, 2025
cd5335b
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 24, 2025
0e15887
test(pe_relationship): suppress pylint warning for redefined-outer-name
willis89pr Jul 24, 2025
d5e7b3a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 24, 2025
eb558d5
fix(java_relationship): clean up pylint warnings and naming conflicts
willis89pr Jul 24, 2025
a8f20f6
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 24, 2025
fc6bef5
fix(pe_relationship): prevent self-referencing relationships in depen…
willis89pr Jul 24, 2025
ac38ce2
refactor(dotnet_relationship): unify .NET resolution phases and add c…
willis89pr Jul 25, 2025
ecf2573
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
f62719e
fix(dotnet_relationship): resolve lint violations and improve closure…
willis89pr Jul 25, 2025
bdb8ebc
Merge.
willis89pr Jul 25, 2025
73c5a5f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
bebd5b7
chore(test_java_relationship): suppress pytest fixture redefinition w…
willis89pr Jul 25, 2025
526a044
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 25, 2025
0c0b794
test(dotnet_relationship): fix fixture name and ensure plugin executi…
willis89pr Jul 25, 2025
ef3b369
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
75bdcc5
test(dotnet_relationship): fix probe path for unmanaged import resolu…
willis89pr Jul 25, 2025
d75c9ad
Merge.
willis89pr Jul 25, 2025
4d8feaa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
9196133
test(elf_relationship): fix system path test to avoid self-dependency
willis89pr Jul 25, 2025
2ab8eed
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 25, 2025
d0fc1b3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
61f80fa
test(pe_relationship): fix symlink heuristic test and remove legacy J…
willis89pr Jul 25, 2025
9cbcce7
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 25, 2025
4189274
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
2f78161
test(pe_relationship): align DLL installPath with binary probe path f…
willis89pr Jul 25, 2025
a17d90b
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Jul 25, 2025
6cfc308
Add symlink support and debug logging to CycloneDX writer
willis89pr Jul 25, 2025
09457f7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2025
f6a783e
Merge branch 'main' into fstree
willis89pr Jul 25, 2025
c445824
Revert changes in output writers
willis89pr Aug 8, 2025
eefe217
Merge.
willis89pr Aug 8, 2025
84ce9c8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 8, 2025
969db61
Merge branch 'main' into fstree
willis89pr Aug 8, 2025
092cb1e
SBOM: Enhance get_software_by_path() to support symlink traversal via…
willis89pr Aug 8, 2025
06f2b86
SBOM: Refactor _record_symlink() to add node metadata and enforce ide…
willis89pr Aug 8, 2025
8344f39
SBOM: Add _rebuild_symlink_edges() to restore symlink relationships a…
willis89pr Aug 8, 2025
280b24b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 8, 2025
ce214af
SBOM: Remove _rebuild_symlink_edges() and post-init call due to host …
willis89pr Aug 11, 2025
6705054
Merge.
willis89pr Aug 11, 2025
383eae9
Merge branch 'main' into fstree
willis89pr Aug 11, 2025
088807a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 11, 2025
d4589f8
SBOM: Remove redundant local import of normalize_path in _record_syml…
willis89pr Aug 11, 2025
75fecf9
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Aug 11, 2025
ddd4739
generate/merge/_sbom/elf_relationship: Refactor symlink handling, swi…
willis89pr Aug 13, 2025
3c68ec9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2025
60a82e2
generate: improve fs_tree target discovery for symlink metadata synth…
willis89pr Aug 13, 2025
d7f1144
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Aug 13, 2025
c3ef46d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2025
762ddc9
generate: normalize target node lookups in fs_tree symlink metadata s…
willis89pr Aug 13, 2025
b7ab817
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Aug 13, 2025
21a0579
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2025
bb0c2a7
dotnet_relationship: standardize and enhance debug logging for relati…
willis89pr Aug 13, 2025
0174f84
elf_relationship: standardize debug logging and clarify match phases
willis89pr Aug 13, 2025
187b6d0
java_relationship: standardize debug logging and clarify resolution p…
willis89pr Aug 13, 2025
01ca3f3
pe_relationship: standardize debug logging and clarify match phases
willis89pr Aug 13, 2025
2855551
Merge branch 'fstree' of https://github.com/LLNL/Surfactant into fstree
willis89pr Aug 13, 2025
2cad38d
Merge branch 'main' into fstree
willis89pr Aug 13, 2025
4c571d1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 13, 2025
4513d61
Merge branch 'main' into fstree
willis89pr Aug 21, 2025
cc01239
fix(lint): resolve Ruff and Pylint issues in generate.py
willis89pr Aug 21, 2025
bce82f5
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Aug 21, 2025
62b91dc
feat(sbom): add public symlink API; refactor generate to use it
willis89pr Aug 21, 2025
3bac275
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 21, 2025
0007804
refactor(paths): add basename_posix and use it to remove broad except…
willis89pr Aug 21, 2025
e18739e
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Aug 21, 2025
08bc50e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 21, 2025
02171dd
Merge branch 'main' into fstree
willis89pr Aug 26, 2025
cec7883
Merge branch 'main' into fstree
willis89pr Aug 28, 2025
b6c21ea
chore(gitignore): remove temporary debugging files from ignore list
willis89pr Aug 29, 2025
425c527
test(pe_relationship): correct DLL installPath and clarify fs_tree usage
willis89pr Aug 29, 2025
930692d
test(relationships): clean up and clarify .NET, ELF, Java, and PE tes…
willis89pr Aug 29, 2025
cb3ed1f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 29, 2025
1a79d67
test(fs_tree): expand coverage for path normalization, symlink traver…
willis89pr Aug 29, 2025
40c525a
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Aug 29, 2025
84c7570
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 29, 2025
d4d5ce6
fix(fs_tree): switch to deque BFS with depth cap in get_software_by_path
willis89pr Aug 29, 2025
cd89969
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Aug 29, 2025
3a4e5f5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 29, 2025
5a91ed7
fix(fs_tree): always enqueue (node, depth) tuples in BFS
willis89pr Aug 29, 2025
9029ffc
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Aug 29, 2025
a393def
fix(tests): make Windows-path docstring raw to silence pylint W1401
willis89pr Aug 29, 2025
ecee483
Merge branch 'main' into fstree
willis89pr Sep 15, 2025
5521c17
fix(generate): walk symlinked directories and modernize logging
willis89pr Sep 16, 2025
ae78f9c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 16, 2025
63d6423
Merge branch 'main' into fstree
willis89pr Sep 26, 2025
0ca1f36
fix(resolve_link): rewrite symlink resolution with pathlib and better…
willis89pr Sep 30, 2025
9ea43a9
test(resolve_link): add pytest suite for symlink resolution
willis89pr Sep 30, 2025
fffe094
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 30, 2025
1504b31
Removed debugging file
willis89pr Oct 1, 2025
ee093bf
test(resolve_link): rename fixture to _setup_symlinks and move tests
willis89pr Oct 1, 2025
b644000
Merge branch 'resolve_link' of github.com:LLNL/Surfactant into resolv…
willis89pr Oct 1, 2025
e0b09dc
test(resolve_link): add test for symlink to parent outside extract_dir
willis89pr Oct 1, 2025
24071d2
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 1, 2025
17c68ee
test(resolve_link): correct expectation for symlink to parent
willis89pr Oct 1, 2025
632adc4
Merge branch 'resolve_link' of github.com:LLNL/Surfactant into resolv…
willis89pr Oct 1, 2025
7f62f41
test(resolve_link): normalize absolute symlink comparison on Windows
willis89pr Oct 1, 2025
2b3ed3d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 1, 2025
642883b
test(resolve_link): normalize all path comparisons with Path()
willis89pr Oct 1, 2025
8c3f504
Merge branch 'resolve_link' of github.com:LLNL/Surfactant into resolv…
willis89pr Oct 1, 2025
84fb901
test(resolve_link): normalize absolute symlink test with Path.resolve()
willis89pr Oct 1, 2025
df34efc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 1, 2025
486b06a
fix(resolve_link): improve cycle handling and normalize path comparisons
willis89pr Oct 1, 2025
247a63d
Merge branch 'resolve_link' of github.com:LLNL/Surfactant into resolv…
willis89pr Oct 1, 2025
5022265
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 1, 2025
03bd5b1
test(resolve_link): use samefile() for absolute symlink comparison
willis89pr Oct 1, 2025
2fc6e90
Merge branch 'resolve_link' of github.com:LLNL/Surfactant into resolv…
willis89pr Oct 1, 2025
57da5ae
Merge branch 'resolve_link' into fstree
willis89pr Oct 2, 2025
cf59bf6
fix(generate): correct logger formatting for parent container
willis89pr Oct 2, 2025
57027f7
fix(generate): disable symlink following in SBOM directory walk
willis89pr Oct 8, 2025
d43cdc6
feat(fstree): add deferred symlink expansion for cross-directory link…
willis89pr Oct 9, 2025
46413e6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 9, 2025
b8c8413
feat(symlink): move deferred symlink expansion logic into SBOM helper
willis89pr Oct 9, 2025
8967afd
Merge.
willis89pr Oct 9, 2025
4e39f64
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 9, 2025
f610c2c
feat(symlink): refactor symlink handling and add shared helper for ed…
willis89pr Oct 9, 2025
63e075c
Merge.
willis89pr Oct 9, 2025
fedd24f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 9, 2025
7f82c92
chore(lint): disable Pylint too-many-lines warning in _sbom.py
willis89pr Oct 9, 2025
7101920
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Oct 9, 2025
dce6dcd
Merge branch 'main' into fstree
willis89pr Oct 9, 2025
88c94e2
tests(symlink): remove new resolve_link tests and restore original suite
willis89pr Oct 9, 2025
3d5e0a8
fix(json): exclude _pending_dir_links from SBOM serialization
willis89pr Oct 9, 2025
e0736f2
tests(fs_tree): add test for deferred directory symlink expansion
willis89pr Oct 9, 2025
3401f37
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 9, 2025
818f325
Merge branch 'main' into fstree
willis89pr Oct 14, 2025
19a4122
Merge branch 'main' into fstree
willis89pr Oct 16, 2025
41a93fa
Merge branch 'main' into fstree
willis89pr Oct 27, 2025
171c3e0
Merge branch 'main' into fstree
willis89pr Nov 5, 2025
ca20221
feat(elf_relationship): add detailed ELF loader search order comments…
willis89pr Nov 5, 2025
d5e76c2
refactor(elf_relationship): modernize substitute_all_dst() with prese…
willis89pr Nov 6, 2025
4dde076
docs(pe_relationship, elf_relationship): preserve and integrate legac…
willis89pr Nov 6, 2025
8c4fc1c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 6, 2025
f450b5b
refactor(pe_relationship): remove redundant commented legacy implemen…
willis89pr Nov 6, 2025
7d331cd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 6, 2025
36c4451
docs(sbom): clarify type hints in add_entries docstring
willis89pr Nov 7, 2025
f0df8a6
Merge branch 'main' into fstree
willis89pr Nov 11, 2025
ae6b16e
fix(utils): preserve literal backslashes in PurePosixPath inputs to n…
willis89pr Nov 12, 2025
f486d2a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 12, 2025
907ac25
feat(fs_tree): add hash-equivalence support and symlink metadata inje…
willis89pr Nov 14, 2025
0474fa8
Merge branch 'main' into fstree
willis89pr Nov 14, 2025
1ad20ed
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2025
f620731
Fixed comments
willis89pr Nov 14, 2025
49990f2
fix(fs_tree): bind loop variable in _merge_md to satisfy Ruff B023
willis89pr Nov 14, 2025
06dfe01
style(lint): suppress pylint W0718 for intentional broad exception ha…
willis89pr Nov 14, 2025
cedf529
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2025
3f8572e
style(lint): suppress pylint W0718 for intentional broad exception ha…
willis89pr Nov 14, 2025
09477c0
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Nov 14, 2025
44852d8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 14, 2025
93674f2
style(lint): suppress pylint R0904 for SBOM class
willis89pr Nov 14, 2025
3353e05
Merge branch 'fstree' of github.com:LLNL/Surfactant into fstree
willis89pr Nov 14, 2025
3f3690f
Merge branch 'main' into fstree
willis89pr Nov 17, 2025
2b7d302
Merge branch 'main' into fstree
willis89pr Dec 4, 2025
3a81e17
feat(dotnet): restore absolute-path unmanaged import resolution and a…
willis89pr Dec 5, 2025
c854a41
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 5, 2025
4f2ecd3
Merge branch 'main' into fstree
willis89pr Dec 8, 2025
a266edd
feat(dotnet): add legacy probing patterns, fs_tree resolution, and op…
willis89pr Dec 8, 2025
3d2ea7f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 8, 2025
efff1a6
Merge.
willis89pr Dec 8, 2025
a1df112
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 9, 2025
6f506bb
test(dotnet): replace heuristic-match test with strict basename-match…
willis89pr Dec 9, 2025
e7c215f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 9, 2025
cdb9390
elf_relationship: remove Phase 3 heuristic and improve documentation
willis89pr Dec 9, 2025
bbfbc71
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 9, 2025
ba0be74
tests: update ELF symlink fixture and remove obsolete heuristic tests
willis89pr Dec 9, 2025
8aa1f62
pe_relationship: remove phase 3 heuristic and update documentation/co…
willis89pr Dec 9, 2025
7a55b80
feat(pe): add case-insensitive PE path resolution and tighten legacy …
willis89pr Dec 10, 2025
d9dc148
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2025
61d09be
test(pe): add tests for case-insensitive matching and basename correc…
willis89pr Dec 10, 2025
000c622
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 10, 2025
87a1747
java_relationship: add legacy export-dict phase as backup resolution
willis89pr Dec 11, 2025
b26c590
tests(java_relationship): remove obsolete heuristic match test
willis89pr Dec 11, 2025
3dd8764
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 11, 2025
73036ac
java_relationship: remove unused fname and disable Phase 1 fs_tree re…
willis89pr Dec 11, 2025
72ffa82
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 11, 2025
13c6a87
java_relationship: rebuild export dict per SBOM to prevent state leakage
willis89pr Dec 11, 2025
fcf98ea
fix(dotnet): restore legacy unmanaged absolute-path behavior with gra…
willis89pr Dec 30, 2025
27a39dd
Merge branch 'main' into fstree
willis89pr Dec 30, 2025
f681911
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 30, 2025
91c9fb6
test(dotnet_relationship): align fixtures with legacy probing semantics
willis89pr Dec 30, 2025
53801e7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 30, 2025
b802456
fix(elf): preserve legacy ELF dependency resolution semantics
willis89pr Dec 30, 2025
3dca075
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 30, 2025
8b08c8e
Merge branch 'main' into fstree
willis89pr Jan 7, 2026
302c0d3
Merge branch 'main' into fstree
willis89pr Jan 14, 2026
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,4 @@ $RECYCLE.BIN/
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*
.nfs*
184 changes: 121 additions & 63 deletions surfactant/cmd/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import queue
import re
import sys
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Tuple, Union

import click
from loguru import logger
from networkx.exception import NetworkXError

from surfactant import ContextEntry
from surfactant.cmd.internal.generate_utils import SpecimenContextParamType
Expand Down Expand Up @@ -324,7 +325,7 @@ def sbom(
while not contextQ.empty():
entry: ContextEntry = contextQ.get()
if entry.archive:
logger.info("Processing parent container " + str(entry.archive))
logger.info(f"Processing parent container {entry.archive}")
# TODO: if the parent archive has an info extractor that does unpacking interally, should the children be added to the SBOM?
# current thoughts are (Syft) doesn't provide hash information for a proper SBOM software entry, so exclude these
# extractor plugins meant to unpack files could be okay when used on an "archive", but then extractPaths should be empty
Expand Down Expand Up @@ -419,17 +420,40 @@ def sbom(
user_institution_name=recorded_institution,
container_prefix=entry.containerPrefix,
)
except Exception as e:
except Exception as e: # pylint: disable=broad-exception-caught
raise RuntimeError(f"Unable to process: {filepath}") from e
entries.append(sw_parent)
entries.extend(sw_children if sw_children else [])
# ------------------------------------------------------------------------
# (Optional - Early Injection) Inject symlink paths into each Software entry so SBOM helper handles them
# ------------------------------------------------------------------------
# Early injection: add symlinks gathered so far so fs_tree sees them
for sw in entries:
if sw.fileName is None:
sw.fileName = []
if sw.installPath is None:
sw.installPath = []
# Filename symlinks
for link in filename_symlinks.get(sw.sha256, []):
if link not in sw.fileName:
logger.debug(
f"Injecting filename symlink '{link}' for SHA {sw.sha256}"
)
sw.fileName.append(link)
# Install-path symlinks
for link in file_symlinks.get(sw.sha256, []):
if link not in sw.installPath:
logger.debug(
f"Injecting install-path symlink '{link}' for SHA {sw.sha256}"
)
sw.installPath.append(link)
new_sbom.add_software_entries(entries, parent_entry=parent_entry)
# epath was a file, no need to walk the directory tree
continue

# epath is a directory, walk it
for cdir, dirs, files in os.walk(epath):
logger.info("Processing " + str(cdir))
logger.info(f"Processing {cdir}")

if entry.installPrefix:
for dir_ in dirs:
Expand All @@ -446,8 +470,20 @@ def sbom(
epath.as_posix(), entry.installPrefix, dest
)
dir_symlinks.append((install_source, install_dest))

entries = []
# Reflect in fs_tree immediately
try:
new_sbom.record_symlink(
install_source, install_dest, subtype="directory"
)
logger.debug(
f"[fs_tree] (dir) {install_source} → {install_dest}"
)
except (NetworkXError, ValueError) as e:
logger.warning(
f"Failed to record directory symlink in fs_tree: {install_source} → {install_dest}: {e}"
)

entries: List[Software] = []
for file in files:
# os.path.join will insert an OS specific separator between cdir and f
# need to make sure that separator is a / and not a \ on windows
Expand All @@ -463,6 +499,7 @@ def sbom(
# Dead/infinite links will error so skip them
if true_filepath is None:
continue

# Compute sha256 hash of the file; skip if the file pointed by the symlink can't be opened
try:
true_file_sha256 = sha256sum(true_filepath)
Expand All @@ -471,6 +508,26 @@ def sbom(
f"Unable to open symlink {filepath} pointing to {true_filepath}"
)
continue

# Record both source and target paths under the same hash node
install_filepath = real_path_to_install_path(
epath.as_posix(), entry.installPrefix, filepath
)
install_dest = real_path_to_install_path(
epath.as_posix(), entry.installPrefix, true_filepath
)

try:
new_sbom.record_hash_node(install_filepath, true_file_sha256)
new_sbom.record_hash_node(install_dest, true_file_sha256)
logger.debug(
f"[fs_tree] Linked symlink + target by hash: {install_filepath} ↔ {install_dest}"
)
except Exception as e: # pylint: disable=broad-exception-caught
logger.warning(
f"[fs_tree] Failed to link symlink + target by hash for {filepath}: {e}"
)

# Record the symlink name to be added as a file name
# Dead links would appear as a file, so need to check the true path to see
# if the thing pointed to is a file or a directory
Expand All @@ -496,6 +553,22 @@ def sbom(
file_symlinks[true_file_sha256].append(install_filepath)
else:
dir_symlinks.append((install_filepath, install_dest))

# Reflect this symlink in fs_tree immediately
try:
subtype = (
"file" if os.path.isfile(true_filepath) else "directory"
)
new_sbom.record_symlink(
install_filepath, install_dest, subtype=subtype
)
logger.debug(
f"[fs_tree] ({subtype}) {install_filepath} → {install_dest}"
)
except (NetworkXError, ValueError) as e:
logger.warning(
f"Failed to record symlink in fs_tree: {install_filepath} → {install_dest}: {e}"
)
# NOTE Two cases that don't get recorded (but maybe should?) are:
# 1. If the file pointed to is outside the extract paths, it won't
# appear in the SBOM at all -- is that desirable? If it were included,
Expand All @@ -509,6 +582,8 @@ def sbom(
entry.includeFileExts = []
if not entry.excludeFileExts:
entry.excludeFileExts = []

# file-type identification and SBOM entry creation
if (
(
ftype := pm.hook.identify_file_type(
Expand Down Expand Up @@ -539,69 +614,52 @@ def sbom(
or entry.omitUnrecognizedTypes,
container_prefix=entry.containerPrefix,
)
except Exception as e:
except Exception as e: # pylint: disable=broad-exception-caught
raise RuntimeError(f"Unable to process: {filepath}") from e

entries.append(sw_parent)
entries.extend(sw_children if sw_children else [])
# ------------------------------------------------------------------------
# (Optional - Early Injection) Inject symlink paths into each Software entry so SBOM helper handles them
# ------------------------------------------------------------------------
# Early injection for batch (so fs_tree captures aliases)
for sw in entries:
if sw.fileName is None:
sw.fileName = []
if sw.installPath is None:
sw.installPath = []
# Filename symlinks
for link in filename_symlinks.get(sw.sha256, []):
if link not in sw.fileName:
logger.debug(
f"Injecting filename symlink '{link}' for SHA {sw.sha256}"
)
sw.fileName.append(link)
# Install-path symlinks
for link in file_symlinks.get(sw.sha256, []):
if link not in sw.installPath:
logger.debug(
f"Injecting install-path symlink '{link}' for SHA {sw.sha256}"
)
sw.installPath.append(link)
new_sbom.add_software_entries(entries, parent_entry=parent_entry)

# Add symlinks to install paths and file names
for software in new_sbom.software:
# ensure fileName, installPath, and metadata lists for the software entry have been created
# for a user supplied input SBOM, there are no guarantees
if software.fileName is None:
software.fileName = []
if software.installPath is None:
software.installPath = []
if software.metadata is None:
software.metadata = []
if software.sha256 in filename_symlinks:
filename_symlinks_added = []
for filename in filename_symlinks[software.sha256]:
if filename not in software.fileName:
software.fileName.append(filename)
filename_symlinks_added.append(filename)
if filename_symlinks_added:
# Store information on which file names are symlinks
software.metadata.append({"fileNameSymlinks": filename_symlinks_added})
if software.sha256 in file_symlinks:
symlinks_added = []
for full_path in file_symlinks[software.sha256]:
if full_path not in software.installPath:
software.installPath.append(full_path)
symlinks_added.append(full_path)
if symlinks_added:
# Store information on which install paths are symlinks
software.metadata.append({"installPathSymlinks": symlinks_added})

# Add directory symlink destinations to extract/install paths
for software in new_sbom.software:
# NOTE: this probably doesn't actually add any containerPath symlinks
for paths in (software.containerPath, software.installPath):
if paths is None:
continue
paths_to_add = []
for path in paths:
for link_source, link_dest in dir_symlinks:
if path.startswith(link_dest):
# Replace the matching start with the symlink instead
# We can't use os.path.join here because we end up with absolute paths after
# removing the common start.
paths_to_add.append(path.replace(link_dest, link_source, 1))
if paths_to_add:
found_md_installpathsymlinks = False
# make sure software.metadata list has been initialized
if software.metadata is None:
software.metadata = []
if isinstance(software.metadata, Iterable):
for md in software.metadata:
if isinstance(md, Dict) and "installPathSymlinks" in md:
found_md_installpathsymlinks = True
md["installPathSymlinks"] += paths_to_add
if not found_md_installpathsymlinks:
software.metadata.append({"installPathSymlinks": paths_to_add})
paths += paths_to_add
# ------------------------------------------------------------------
# Expand deferred directory symlinks once fs_tree is fully populated
# ------------------------------------------------------------------
new_sbom.expand_pending_dir_symlinks()

# ------------------------------------------------------------------
# Expand deferred file symlinks after all installPath nodes are added
# ------------------------------------------------------------------
new_sbom.expand_pending_file_symlinks()

# ------------------------------------------------------------------
# Inject legacy-style symlink metadata (fileNameSymlinks and
# installPathSymlinks) derived from fs_tree relationships
# ------------------------------------------------------------------
new_sbom.inject_symlink_metadata()

else:
logger.info("Skipping gathering file metadata and adding software entries")

Expand Down
8 changes: 7 additions & 1 deletion surfactant/cmd/merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ def merge(
merged_sbom.merge(sbom_m)

# Find root nodes: those with zero incoming edges
roots = [n for n, deg in merged_sbom.graph.in_degree() if deg == 0]
roots = [
n
for n, deg in merged_sbom.graph.in_degree()
if deg == 0 and merged_sbom.graph.nodes.get(n, {}).get("type") != "Path"
]
logger.info(f"ROOT NODES: {roots}")

# Detect any directed cycles
Expand All @@ -122,6 +126,8 @@ def merge(
if config and "systemRelationship" in config:
system_relationship = config["systemRelationship"]
for root_uuid in roots:
if merged_sbom.graph.nodes.get(root_uuid, {}).get("type") == "Path":
continue
merged_sbom.create_relationship(system_obj.UUID, root_uuid, system_relationship)
else:
logger.warning(
Expand Down
3 changes: 3 additions & 0 deletions surfactant/output/cytrics_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
# SPDX-License-Identifier: MIT
from typing import Optional

from loguru import logger

import surfactant.plugin
from surfactant.sbomtypes import SBOM


@surfactant.plugin.hookimpl
def write_sbom(sbom: SBOM, outfile) -> None:
# outfile is a file pointer, not a file name
logger.debug("writing SBOM")
outfile.write(sbom.to_json(indent=2))


Expand Down
44 changes: 44 additions & 0 deletions surfactant/relationships/_internal/windows_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,47 @@ def find_installed_software(
# matching probe directory and filename, add software to list
possible_matches.append(e)
return possible_matches


# construct a list of directories to probe for establishing dotnet relationships
def get_dotnet_probedirs(software: Software, refCulture, refName, dnProbingPaths):
probedirs = []
# probe for the referenced assemblies
if isinstance(software.installPath, Iterable):
for install_filepath in software.installPath:
install_basepath = pathlib.PureWindowsPath(install_filepath).parent.as_posix()
if refCulture is None or refCulture == "":
# [application base] / [assembly name].dll
# [application base] / [assembly name] / [assembly name].dll
probedirs.append(pathlib.PureWindowsPath(install_basepath).as_posix())
probedirs.append(pathlib.PureWindowsPath(install_basepath, refName).as_posix())
if dnProbingPaths is not None:
# add probing private paths
for path in dnProbingPaths:
# [application base] / [binpath] / [assembly name].dll
# [application base] / [binpath] / [assembly name] / [assembly name].dll
probedirs.append(pathlib.PureWindowsPath(install_basepath, path).as_posix())
probedirs.append(
pathlib.PureWindowsPath(install_basepath, path, refName).as_posix()
)
else:
# [application base] / [culture] / [assembly name].dll
# [application base] / [culture] / [assembly name] / [assembly name].dll
probedirs.append(pathlib.PureWindowsPath(install_basepath, refCulture).as_posix())
probedirs.append(
pathlib.PureWindowsPath(install_basepath, refName, refCulture).as_posix()
)
if dnProbingPaths is not None:
# add probing private paths
for path in dnProbingPaths:
# [application base] / [binpath] / [culture] / [assembly name].dll
# [application base] / [binpath] / [culture] / [assembly name] / [assembly name].dll
probedirs.append(
pathlib.PureWindowsPath(install_basepath, path, refCulture).as_posix()
)
probedirs.append(
pathlib.PureWindowsPath(
install_basepath, path, refName, refCulture
).as_posix()
)
return probedirs
Loading