Skip to content

feat: replace Binary DB direct access with ldb_service API#212

Open
soimkim wants to merge 4 commits into
mainfrom
api
Open

feat: replace Binary DB direct access with ldb_service API#212
soimkim wants to merge 4 commits into
mainfrom
api

Conversation

@soimkim

@soimkim soimkim commented Jul 24, 2026

Copy link
Copy Markdown
Contributor
  • New Features
    • Binary metadata lookup now uses the knowledge-base service over HTTP.
    • Added support for configuring the knowledge-base URL and access token via command-line options (with environment-variable defaults).

Summary by CodeRabbit

  • New Features

    • Added HTTP-based binary OSS matching through the knowledge base service.
    • Added --kb_url and --kb_token command-line options, with environment-variable support.
    • Added chunked matching for large binary collections and graceful handling of unavailable endpoints or failed requests.
  • Chores

    • Removed the previous direct database lookup dependency and connection options.

@soimkim soimkim self-assigned this Jul 24, 2026
@soimkim soimkim added the enhancement [PR/Issue] New feature or request label Jul 24, 2026
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The binary scanner replaces PostgreSQL-based OSS lookup with chunked HTTP requests to ldb_service. KB URL and token options are added to the CLI and propagated through find_binaries, while PostgreSQL’s binary dependency is removed.

Changes

Binary Knowledge Base Migration

Layer / File(s) Summary
HTTP binary matching
src/fosslight_binary/_binary_dao.py
KB configuration, endpoint checks, chunked /binary/match requests, response aggregation, and OSS item enrichment are implemented.
KB configuration wiring
src/fosslight_binary/cli.py, src/fosslight_binary/binary_analysis.py, src/fosslight_binary/_help.py, pyproject.toml
CLI options, help text, analysis parameters, and dependency declarations are updated for the HTTP knowledge-base lookup.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant find_binaries
  participant BinaryDAO
  participant ldb_service
  CLI->>find_binaries: pass kb_url and kb_token
  find_binaries->>BinaryDAO: request OSS enrichment
  BinaryDAO->>ldb_service: probe and POST /binary/match
  ldb_service-->>BinaryDAO: return match results
  BinaryDAO-->>find_binaries: update matched binary items
Loading

Possibly related PRs

Suggested reviewers: bjk7119

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing direct Binary DB access with the ldb_service API.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/fosslight_binary/_binary_dao.py (1)

32-101: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add mocked coverage for the binary DB lookup path.

get_oss_info_from_db() is now wired into binary_analysis.py, but the test files only contain static schema/tox coverage. Mocked tests should cover chunk boundary payloads, mixed matched/unmatched results, malformed or failed POST /binary/match responses, and the JAR-oss-item preservation branch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_binary/_binary_dao.py` around lines 32 - 101, Add mocked tests
for get_oss_info_from_db covering payload chunking at _CHUNK_SIZE boundaries,
mixed matched and unmatched response results, malformed responses and failed
_post_binary_match calls, and preservation of existing JAR-derived OSS items.
Assert returned items and matched counts, using mocks for resolve_kb_config and
_post_binary_match without changing production behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/fosslight_binary/_binary_dao.py`:
- Line 20: Require HTTPS for KB requests carrying bearer tokens: update
DEFAULT_KB_URL in src/fosslight_binary/_binary_dao.py at lines 20-20 to the
HTTPS endpoint and add URL validation that rejects non-HTTPS URLs, allowing only
an explicitly documented local-development exception if necessary. Update the
documented example in src/fosslight_binary/_help.py at lines 53-53 to use HTTPS.
- Line 23: Update the BINARY_MATCH_CHUNK_SIZE initialization to parse the
environment value safely with a fallback, and require the resulting chunk size
to be greater than zero before using it. Preserve the default behavior for
missing or invalid values so module import and chunk iteration cannot fail or
skip matching.

---

Nitpick comments:
In `@src/fosslight_binary/_binary_dao.py`:
- Around line 32-101: Add mocked tests for get_oss_info_from_db covering payload
chunking at _CHUNK_SIZE boundaries, mixed matched and unmatched response
results, malformed responses and failed _post_binary_match calls, and
preservation of existing JAR-derived OSS items. Assert returned items and
matched counts, using mocks for resolve_kb_config and _post_binary_match without
changing production behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1db35e6f-6090-4a89-8d6d-feec2033909b

📥 Commits

Reviewing files that changed from the base of the PR and between ca176b0 and 2b2fcf7.

📒 Files selected for processing (5)
  • pyproject.toml
  • src/fosslight_binary/_binary_dao.py
  • src/fosslight_binary/_help.py
  • src/fosslight_binary/binary_analysis.py
  • src/fosslight_binary/cli.py
💤 Files with no reviewable changes (1)
  • pyproject.toml

logger = logging.getLogger(constant.LOGGER_NAME)
DB_URL_DEFAULT = "postgresql://bin_analysis_script_user:script_123@bat.lge.com:5432/bat"

DEFAULT_KB_URL = "http://fosslight-kb.lge.com/"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Require TLS for KB requests that may carry bearer tokens. The default and documented example use cleartext HTTP, while Line 114 attaches Authorization: Bearer ...; network observers can capture the token and submitted binary metadata.

  • src/fosslight_binary/_binary_dao.py#L20-L20: change the default to the HTTPS endpoint and reject non-HTTPS URLs (except an explicitly documented local-development exception, if needed).
  • src/fosslight_binary/_help.py#L53-L53: replace the HTTP example with HTTPS.
📍 Affects 2 files
  • src/fosslight_binary/_binary_dao.py#L20-L20 (this comment)
  • src/fosslight_binary/_help.py#L53-L53
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_binary/_binary_dao.py` at line 20, Require HTTPS for KB
requests carrying bearer tokens: update DEFAULT_KB_URL in
src/fosslight_binary/_binary_dao.py at lines 20-20 to the HTTPS endpoint and add
URL validation that rejects non-HTTPS URLs, allowing only an explicitly
documented local-development exception if necessary. Update the documented
example in src/fosslight_binary/_help.py at lines 53-53 to use HTTPS.

Source: Linters/SAST tools

Comment thread src/fosslight_binary/_binary_dao.py Outdated
soimkim added 2 commits July 24, 2026 14:48
Skip API lookup when KB URL is invalid, /health fails, or /binary/match
returns 404, and exclude flagged binaries from the match payload.
Fall back to 3000 with a warning when the env var is non-numeric or <= 0.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/fosslight_binary/_binary_dao.py (2)

163-200: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Simplify the jar-analysis skip: it enters the loop only to break immediately.

When item.found_in_jar_analysis is true, the loop starts, hits break on the very first oss_rows element and exits — so bin_oss_items never gets populated and the function returns False. Functionally fine, but written as an early-return would be clearer than looping-then-breaking-once.

♻️ Proposed refactor
 def _apply_match_result_to_item(item, result: dict) -> bool:
     """Apply a /binary/match result to one binary item. Returns True if matched."""
     if not result or not result.get("matched"):
         return False
+    if item.found_in_jar_analysis:
+        return False
     oss_rows = result.get("oss_items") or []
     if not oss_rows:
         return False

-    if not item.found_in_jar_analysis and item.oss_items:
+    if item.oss_items:
         item.oss_items = []

     bin_oss_items = []
     for row in oss_rows:
-        if item.found_in_jar_analysis:
-            break
         oss_from_db = OssItem(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_binary/_binary_dao.py` around lines 163 - 200, Update
_apply_match_result_to_item to return early when item.found_in_jar_analysis is
true, before iterating over oss_rows. Remove the redundant loop-level break
while preserving the existing False result and all normal OSS-item processing
for non-jar-analysis items.

68-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

URL/header construction is duplicated across three call sites.

check_kb_server_reachable, check_binary_match_endpoint, and _post_binary_match each independently build the request URL and set Accept/Content-Type/Authorization headers. Extracting a shared helper (e.g., _build_kb_request(kb_url, path, kb_token, data=None, method="GET")) would reduce the risk of the three implementations drifting (e.g., one gaining a header the others miss).

Also applies to: 98-104, 252-260

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_binary/_binary_dao.py` around lines 68 - 70, The request URL
and header setup is duplicated across check_kb_server_reachable,
check_binary_match_endpoint, and _post_binary_match. Add a shared helper such as
_build_kb_request that accepts the base URL, path, token, optional payload, and
method, then update all three call sites to use it while preserving their
existing headers, methods, and request data.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/fosslight_binary/_binary_dao.py`:
- Around line 202-247: Update get_oss_info_from_db so a failed chunk does not
return immediately and discard earlier results. Stop processing further chunks
when _post_binary_match returns None or response parsing raises, then continue
to the existing item-application loop so accumulated results_by_id are applied
and _cnt_auto_identified reflects successful chunks only.
- Around line 131-161: Update _build_deduped_payload so entries without a
checksum are never deduplicated or keyed together by filename; retain the
existing filename+checksum deduplication only when a checksum is present, while
preserving payload creation and API ID mapping for all items.

---

Nitpick comments:
In `@src/fosslight_binary/_binary_dao.py`:
- Around line 163-200: Update _apply_match_result_to_item to return early when
item.found_in_jar_analysis is true, before iterating over oss_rows. Remove the
redundant loop-level break while preserving the existing False result and all
normal OSS-item processing for non-jar-analysis items.
- Around line 68-70: The request URL and header setup is duplicated across
check_kb_server_reachable, check_binary_match_endpoint, and _post_binary_match.
Add a shared helper such as _build_kb_request that accepts the base URL, path,
token, optional payload, and method, then update all three call sites to use it
while preserving their existing headers, methods, and request data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 27556d2b-ebbb-4121-be86-cf44609638b6

📥 Commits

Reviewing files that changed from the base of the PR and between 2b2fcf7 and 4bcc950.

📒 Files selected for processing (5)
  • pyproject.toml
  • src/fosslight_binary/_binary_dao.py
  • src/fosslight_binary/_help.py
  • src/fosslight_binary/binary_analysis.py
  • src/fosslight_binary/cli.py
💤 Files with no reviewable changes (1)
  • pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/fosslight_binary/_help.py
  • src/fosslight_binary/binary_analysis.py
  • src/fosslight_binary/cli.py

Comment on lines +131 to +161
def _match_key(filename: str, checksum: str) -> MatchKey:
return filename, checksum or ""


def _build_deduped_payload(
bin_info_list,
tlsh_null: str,
) -> Tuple[List[dict], Dict[MatchKey, str]]:
"""Deduplicate by filename+checksum; return API payload and key→api_id map."""
key_to_id: Dict[MatchKey, str] = {}
items_payload: List[dict] = []

for item in bin_info_list:
if item.exclude:
continue
filename = item.binary_name_without_path
checksum = item.checksum or ""
key = _match_key(filename, checksum)
if key in key_to_id:
continue
api_id = str(len(items_payload))
key_to_id[key] = api_id
items_payload.append({
"id": api_id,
"filename": filename,
"checksum": checksum,
"tlsh": item.tlsh or tlsh_null,
})

return items_payload, key_to_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Dedup key falls back to empty checksum, risking merged attribution for unrelated files.

checksum = item.checksum or "" means any items missing a checksum are deduped/keyed purely by filename. If two distinct binaries share a name but neither has a computed checksum, they collapse to one API entry/key and both receive the same OSS match — potentially wrong attribution for one of them.

♻️ Proposed fix: don't dedup entries lacking a checksum
     for item in bin_info_list:
         if item.exclude:
             continue
         filename = item.binary_name_without_path
         checksum = item.checksum or ""
-        key = _match_key(filename, checksum)
-        if key in key_to_id:
-            continue
-        api_id = str(len(items_payload))
-        key_to_id[key] = api_id
+        key = _match_key(filename, checksum) if checksum else (filename, f"__noref_{len(items_payload)}")
+        if checksum and key in key_to_id:
+            continue
+        api_id = str(len(items_payload))
+        key_to_id[key] = api_id
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _match_key(filename: str, checksum: str) -> MatchKey:
return filename, checksum or ""
def _build_deduped_payload(
bin_info_list,
tlsh_null: str,
) -> Tuple[List[dict], Dict[MatchKey, str]]:
"""Deduplicate by filename+checksum; return API payload and key→api_id map."""
key_to_id: Dict[MatchKey, str] = {}
items_payload: List[dict] = []
for item in bin_info_list:
if item.exclude:
continue
filename = item.binary_name_without_path
checksum = item.checksum or ""
key = _match_key(filename, checksum)
if key in key_to_id:
continue
api_id = str(len(items_payload))
key_to_id[key] = api_id
items_payload.append({
"id": api_id,
"filename": filename,
"checksum": checksum,
"tlsh": item.tlsh or tlsh_null,
})
return items_payload, key_to_id
def _match_key(filename: str, checksum: str) -> MatchKey:
return filename, checksum or ""
def _build_deduped_payload(
bin_info_list,
tlsh_null: str,
) -> Tuple[List[dict], Dict[MatchKey, str]]:
"""Deduplicate by filename+checksum; return API payload and key→api_id map."""
key_to_id: Dict[MatchKey, str] = {}
items_payload: List[dict] = []
for item in bin_info_list:
if item.exclude:
continue
filename = item.binary_name_without_path
checksum = item.checksum or ""
key = _match_key(filename, checksum) if checksum else (filename, f"__noref_{len(items_payload)}")
if checksum and key in key_to_id:
continue
api_id = str(len(items_payload))
key_to_id[key] = api_id
items_payload.append({
"id": api_id,
"filename": filename,
"checksum": checksum,
"tlsh": item.tlsh or tlsh_null,
})
return items_payload, key_to_id
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_binary/_binary_dao.py` around lines 131 - 161, Update
_build_deduped_payload so entries without a checksum are never deduplicated or
keyed together by filename; retain the existing filename+checksum deduplication
only when a checksum is present, while preserving payload creation and API ID
mapping for all items.

Comment thread src/fosslight_binary/_binary_dao.py
Drop the /health pre-check, continue remaining chunks after a failed
chunk, and still apply results collected so far.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/fosslight_binary/_binary_dao.py`:
- Around line 197-202: Move the try/except handling in the binary match
chunk-processing loop so each iteration is independently protected. Ensure
errors from response processing, including response.get in the chunk flow, are
logged by the existing warning and continue to the next chunk without aborting
later processing; preserve accumulated results.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8199bc3f-8779-4753-be35-abd532ad30a9

📥 Commits

Reviewing files that changed from the base of the PR and between 4bcc950 and c126f80.

📒 Files selected for processing (1)
  • src/fosslight_binary/_binary_dao.py

Comment on lines +197 to +202
logger.warning(
f"Binary match chunk failed "
f"({chunk_start}:{chunk_start + len(chunk)}); "
"keeping results so far and continuing with next chunks."
)
continue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Catch response-processing errors per chunk.

The try still wraps the entire loop (Lines 192-206). A malformed successful response—for example, a JSON array causing response.get(...) to raise—exits the loop and skips every later chunk. Move the try inside the loop so this failure follows the stated “continue with next chunks” behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/fosslight_binary/_binary_dao.py` around lines 197 - 202, Move the
try/except handling in the binary match chunk-processing loop so each iteration
is independently protected. Ensure errors from response processing, including
response.get in the chunk flow, are logged by the existing warning and continue
to the next chunk without aborting later processing; preserve accumulated
results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement [PR/Issue] New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant