Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
83c10db
feat: create pipeline for symbol reachability and add a test
ziadhany Apr 22, 2026
3799817
Add more test for reachability and remove redundant code
ziadhany Jun 5, 2026
a3d1172
Fix the format bugs and refactor the code
ziadhany Jun 10, 2026
2f0dd84
Fix a bug in the import-catching logic and add a test.
ziadhany Jun 11, 2026
00fd333
Add an unidiff dependency to pyproject.toml file
ziadhany Jun 16, 2026
5da2504
Add unidiff to package dependencies to parse diff text
ziadhany Jun 16, 2026
1e7f76e
Simplify the pipeline logic for imports and direct calls
ziadhany Jun 23, 2026
4428760
Add support for vulnerablecode reachability option
ziadhany Jun 24, 2026
e1a2d86
Fix the tests and improve patch extraction performance
ziadhany Jun 24, 2026
bf94dc8
Fix formatting and linting errors.
ziadhany Jun 25, 2026
c9b9652
Refactor and simplify reachability pipeline
ziadhany Jun 26, 2026
c4ac68a
Add support for getting constant symbols
ziadhany Jul 1, 2026
d48c18e
Remove dead code and fix the test
ziadhany Jul 1, 2026
6686487
Add unidiff to uv.lock
ziadhany Jul 1, 2026
a9076d3
Add support constant to resource analyzer
ziadhany Jul 1, 2026
2867643
Fix formating error in CI
ziadhany Jul 1, 2026
4b48ad7
Add a test for constants, extract_imports,collect_imports
ziadhany Jul 2, 2026
1bd85f6
Remove dependency and copy only the required file
ziadhany Jul 15, 2026
09cfa5f
Update pipeline/functions name
ziadhany Jul 22, 2026
3bfa88a
Fix CI files format
ziadhany Jul 23, 2026
ec79943
Fix a typo in patch.py.ABOUT file
ziadhany Jul 23, 2026
3744e2f
Remove the unidiff library from the dependencies
ziadhany Jul 23, 2026
128bfdf
Skip the test for macOS
ziadhany Jul 23, 2026
7258c0a
Allow reachability by default, for vulnerabilities pipeline
ziadhany Jul 29, 2026
27de9f1
Update the code to difflib instead of unidiff library
ziadhany Jul 29, 2026
0d85586
Add missing docs
ziadhany Aug 7, 2026
c9414ea
Fix a typo in build_symbol_metadata function signature
ziadhany Aug 7, 2026
566ae1e
Add a test for java
ziadhany Aug 10, 2026
9985d21
Simplify the pipeline test
ziadhany Aug 11, 2026
131b68e
Generate advisory reachability report ( last step in the pipeline )
ziadhany Aug 13, 2026
69fc18a
Fix Formating and typo in test
ziadhany Aug 14, 2026
98350c3
Remove type hints
ziadhany Aug 14, 2026
9ce4cb4
Remove type hints for symbols.py
ziadhany Aug 14, 2026
c89c64e
Remove type hints for symbols.py
ziadhany Aug 14, 2026
2f14b41
Fix a typo in docs
ziadhany Aug 14, 2026
9a6d42d
Fix a typo in error message
ziadhany Aug 14, 2026
01f294c
Update the pipeline to clone repo once and collect_patch_symbols for …
ziadhany Aug 18, 2026
40f5f0e
Try to fix bug in vulnerability dependency
ziadhany Aug 20, 2026
a36ba7e
Update the pipeline to have a test for resource_patch_matcher
ziadhany Aug 24, 2026
30c8c7b
Add more test and make sure it returns not if there is no match
ziadhany Aug 24, 2026
fa64a68
Move Business logic to be in the pipes reachability file
ziadhany Aug 24, 2026
8f83785
fix is_reachable to be by default NOT_REACHABLE
ziadhany Aug 25, 2026
07ed82f
Fix a bug related to vulnerability dependency reachability pipeline
ziadhany Aug 27, 2026
e65b8e2
Update function docs
ziadhany Aug 28, 2026
40d80ca
Fix a typo
ziadhany Aug 28, 2026
83200b3
Fix format error
ziadhany Aug 28, 2026
bdc627e
Add a LoopProgress to the most time-consuming functions
ziadhany Aug 28, 2026
3535486
Expose reachability in API for package and dependency
ziadhany Aug 24, 2026
fc917e7
Simplify the apply_reachability_to_packages_and_dependencies function
ziadhany Aug 25, 2026
96a827a
Resolve merge conflict
ziadhany Aug 28, 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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ run = "scancodeio:combined_run"
analyze_docker_image = "scanpipe.pipelines.analyze_docker:Docker"
analyze_root_filesystem_or_vm_image = "scanpipe.pipelines.analyze_root_filesystem:RootFS"
analyze_windows_docker_image = "scanpipe.pipelines.analyze_docker_windows:DockerWindows"
analyze_symbols_reachability = "scanpipe.pipelines.analyze_symbols_reachability:SymbolReachability"
benchmark_purls = "scanpipe.pipelines.benchmark_purls:BenchmarkPurls"
collect_strings_gettext = "scanpipe.pipelines.collect_strings_gettext:CollectStringsGettext"
collect_symbols_ctags = "scanpipe.pipelines.collect_symbols_ctags:CollectSymbolsCtags"
Expand Down
116 changes: 116 additions & 0 deletions scanpipe/pipelines/analyze_symbols_reachability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# SPDX-License-Identifier: Apache-2.0
#
# http://nexb.com and https://github.com/aboutcode-org/scancode.io
# The ScanCode.io software is licensed under the Apache License version 2.0.
# Data generated with ScanCode.io is provided as-is without warranties.
# ScanCode is a trademark of nexB Inc.
#
# You may not use this software except in compliance with the License.
# You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
#
# Data Generated with ScanCode.io is provided on an "AS IS" BASIS, WITHOUT WARRANTIES
# OR CONDITIONS OF ANY KIND, either express or implied. No content created from
# ScanCode.io should be considered or used as legal advice. Consult an Attorney
# for any legal advice.
#
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
# Visit https://github.com/aboutcode-org/scancode.io for support and download.

from scanpipe.pipelines import Pipeline
from scanpipe.pipes import reachability
from scanpipe.pipes.symbols import TS_QUERIES


class SymbolReachability(Pipeline):
"""
Determine the reachability of vulnerabilities identified in the project.

Note: You must run `find_vulnerabilities` pipeline before running this pipeline.

For every patch the git repository is cloned and extract the vulnerable and fixed
symbols from the patch commit. These symbols are then matched against
the project's codebase resources to determine if the vulnerable code
is actually present and reachable.

The analysis checks if vulnerable symbols are defined, imported, called,
or exactly match a code within the project files. The results, including
tool_details and a reachability status (yes, unknown, or no), are stored
in the `extra_data` of the matching resources under the `symbols_reachability` key.

Finally, a summary report is generated for each vulnerability
advisory and saved as a JSON output file.
"""

download_inputs = False
is_addon = True
results_url = "/project/{slug}/resources/?extra_data=symbol_reachability"

@classmethod
def steps(cls):
return (
cls.get_vulnerabilities_patches,
cls.collect_resource_index,
cls.collect_patch_symbols,
cls.collect_and_match_resources,
cls.generate_advisory_reachability_report,
cls.apply_reachability_to_packages_and_dependencies,
)

def get_vulnerabilities_patches(self):
"""Get unique patch for all vulnerabilities."""
self.patches = reachability.get_vulnerabilities_patches(
package_vulnerabilities=self.project.package_vulnerabilities,
dependency_vulnerabilities=self.project.dependency_vulnerabilities,
)

def collect_resource_index(self):
"""Collect resources symbols for each resource"""
self.candidate_resources = self.project.codebaseresources.files().filter(
is_binary=False,
is_archive=False,
is_media=False,
programming_language__in=TS_QUERIES.keys(),
)
self.resource_indexes = reachability.collect_resource_index(
candidate_resources=self.candidate_resources, logger=self.log
)

def collect_patch_symbols(self):
"""Collect patch symbols for all related commits."""
self.patch_symbols = reachability.collect_patch_symbols(
patches=self.patches, logger=self.log
)

def collect_and_match_resources(self):
"""Match resource symbols against patch symbols."""
reachability.match_patches_to_resources(
patches=self.patches,
patch_symbols=self.patch_symbols,
resource_indexes=self.resource_indexes,
candidate_resources=self.candidate_resources,
logger=self.log,
)

def generate_advisory_reachability_report(self):
"""Generate a reachability report summarizing status by advisory."""
self.advisories_reachability_report = (
reachability.generate_advisory_reachability_report(
project=self.project,
patches=self.patches,
candidate_resources=self.candidate_resources,
)
)

def apply_reachability_to_packages_and_dependencies(self):
"""
Save reachability results by updating DiscoveredPackage and
DiscoveredDependency records with the computed reachability data
in their affected_by_vulnerabilities JSON field.
"""
reachability.apply_reachability_to_packages_and_dependencies(
project=self.project, advisory_report=self.advisories_reachability_report
)
Loading
Loading