libidentifier 0.2.0rc1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- libidentifier-0.2.0rc1/CHANGELOG.md +42 -0
- libidentifier-0.2.0rc1/LICENSE +62 -0
- libidentifier-0.2.0rc1/MANIFEST.in +15 -0
- libidentifier-0.2.0rc1/PKG-INFO +156 -0
- libidentifier-0.2.0rc1/README.md +127 -0
- libidentifier-0.2.0rc1/THIRD_PARTY_NOTICES.md +15 -0
- libidentifier-0.2.0rc1/benchmarks/corpus.example.json +11 -0
- libidentifier-0.2.0rc1/benchmarks/run.py +84 -0
- libidentifier-0.2.0rc1/catalog/references.example.json +13 -0
- libidentifier-0.2.0rc1/catalog/references.json +63 -0
- libidentifier-0.2.0rc1/docs/architecture.md +51 -0
- libidentifier-0.2.0rc1/docs/development/README.md +28 -0
- libidentifier-0.2.0rc1/docs/development/archive/technical-specification-v1.md +595 -0
- libidentifier-0.2.0rc1/docs/development/decisions/0001-stage-2.md +34 -0
- libidentifier-0.2.0rc1/docs/development/release-readiness.md +51 -0
- libidentifier-0.2.0rc1/docs/development/roadmap.md +24 -0
- libidentifier-0.2.0rc1/docs/development/stages/future.md +9 -0
- libidentifier-0.2.0rc1/docs/development/stages/stage-1.md +12 -0
- libidentifier-0.2.0rc1/docs/development/stages/stage-2.md +60 -0
- libidentifier-0.2.0rc1/docs/development/stages/stage-3.md +18 -0
- libidentifier-0.2.0rc1/docs/development/testing.md +85 -0
- libidentifier-0.2.0rc1/docs/development/validation/cleanup-windows-2026-10-20.md +61 -0
- libidentifier-0.2.0rc1/docs/development/validation/managed-cli-windows-2026-10-21.md +82 -0
- libidentifier-0.2.0rc1/docs/development/validation/phase-a-windows-2026-10-20.md +69 -0
- libidentifier-0.2.0rc1/docs/development/validation/stage2-matrix.json +201 -0
- libidentifier-0.2.0rc1/docs/development/validation/stage2-pilot.json +166 -0
- libidentifier-0.2.0rc1/docs/development/validation/stage2-validation.md +202 -0
- libidentifier-0.2.0rc1/docs/fingerprints.md +18 -0
- libidentifier-0.2.0rc1/docs/formats.md +19 -0
- libidentifier-0.2.0rc1/docs/installation.md +179 -0
- libidentifier-0.2.0rc1/docs/integration.md +593 -0
- libidentifier-0.2.0rc1/docs/limitations.md +31 -0
- libidentifier-0.2.0rc1/docs/profile-database.md +68 -0
- libidentifier-0.2.0rc1/docs/quickstart.md +246 -0
- libidentifier-0.2.0rc1/docs/releases.md +213 -0
- libidentifier-0.2.0rc1/pyproject.toml +45 -0
- libidentifier-0.2.0rc1/setup.cfg +4 -0
- libidentifier-0.2.0rc1/src/libidentifier/__init__.py +36 -0
- libidentifier-0.2.0rc1/src/libidentifier/api.py +90 -0
- libidentifier-0.2.0rc1/src/libidentifier/archive.py +133 -0
- libidentifier-0.2.0rc1/src/libidentifier/cli.py +340 -0
- libidentifier-0.2.0rc1/src/libidentifier/cli_resources.py +36 -0
- libidentifier-0.2.0rc1/src/libidentifier/cli_setup.py +177 -0
- libidentifier-0.2.0rc1/src/libidentifier/config.py +54 -0
- libidentifier-0.2.0rc1/src/libidentifier/detect.py +30 -0
- libidentifier-0.2.0rc1/src/libidentifier/errors.py +30 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/__init__.py +2 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/dex.py +121 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/dex_tables.py +137 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/elf.py +66 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/instructions.py +77 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/metadata.py +99 -0
- libidentifier-0.2.0rc1/src/libidentifier/extractors/version_metadata.py +72 -0
- libidentifier-0.2.0rc1/src/libidentifier/fingerprint/__init__.py +2 -0
- libidentifier-0.2.0rc1/src/libidentifier/fingerprint/dex_v2.py +97 -0
- libidentifier-0.2.0rc1/src/libidentifier/fingerprint/elf_v1.py +16 -0
- libidentifier-0.2.0rc1/src/libidentifier/grouping.py +74 -0
- libidentifier-0.2.0rc1/src/libidentifier/inventory.py +260 -0
- libidentifier-0.2.0rc1/src/libidentifier/matcher.py +381 -0
- libidentifier-0.2.0rc1/src/libidentifier/models.py +423 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/__init__.py +2 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/builder.py +182 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/catalog.py +135 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/distribution.py +303 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/fetcher.py +141 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/pom.py +66 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/schema.py +137 -0
- libidentifier-0.2.0rc1/src/libidentifier/profiles/store.py +212 -0
- libidentifier-0.2.0rc1/src/libidentifier/purl.py +36 -0
- libidentifier-0.2.0rc1/src/libidentifier/relationships.py +168 -0
- libidentifier-0.2.0rc1/src/libidentifier/sbom.py +62 -0
- libidentifier-0.2.0rc1/src/libidentifier/serialization.py +53 -0
- libidentifier-0.2.0rc1/src/libidentifier/table.py +254 -0
- libidentifier-0.2.0rc1/src/libidentifier/version.py +2 -0
- libidentifier-0.2.0rc1/src/libidentifier/vulnerabilities/__init__.py +2 -0
- libidentifier-0.2.0rc1/src/libidentifier/vulnerabilities/correlate.py +164 -0
- libidentifier-0.2.0rc1/src/libidentifier/vulnerabilities/database.py +213 -0
- libidentifier-0.2.0rc1/src/libidentifier/vulnerabilities/models.py +155 -0
- libidentifier-0.2.0rc1/src/libidentifier/vulnerabilities/runner.py +148 -0
- libidentifier-0.2.0rc1/src/libidentifier/vulnerabilities/setup.py +74 -0
- libidentifier-0.2.0rc1/src/libidentifier.egg-info/PKG-INFO +156 -0
- libidentifier-0.2.0rc1/src/libidentifier.egg-info/SOURCES.txt +101 -0
- libidentifier-0.2.0rc1/src/libidentifier.egg-info/dependency_links.txt +1 -0
- libidentifier-0.2.0rc1/src/libidentifier.egg-info/entry_points.txt +2 -0
- libidentifier-0.2.0rc1/src/libidentifier.egg-info/requires.txt +9 -0
- libidentifier-0.2.0rc1/src/libidentifier.egg-info/top_level.txt +1 -0
- libidentifier-0.2.0rc1/tests/conftest.py +299 -0
- libidentifier-0.2.0rc1/tests/fixtures/scan-v1-legacy.json +15 -0
- libidentifier-0.2.0rc1/tests/test_catalog_fetch_rebuild.py +65 -0
- libidentifier-0.2.0rc1/tests/test_cli_and_sbom.py +72 -0
- libidentifier-0.2.0rc1/tests/test_cli_setup.py +215 -0
- libidentifier-0.2.0rc1/tests/test_detect_and_archive.py +37 -0
- libidentifier-0.2.0rc1/tests/test_dex_elf_features.py +60 -0
- libidentifier-0.2.0rc1/tests/test_frameworks_and_contract.py +247 -0
- libidentifier-0.2.0rc1/tests/test_offline_assessment.py +278 -0
- libidentifier-0.2.0rc1/tests/test_osv_convenience.py +185 -0
- libidentifier-0.2.0rc1/tests/test_profile_distribution.py +203 -0
- libidentifier-0.2.0rc1/tests/test_profile_matching.py +123 -0
- libidentifier-0.2.0rc1/tests/test_sca_readiness.py +262 -0
- libidentifier-0.2.0rc1/tests/test_scanner_compatibility.py +122 -0
- libidentifier-0.2.0rc1/tests/test_stage2.py +303 -0
- libidentifier-0.2.0rc1/tests/test_table_and_score.py +147 -0
- libidentifier-0.2.0rc1/tools/check_distributions.py +42 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0rc1 — Stage 2 preview (publication pending)
|
|
4
|
+
|
|
5
|
+
- Complete PyPI/GitHub source installation routes, Windows activation-free
|
|
6
|
+
commands, result interpretation, managed-path updates and user troubleshooting.
|
|
7
|
+
README/PyPI links lead to installation/usage before the advanced API reference.
|
|
8
|
+
|
|
9
|
+
- Managed `scan app.apk` first-run setup with one consent prompt, `--yes`, strict
|
|
10
|
+
`--offline`, project-pinned scanner downloads and persistent per-user resources.
|
|
11
|
+
- `--vulns` alias, table default for managed scans, preserved explicit-profile
|
|
12
|
+
JSON defaults and download-free analysis APIs; optional failures retain inventory.
|
|
13
|
+
|
|
14
|
+
- Explicit profile packaging/acquisition APIs and CLI, portable release manifests,
|
|
15
|
+
hashes, engine compatibility, bounded downloads/decompression, SQLite integrity
|
|
16
|
+
checks and atomic install with explicit replacement. Analysis remains offline.
|
|
17
|
+
- Single-source package version, PyPI metadata, wheel/sdist content checks,
|
|
18
|
+
Trusted Publishing workflow and maintainer publication instructions.
|
|
19
|
+
|
|
20
|
+
- Release-first roadmap: preview package and small schema-2 profile distribution
|
|
21
|
+
before catalog expansion and Stage 3 accuracy qualification.
|
|
22
|
+
- Removed obsolete generated validation output and schema-1 sample databases;
|
|
23
|
+
retained selected dated evidence under `docs/development/validation/`.
|
|
24
|
+
- Canonical DEX implementation now uses `fingerprint/dex_v2.py`; optional local
|
|
25
|
+
qualification resources use ignored `.local/` and `.tools/` directories.
|
|
26
|
+
|
|
27
|
+
- Canonical DEX descriptors/interfaces and location-aware ownership uncertainty.
|
|
28
|
+
- Additive evidence, analysis status, unattributed clusters and typed structural,
|
|
29
|
+
ordinary invocation, published-dependency and component relationship models.
|
|
30
|
+
- Internal reference schema 2 separates releases, artifacts, variants, fingerprints
|
|
31
|
+
and occurrences; canonical fingerprints require an explicit profile rebuild.
|
|
32
|
+
- Direct POM/local-property interpretation and attributable embedded Maven metadata.
|
|
33
|
+
- Contributor documentation, preserved historical specification, contract fixtures,
|
|
34
|
+
platform CI and a benchmark harness. Existing OSV provisioning/discovery/offline
|
|
35
|
+
execution and compact table behavior are preserved.
|
|
36
|
+
- CI validates regular package installations and retains per-environment runtime,
|
|
37
|
+
scanner and JUnit evidence, including skip reasons.
|
|
38
|
+
|
|
39
|
+
## 0.1.0
|
|
40
|
+
|
|
41
|
+
- Initial Stage 1 implementation with APK/DEX/ELF inspection, DEX shape fingerprints, ELF identity fingerprints, SQLite profile building, offline matching, JSON output, CLI commands, and CycloneDX export for exact high-confidence versions.
|
|
42
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
https://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
|
10
|
+
|
|
11
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
|
12
|
+
|
|
13
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
|
14
|
+
|
|
15
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
|
16
|
+
|
|
17
|
+
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
|
18
|
+
|
|
19
|
+
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
|
20
|
+
|
|
21
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License.
|
|
22
|
+
|
|
23
|
+
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on or derived from the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. Derivative Works shall not include works that remain separable from, or merely link or bind by name to the interfaces of, the Work.
|
|
24
|
+
|
|
25
|
+
"Contribution" shall mean any work of authorship that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner.
|
|
26
|
+
|
|
27
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
|
28
|
+
|
|
29
|
+
2. Grant of Copyright License.
|
|
30
|
+
|
|
31
|
+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
|
32
|
+
|
|
33
|
+
3. Grant of Patent License.
|
|
34
|
+
|
|
35
|
+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work. If You institute patent litigation against any entity alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
|
36
|
+
|
|
37
|
+
4. Redistribution.
|
|
38
|
+
|
|
39
|
+
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet these conditions: You must give recipients a copy of this License; modified files must carry prominent notices stating that You changed the files; and You must retain copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding notices that do not pertain to any part of the Derivative Works. If the Work includes a NOTICE file, Derivative Works that You distribute must include a readable copy of applicable attribution notices.
|
|
40
|
+
|
|
41
|
+
5. Submission of Contributions.
|
|
42
|
+
|
|
43
|
+
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License.
|
|
44
|
+
|
|
45
|
+
6. Trademarks.
|
|
46
|
+
|
|
47
|
+
This License does not grant permission to use trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work.
|
|
48
|
+
|
|
49
|
+
7. Disclaimer of Warranty.
|
|
50
|
+
|
|
51
|
+
Unless required by applicable law or agreed to in writing, Licensor provides the Work on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
52
|
+
|
|
53
|
+
8. Limitation of Liability.
|
|
54
|
+
|
|
55
|
+
In no event and under no legal theory, whether in tort, contract, or otherwise, unless required by applicable law or agreed to in writing, shall any Contributor be liable to You for damages arising as a result of this License or out of the use or inability to use the Work.
|
|
56
|
+
|
|
57
|
+
9. Accepting Warranty or Additional Liability.
|
|
58
|
+
|
|
59
|
+
While redistributing the Work or Derivative Works thereof, You may choose to offer support, warranty, indemnity, or other liability obligations. In accepting such obligations, You act only on Your own behalf and on Your sole responsibility.
|
|
60
|
+
|
|
61
|
+
END OF TERMS AND CONDITIONS
|
|
62
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
include LICENSE THIRD_PARTY_NOTICES.md CHANGELOG.md
|
|
2
|
+
recursive-include docs *.md *.json
|
|
3
|
+
recursive-exclude docs __pycache__ *integration-moraine* *moraine-integration*
|
|
4
|
+
recursive-include catalog *.json
|
|
5
|
+
recursive-include benchmarks *.py *.json
|
|
6
|
+
recursive-include tests *.py *.json
|
|
7
|
+
recursive-include tools *.py
|
|
8
|
+
prune .local
|
|
9
|
+
prune .tools
|
|
10
|
+
prune .development-deps
|
|
11
|
+
prune .release-venv
|
|
12
|
+
prune samples
|
|
13
|
+
prune test-results
|
|
14
|
+
prune build
|
|
15
|
+
exclude moraine-integration.md
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: libidentifier
|
|
3
|
+
Version: 0.2.0rc1
|
|
4
|
+
Summary: Offline identification of compiled Android and native libraries from local fingerprints
|
|
5
|
+
Author: LibIdentifier authors
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Repository, https://github.com/ernestomgz/libidentifier
|
|
8
|
+
Project-URL: Documentation, https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md
|
|
9
|
+
Project-URL: Installation, https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md
|
|
10
|
+
Project-URL: API reference, https://github.com/ernestomgz/libidentifier/blob/main/docs/integration.md
|
|
11
|
+
Project-URL: Issues, https://github.com/ernestomgz/libidentifier/issues
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
21
|
+
Requires-Dist: lief==0.17.1
|
|
22
|
+
Requires-Dist: packaging>=24
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
25
|
+
Provides-Extra: release
|
|
26
|
+
Requires-Dist: build>=1.2; extra == "release"
|
|
27
|
+
Requires-Dist: twine>=6; extra == "release"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# LibIdentifier
|
|
31
|
+
|
|
32
|
+
Identify known libraries and frameworks in Android APKs, DEX and native ELF files.
|
|
33
|
+
LibIdentifier is an independent Python package and CLI. Analysis runs locally;
|
|
34
|
+
your APK is never uploaded. Optional OSV assessment uses a local advisory database
|
|
35
|
+
and does not establish reachability or exploitability.
|
|
36
|
+
|
|
37
|
+
**Preview:** the initial official profile catalog covers six library families and
|
|
38
|
+
eight releases. No match does not mean no third-party code. See
|
|
39
|
+
[limitations](https://github.com/ernestomgz/libidentifier/blob/main/docs/limitations.md). The PyPI route requires a published package, and managed
|
|
40
|
+
library scans require published profiles. Check [installation availability](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md#before-you-start)
|
|
41
|
+
or use the source route and profile-free inspection below.
|
|
42
|
+
|
|
43
|
+
## Install from PyPI or GitHub
|
|
44
|
+
|
|
45
|
+
Python 3.12 is recommended. New to Python environments? Follow the complete
|
|
46
|
+
[Windows/Linux installation guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md), including the
|
|
47
|
+
activation-free Windows option.
|
|
48
|
+
|
|
49
|
+
**Released package from PyPI** (after publication), in your Python environment:
|
|
50
|
+
|
|
51
|
+
```powershell
|
|
52
|
+
python -m pip install "libidentifier==0.2.0rc1"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Reviewed source from GitHub**, in your Python environment:
|
|
56
|
+
|
|
57
|
+
```powershell
|
|
58
|
+
git clone https://github.com/ernestomgz/libidentifier.git
|
|
59
|
+
cd libidentifier
|
|
60
|
+
python -m pip install .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Both methods provide the same command. Check the installation, then scan your
|
|
64
|
+
own APK (replace the example path):
|
|
65
|
+
|
|
66
|
+
```powershell
|
|
67
|
+
libidentifier --version
|
|
68
|
+
libidentifier scan "app.apk" --vulns
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The source route installs the code before PyPI publication, but automatic library
|
|
72
|
+
scans still require the official profiles to be available. Until then,
|
|
73
|
+
`libidentifier inspect "app.apk" --format table` works without profiles; see
|
|
74
|
+
[installation verification](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md#verify-without-profiles).
|
|
75
|
+
|
|
76
|
+
`--vulnerabilities` is the long spelling of `--vulns`. For library identification
|
|
77
|
+
without advisory assessment:
|
|
78
|
+
|
|
79
|
+
```powershell
|
|
80
|
+
libidentifier scan app.apk
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
On first use, the CLI lists missing resources, shows their destination and asks
|
|
84
|
+
`Download and set up these resources? [y/N]`. Accept to install the official
|
|
85
|
+
profiles and, when requested, the project-qualified OSV-Scanner and Maven advisory
|
|
86
|
+
data. Later scans reuse them. Existing resources are never silently updated.
|
|
87
|
+
Without vulnerability assessment, only profiles are needed.
|
|
88
|
+
|
|
89
|
+
Managed scans print the compact table. Setup messages go to stderr. Windows
|
|
90
|
+
resources live under `%LOCALAPPDATA%/LibIdentifier`; Linux uses
|
|
91
|
+
`${XDG_CACHE_HOME:-~/.cache}/libidentifier`. `LIBIDENTIFIER_HOME` overrides the
|
|
92
|
+
managed root. Automatic scanner installation currently supports Windows/Linux
|
|
93
|
+
x64 and uses project-pinned URLs and SHA-256 values, never GitHub's latest tag.
|
|
94
|
+
|
|
95
|
+
## Useful options
|
|
96
|
+
|
|
97
|
+
```powershell
|
|
98
|
+
# Authorize missing-resource setup in scripts; never prompts.
|
|
99
|
+
libidentifier scan app.apk --vulns --yes
|
|
100
|
+
|
|
101
|
+
# Reuse installed resources without any downloads.
|
|
102
|
+
libidentifier scan app.apk --vulns --offline
|
|
103
|
+
|
|
104
|
+
# JSON instead of a table; --output alone also selects JSON in managed mode.
|
|
105
|
+
libidentifier scan app.apk --vulns --output results.json
|
|
106
|
+
|
|
107
|
+
# Existing explicit usage retains its JSON default and resource overrides.
|
|
108
|
+
libidentifier scan app.apk --profiles custom.sqlite --format json --output results.json
|
|
109
|
+
libidentifier identify app.apk --profiles custom.sqlite --format table
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
A noninteractive first run needs `--yes` or preinstalled resources. `--offline`
|
|
113
|
+
overrides `--yes`. If optional vulnerability setup fails, identification is
|
|
114
|
+
preserved with an explicit unassessed result. Required profile failures stop the
|
|
115
|
+
scan. Continue with [first scan, result meanings, advanced options and resource updates](https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md).
|
|
116
|
+
|
|
117
|
+
## Python API
|
|
118
|
+
|
|
119
|
+
Use a local database you explicitly provisioned; the managed CLI cache is not
|
|
120
|
+
automatically copied to your working directory. See the
|
|
121
|
+
[complete API setup example](https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md#use-the-python-api).
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from pathlib import Path
|
|
125
|
+
from libidentifier import identify
|
|
126
|
+
|
|
127
|
+
result = identify(Path("app.apk"), profiles=Path("profiles.sqlite"))
|
|
128
|
+
result.write_json(Path("libraries.json"))
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Analysis APIs never prompt, install tools or download data. Explicit maintenance
|
|
132
|
+
APIs are available for consumers that manage their own setup. The authoritative
|
|
133
|
+
[API/JSON guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/integration.md) documents models, coverage, errors, SBOM,
|
|
134
|
+
profile provisioning and offline advisory assessment. Structural matching normally
|
|
135
|
+
identifies families; exact installed versions require stronger evidence.
|
|
136
|
+
|
|
137
|
+
## Documentation and development
|
|
138
|
+
|
|
139
|
+
| I want to… | Read |
|
|
140
|
+
|---|---|
|
|
141
|
+
| Install from pip, GitHub or a source ZIP | [Installation](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md) |
|
|
142
|
+
| Scan, save output, use offline mode or repair setup | [Usage guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md) |
|
|
143
|
+
| Integrate the Python API or consume JSON | [Public contract](https://github.com/ernestomgz/libidentifier/blob/main/docs/integration.md) |
|
|
144
|
+
| Build my own reference catalog | [Profile database](https://github.com/ernestomgz/libidentifier/blob/main/docs/profile-database.md) |
|
|
145
|
+
| Publish/update official releases | [Maintainer release guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/releases.md) |
|
|
146
|
+
|
|
147
|
+
Python 3.11+; `lief==0.17.1`. To use a reviewed checkout before publication:
|
|
148
|
+
|
|
149
|
+
```powershell
|
|
150
|
+
python -m pip install -e ".[dev]"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Tests generate synthetic DEX/APK/ELF fixtures. JAR/AAR **profile generation** needs
|
|
154
|
+
local D8; ordinary scans do not need Java or the Android SDK. See the
|
|
155
|
+
[developer index](https://github.com/ernestomgz/libidentifier/blob/main/docs/development/README.md), [release checklist](https://github.com/ernestomgz/libidentifier/blob/main/docs/development/release-readiness.md),
|
|
156
|
+
[Stage 2 acceptance](https://github.com/ernestomgz/libidentifier/blob/main/docs/development/stages/stage-2.md) and [contributor instructions](https://github.com/ernestomgz/libidentifier/blob/main/AGENTS.md).
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# LibIdentifier
|
|
2
|
+
|
|
3
|
+
Identify known libraries and frameworks in Android APKs, DEX and native ELF files.
|
|
4
|
+
LibIdentifier is an independent Python package and CLI. Analysis runs locally;
|
|
5
|
+
your APK is never uploaded. Optional OSV assessment uses a local advisory database
|
|
6
|
+
and does not establish reachability or exploitability.
|
|
7
|
+
|
|
8
|
+
**Preview:** the initial official profile catalog covers six library families and
|
|
9
|
+
eight releases. No match does not mean no third-party code. See
|
|
10
|
+
[limitations](https://github.com/ernestomgz/libidentifier/blob/main/docs/limitations.md). The PyPI route requires a published package, and managed
|
|
11
|
+
library scans require published profiles. Check [installation availability](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md#before-you-start)
|
|
12
|
+
or use the source route and profile-free inspection below.
|
|
13
|
+
|
|
14
|
+
## Install from PyPI or GitHub
|
|
15
|
+
|
|
16
|
+
Python 3.12 is recommended. New to Python environments? Follow the complete
|
|
17
|
+
[Windows/Linux installation guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md), including the
|
|
18
|
+
activation-free Windows option.
|
|
19
|
+
|
|
20
|
+
**Released package from PyPI** (after publication), in your Python environment:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
python -m pip install "libidentifier==0.2.0rc1"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Reviewed source from GitHub**, in your Python environment:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
git clone https://github.com/ernestomgz/libidentifier.git
|
|
30
|
+
cd libidentifier
|
|
31
|
+
python -m pip install .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Both methods provide the same command. Check the installation, then scan your
|
|
35
|
+
own APK (replace the example path):
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
libidentifier --version
|
|
39
|
+
libidentifier scan "app.apk" --vulns
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The source route installs the code before PyPI publication, but automatic library
|
|
43
|
+
scans still require the official profiles to be available. Until then,
|
|
44
|
+
`libidentifier inspect "app.apk" --format table` works without profiles; see
|
|
45
|
+
[installation verification](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md#verify-without-profiles).
|
|
46
|
+
|
|
47
|
+
`--vulnerabilities` is the long spelling of `--vulns`. For library identification
|
|
48
|
+
without advisory assessment:
|
|
49
|
+
|
|
50
|
+
```powershell
|
|
51
|
+
libidentifier scan app.apk
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
On first use, the CLI lists missing resources, shows their destination and asks
|
|
55
|
+
`Download and set up these resources? [y/N]`. Accept to install the official
|
|
56
|
+
profiles and, when requested, the project-qualified OSV-Scanner and Maven advisory
|
|
57
|
+
data. Later scans reuse them. Existing resources are never silently updated.
|
|
58
|
+
Without vulnerability assessment, only profiles are needed.
|
|
59
|
+
|
|
60
|
+
Managed scans print the compact table. Setup messages go to stderr. Windows
|
|
61
|
+
resources live under `%LOCALAPPDATA%/LibIdentifier`; Linux uses
|
|
62
|
+
`${XDG_CACHE_HOME:-~/.cache}/libidentifier`. `LIBIDENTIFIER_HOME` overrides the
|
|
63
|
+
managed root. Automatic scanner installation currently supports Windows/Linux
|
|
64
|
+
x64 and uses project-pinned URLs and SHA-256 values, never GitHub's latest tag.
|
|
65
|
+
|
|
66
|
+
## Useful options
|
|
67
|
+
|
|
68
|
+
```powershell
|
|
69
|
+
# Authorize missing-resource setup in scripts; never prompts.
|
|
70
|
+
libidentifier scan app.apk --vulns --yes
|
|
71
|
+
|
|
72
|
+
# Reuse installed resources without any downloads.
|
|
73
|
+
libidentifier scan app.apk --vulns --offline
|
|
74
|
+
|
|
75
|
+
# JSON instead of a table; --output alone also selects JSON in managed mode.
|
|
76
|
+
libidentifier scan app.apk --vulns --output results.json
|
|
77
|
+
|
|
78
|
+
# Existing explicit usage retains its JSON default and resource overrides.
|
|
79
|
+
libidentifier scan app.apk --profiles custom.sqlite --format json --output results.json
|
|
80
|
+
libidentifier identify app.apk --profiles custom.sqlite --format table
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
A noninteractive first run needs `--yes` or preinstalled resources. `--offline`
|
|
84
|
+
overrides `--yes`. If optional vulnerability setup fails, identification is
|
|
85
|
+
preserved with an explicit unassessed result. Required profile failures stop the
|
|
86
|
+
scan. Continue with [first scan, result meanings, advanced options and resource updates](https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md).
|
|
87
|
+
|
|
88
|
+
## Python API
|
|
89
|
+
|
|
90
|
+
Use a local database you explicitly provisioned; the managed CLI cache is not
|
|
91
|
+
automatically copied to your working directory. See the
|
|
92
|
+
[complete API setup example](https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md#use-the-python-api).
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from pathlib import Path
|
|
96
|
+
from libidentifier import identify
|
|
97
|
+
|
|
98
|
+
result = identify(Path("app.apk"), profiles=Path("profiles.sqlite"))
|
|
99
|
+
result.write_json(Path("libraries.json"))
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Analysis APIs never prompt, install tools or download data. Explicit maintenance
|
|
103
|
+
APIs are available for consumers that manage their own setup. The authoritative
|
|
104
|
+
[API/JSON guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/integration.md) documents models, coverage, errors, SBOM,
|
|
105
|
+
profile provisioning and offline advisory assessment. Structural matching normally
|
|
106
|
+
identifies families; exact installed versions require stronger evidence.
|
|
107
|
+
|
|
108
|
+
## Documentation and development
|
|
109
|
+
|
|
110
|
+
| I want to… | Read |
|
|
111
|
+
|---|---|
|
|
112
|
+
| Install from pip, GitHub or a source ZIP | [Installation](https://github.com/ernestomgz/libidentifier/blob/main/docs/installation.md) |
|
|
113
|
+
| Scan, save output, use offline mode or repair setup | [Usage guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/quickstart.md) |
|
|
114
|
+
| Integrate the Python API or consume JSON | [Public contract](https://github.com/ernestomgz/libidentifier/blob/main/docs/integration.md) |
|
|
115
|
+
| Build my own reference catalog | [Profile database](https://github.com/ernestomgz/libidentifier/blob/main/docs/profile-database.md) |
|
|
116
|
+
| Publish/update official releases | [Maintainer release guide](https://github.com/ernestomgz/libidentifier/blob/main/docs/releases.md) |
|
|
117
|
+
|
|
118
|
+
Python 3.11+; `lief==0.17.1`. To use a reviewed checkout before publication:
|
|
119
|
+
|
|
120
|
+
```powershell
|
|
121
|
+
python -m pip install -e ".[dev]"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Tests generate synthetic DEX/APK/ELF fixtures. JAR/AAR **profile generation** needs
|
|
125
|
+
local D8; ordinary scans do not need Java or the Android SDK. See the
|
|
126
|
+
[developer index](https://github.com/ernestomgz/libidentifier/blob/main/docs/development/README.md), [release checklist](https://github.com/ernestomgz/libidentifier/blob/main/docs/development/release-readiness.md),
|
|
127
|
+
[Stage 2 acceptance](https://github.com/ernestomgz/libidentifier/blob/main/docs/development/stages/stage-2.md) and [contributor instructions](https://github.com/ernestomgz/libidentifier/blob/main/AGENTS.md).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
LibIdentifier Stage 1 contains original implementation code and does not vendor Androguard, LibScout, OSV-Scanner, Android SDK artifacts, or third-party library binaries.
|
|
4
|
+
|
|
5
|
+
Runtime dependency:
|
|
6
|
+
|
|
7
|
+
- LIEF, used for DEX and ELF parsing. See https://lief.re/ and the LIEF project license for redistribution terms.
|
|
8
|
+
|
|
9
|
+
Research influence:
|
|
10
|
+
|
|
11
|
+
- LibScout's profile-and-match approach informed the high-level fingerprinting strategy.
|
|
12
|
+
- Androguard documentation informed Android bytecode terminology.
|
|
13
|
+
|
|
14
|
+
No upstream source files from those projects were copied into this implementation.
|
|
15
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"samples": [
|
|
4
|
+
{
|
|
5
|
+
"path": "fixtures/independent.apk",
|
|
6
|
+
"ground_truth_complete": true,
|
|
7
|
+
"components": [{"family_purl": "pkg:maven/example/demo", "version": "1.0"}],
|
|
8
|
+
"build": {"compiler": "record actual version", "transformation": "unoptimized", "keep_rules_sha256": null}
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Isolated scan measurements; quality metrics require complete build ground truth.
|
|
2
|
+
|
|
3
|
+
python benchmarks/run.py --profiles profiles.sqlite --corpus corpus.json
|
|
4
|
+
Corpus paths are relative to the manifest. Each sample runs in a new process.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
import argparse
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
import time
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def peak_rss():
|
|
17
|
+
if os.name != 'nt':
|
|
18
|
+
import resource
|
|
19
|
+
return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss * 1024
|
|
20
|
+
import ctypes
|
|
21
|
+
from ctypes import wintypes
|
|
22
|
+
class Counters(ctypes.Structure):
|
|
23
|
+
_fields_ = [('cb',wintypes.DWORD),('PageFaultCount',wintypes.DWORD)] + [(name,ctypes.c_size_t) for name in (
|
|
24
|
+
'PeakWorkingSetSize','WorkingSetSize','QuotaPeakPagedPoolUsage','QuotaPagedPoolUsage',
|
|
25
|
+
'QuotaPeakNonPagedPoolUsage','QuotaNonPagedPoolUsage','PagefileUsage','PeakPagefileUsage')]
|
|
26
|
+
counters=Counters();counters.cb=ctypes.sizeof(counters)
|
|
27
|
+
kernel=ctypes.WinDLL('kernel32',use_last_error=True)
|
|
28
|
+
kernel.GetCurrentProcess.restype=wintypes.HANDLE
|
|
29
|
+
psapi=ctypes.WinDLL('psapi',use_last_error=True)
|
|
30
|
+
psapi.GetProcessMemoryInfo.argtypes=[wintypes.HANDLE,ctypes.POINTER(Counters),wintypes.DWORD]
|
|
31
|
+
if not psapi.GetProcessMemoryInfo(kernel.GetCurrentProcess(),ctypes.byref(counters),counters.cb):
|
|
32
|
+
raise ctypes.WinError(ctypes.get_last_error())
|
|
33
|
+
return counters.PeakWorkingSetSize
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def worker(path,profiles):
|
|
37
|
+
import lief
|
|
38
|
+
from libidentifier import identify
|
|
39
|
+
started=time.perf_counter();result=identify(path,profiles=profiles)
|
|
40
|
+
return {'input':result.input.to_dict(),'tool_version':result.tool_version,'python':sys.version.split()[0],
|
|
41
|
+
'lief':lief.__version__,'profile_database':result.profile_database.to_dict(),
|
|
42
|
+
'seconds':time.perf_counter()-started,'peak_rss_bytes':peak_rss(),
|
|
43
|
+
'classes':result.coverage.analyzed_count['classes'],'unknown':result.coverage.unknown_classes_total,
|
|
44
|
+
'clusters':len(result.unattributed_clusters),'relationships':len(result.relationships),
|
|
45
|
+
'analysis_runs':[r.to_dict() for r in result.analysis_runs],
|
|
46
|
+
'errors':[e.to_dict() for e in result.errors],
|
|
47
|
+
'components':[{'family_purl':c.family_purl,'version':c.version} for c in result.components]}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def quality(rows, samples):
|
|
51
|
+
tp=fp=fn=exact=correct=known=0
|
|
52
|
+
for row,sample in zip(rows,samples):
|
|
53
|
+
if not sample.get('ground_truth_complete'):
|
|
54
|
+
continue
|
|
55
|
+
expected={c['family_purl']:c.get('version') for c in sample['components']}
|
|
56
|
+
observed={c['family_purl']:c['version'] for c in row['components']}
|
|
57
|
+
tp+=len(expected.keys()&observed.keys());fp+=len(observed.keys()-expected.keys());fn+=len(expected.keys()-observed.keys())
|
|
58
|
+
known+=sum(v is not None for v in expected.values())
|
|
59
|
+
for family,version in observed.items():
|
|
60
|
+
if version is not None:
|
|
61
|
+
exact+=1;correct+=family in expected and expected[family]==version
|
|
62
|
+
return {'family_true_positive':tp,'family_false_positive':fp,'family_false_negative':fn,
|
|
63
|
+
'exact_version_predictions':exact,'correct_exact_versions':correct,'ground_truth_versioned_components':known,
|
|
64
|
+
'family_precision':tp/(tp+fp) if tp+fp else None,'family_recall':tp/(tp+fn) if tp+fn else None,
|
|
65
|
+
'exact_version_precision':correct/exact if exact else None,'exact_version_coverage':correct/known if known else None}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def main():
|
|
69
|
+
parser=argparse.ArgumentParser();parser.add_argument('--profiles',required=True)
|
|
70
|
+
parser.add_argument('--corpus');parser.add_argument('--worker')
|
|
71
|
+
args=parser.parse_args()
|
|
72
|
+
if args.worker:
|
|
73
|
+
print(json.dumps(worker(args.worker,args.profiles)));return
|
|
74
|
+
corpus_path=Path(args.corpus).resolve();corpus=json.loads(corpus_path.read_text())
|
|
75
|
+
if corpus.get('schema_version')!=1:raise ValueError('Unsupported corpus schema')
|
|
76
|
+
rows=[]
|
|
77
|
+
for sample in corpus['samples']:
|
|
78
|
+
completed=subprocess.run([sys.executable,str(Path(__file__).resolve()),'--profiles',str(Path(args.profiles).resolve()),
|
|
79
|
+
'--worker',str((corpus_path.parent/sample['path']).resolve())],check=True,capture_output=True,text=True,encoding='utf-8',timeout=300)
|
|
80
|
+
rows.append(json.loads(completed.stdout))
|
|
81
|
+
print(json.dumps({'schema_version':1,'platform':sys.platform,'samples':rows,'quality':quality(rows,corpus['samples'])},indent=2))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__=='__main__':main()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"references": [
|
|
4
|
+
{
|
|
5
|
+
"purl": "pkg:maven/example/library@1.0.0",
|
|
6
|
+
"path": "reference-artifacts/library-1.0.0.dex",
|
|
7
|
+
"sha256": "<verified-reference-hash>",
|
|
8
|
+
"license": "Apache-2.0",
|
|
9
|
+
"provenance_url": "https://example.invalid/reference"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"fingerprint_algorithm": "dex-shape-v2-canonical+elf-identity-v1",
|
|
4
|
+
"references": [
|
|
5
|
+
{
|
|
6
|
+
"purl": "pkg:maven/com.google.code.gson/gson@2.11.0",
|
|
7
|
+
"repository": "maven-central",
|
|
8
|
+
"url": "https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.11.0/gson-2.11.0.jar",
|
|
9
|
+
"sha256": "57928d6e5a6edeb2abd3770a8f95ba44dce45f3b23b7a9dc2b309c581552a78b",
|
|
10
|
+
"license": "Apache-2.0"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"purl": "pkg:maven/commons-io/commons-io@2.16.1",
|
|
14
|
+
"repository": "maven-central",
|
|
15
|
+
"url": "https://repo.maven.apache.org/maven2/commons-io/commons-io/2.16.1/commons-io-2.16.1.jar",
|
|
16
|
+
"sha256": "f41f7baacd716896447ace9758621f62c1c6b0a91d89acee488da26fc477c84f",
|
|
17
|
+
"license": "Apache-2.0"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"purl": "pkg:maven/com.squareup.retrofit2/retrofit@2.9.0",
|
|
21
|
+
"repository": "maven-central",
|
|
22
|
+
"url": "https://repo.maven.apache.org/maven2/com/squareup/retrofit2/retrofit/2.9.0/retrofit-2.9.0.jar",
|
|
23
|
+
"sha256": "e6ea1929c46852f5bec66ab3357da383476cef4e8d1deefdbf195b79cc4d6581",
|
|
24
|
+
"license": "Apache-2.0"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"purl": "pkg:maven/com.squareup.retrofit2/converter-gson@2.9.0",
|
|
28
|
+
"repository": "maven-central",
|
|
29
|
+
"url": "https://repo.maven.apache.org/maven2/com/squareup/retrofit2/converter-gson/2.9.0/converter-gson-2.9.0.jar",
|
|
30
|
+
"sha256": "32aa206b9a29c9df5eda93a092cfb3b0b9133e232c062baa882f0319f0e79f0e",
|
|
31
|
+
"license": "Apache-2.0"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"purl": "pkg:maven/com.squareup.okhttp3/okhttp@4.9.0",
|
|
35
|
+
"repository": "maven-central",
|
|
36
|
+
"url": "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/4.9.0/okhttp-4.9.0.jar",
|
|
37
|
+
"sha256": "dbc2bb04ecb002b9f4046263ccad996f4a3d3c59a0cc98837e300a6700571f7c",
|
|
38
|
+
"license": "Apache-2.0"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"purl": "pkg:maven/com.squareup.okhttp3/okhttp@4.9.3",
|
|
42
|
+
"repository": "maven-central",
|
|
43
|
+
"url": "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/4.9.3/okhttp-4.9.3.jar",
|
|
44
|
+
"sha256": "93ecd6cba19d87dccfe566ec848d91aae799e3cf16c00709358ea69bd9227219",
|
|
45
|
+
"license": "Apache-2.0"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"purl": "pkg:maven/com.scottyab/rootbeer-lib@0.0.8",
|
|
49
|
+
"repository": "maven-central",
|
|
50
|
+
"url": "https://repo.maven.apache.org/maven2/com/scottyab/rootbeer-lib/0.0.8/rootbeer-lib-0.0.8.aar",
|
|
51
|
+
"sha256": "4750bedff6605ed4ca96e2dd9b13fd6216ba55eb7abf914cbd9f9f00566ad82a",
|
|
52
|
+
"license": "Apache-2.0"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"purl": "pkg:maven/com.squareup.okhttp3/okhttp@3.14.9",
|
|
56
|
+
"repository": "maven-central",
|
|
57
|
+
"url": "https://repo.maven.apache.org/maven2/com/squareup/okhttp3/okhttp/3.14.9/okhttp-3.14.9.jar",
|
|
58
|
+
"sha256": "2570fab55515cbf881d7a4ceef49fc515490bc027057e666776a2832465aeca0",
|
|
59
|
+
"license": "Apache-2.0",
|
|
60
|
+
"notes": "Targeted SCA validation against the dependency declared by Retrofit 2.9.0; not an installed-version claim"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
LibIdentifier is API-first. The CLI delegates to the same `identify()`, `inspect()`, `build_profile()`, and `export_cyclonedx()` functions exposed from `libidentifier`.
|
|
4
|
+
|
|
5
|
+
The scan pipeline is:
|
|
6
|
+
|
|
7
|
+
1. Detect top-level format from magic bytes.
|
|
8
|
+
2. Traverse ZIP/APK members with bounded, safe reads.
|
|
9
|
+
3. Extract DEX class features and ELF identity features with LIEF. A bounded
|
|
10
|
+
standard DEX table reader supplies canonical descriptors, interface lists,
|
|
11
|
+
method references and code-item locations unavailable in LIEF's Python API.
|
|
12
|
+
4. Convert features to deterministic fingerprints.
|
|
13
|
+
5. Query a local read-only SQLite profile database.
|
|
14
|
+
6. Score candidates conservatively and resolve location-aware ownership claims.
|
|
15
|
+
Conflicting claims, shape multiplicity ambiguity and duplicate descriptors
|
|
16
|
+
remain unattributed for component-edge aggregation.
|
|
17
|
+
7. Extract structural/signature relationships and bounded explicit invocation
|
|
18
|
+
references; aggregate only uniquely attributed embedded endpoints.
|
|
19
|
+
8. Group unmatched definitions deterministically by meaningful exact packages
|
|
20
|
+
and inheritance/interface links. Preserve singleton groups and unknown origin.
|
|
21
|
+
9. Attach published reference declarations and supported embedded Maven version
|
|
22
|
+
metadata, reporting capability status, evidence, uncertainty and limitations.
|
|
23
|
+
10. Emit deterministic JSON; unknown-output caps apply after enrichment.
|
|
24
|
+
|
|
25
|
+
The package has no dependency on any consuming application. Optional `scan()`/`correlate()` assessment
|
|
26
|
+
uses a verified local OSV executable and advisory snapshot. Python scan APIs never
|
|
27
|
+
download; the assessment CLI may provision a wholly absent database unless
|
|
28
|
+
`--offline`. Existing databases require explicit update. Assessment itself always
|
|
29
|
+
runs offline. Hosts retain application ownership, reachability and exploitability
|
|
30
|
+
decisions. See the [public contract](integration.md) and [roadmap](development/roadmap.md).
|
|
31
|
+
|
|
32
|
+
`extractors/instructions.py` traverses standard DEX widths and switch/array
|
|
33
|
+
payloads. Ordinary invoke/range forms yield declared references with absolute
|
|
34
|
+
member byte offsets; special dynamic formats and undecodable methods report
|
|
35
|
+
partial coverage. No runtime dispatch, execution, reachability or data-flow is
|
|
36
|
+
inferred. External/ambiguous targets have no embedded target location.
|
|
37
|
+
|
|
38
|
+
`profiles/pom.py` handles direct dependencies/local properties only. Parent,
|
|
39
|
+
BOM, dependency-management and profile context remains preserved but unresolved.
|
|
40
|
+
Source release declarations stay distinct from observed APK code references.
|
|
41
|
+
See [profile storage](profile-database.md) for internal schema/rebuild rules.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
`cli_setup.py` is a CLI-only orchestration layer for managed scans without profile
|
|
45
|
+
overrides. It gathers missing resources, obtains one consent decision, invokes
|
|
46
|
+
explicit profile/advisory maintenance and installs a scanner pinned by
|
|
47
|
+
`cli_resources.py`. Scanner bytes are bounded and checked before execution.
|
|
48
|
+
The same pin catalog is used by native CI; no GitHub latest lookup occurs.
|
|
49
|
+
After setup the managed assessment path is forced offline, including when setup
|
|
50
|
+
was declined or failed. Existing explicit commands and analysis APIs keep their
|
|
51
|
+
previous resource policies.
|