Skip to content

🛡️ Sentry: Harden hybrid search against NaN and DoS#1013

Open
madmax983 wants to merge 2 commits intotrunkfrom
sentry-hybrid-hardening-4029855929144920958
Open

🛡️ Sentry: Harden hybrid search against NaN and DoS#1013
madmax983 wants to merge 2 commits intotrunkfrom
sentry-hybrid-hardening-4029855929144920958

Conversation

@madmax983
Copy link
Owner

Hardened the hybrid search (traverse_and_rank) and semantic pathfinding logic against invalid vector data (NaNs) and excessive resource consumption.

Changes:

  • traverse_and_rank now validates k against MAX_HYBRID_K (100,000) to prevent OOM DoS.
  • traverse_and_rank filters out candidates with NaN similarity scores (which can occur from corrupted stored data) to prevent undefined sorting behavior.
  • SemanticPathfinder::calculate_semantic_cost now returns a safe fallback cost (1.0) when cosine_similarity returns NaN, preventing priority queue corruption.
  • Added comprehensive tests in src/query/hybrid.rs and src/query/semantic_pathfinding.rs verifying these fixes, including tests that bypass standard validation to simulate data corruption.

PR created automatically by Jules for task 4029855929144920958 started by @madmax983

- `src/query/hybrid.rs`: Added `MAX_HYBRID_K` limit (100,000) and filtered NaNs from `traverse_and_rank`.
- `src/query/semantic_pathfinding.rs`: Handled NaN similarity in `calculate_semantic_cost` by using max cost.
- Added regression tests for NaN handling and `k` limit enforcement.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @madmax983, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and security of the system's search and pathfinding functionalities. It introduces mechanisms to prevent denial-of-service attacks by limiting resource consumption and ensures stable operation when encountering invalid or corrupted vector data, specifically floating-point NaN values, which could otherwise lead to unpredictable behavior or system crashes.

Highlights

  • DoS Prevention: The traverse_and_rank function now includes validation for the k parameter, limiting it to MAX_HYBRID_K (100,000) to prevent potential out-of-memory denial-of-service attacks.
  • NaN Handling in Hybrid Search: The traverse_and_rank function has been updated to filter out search candidates that result in NaN similarity scores, which can arise from corrupted vector data, ensuring predictable sorting behavior.
  • NaN Handling in Semantic Pathfinding: The SemanticPathfinder::calculate_semantic_cost method now gracefully handles NaN results from cosine_similarity by returning a default high cost of 1.0, preventing priority queue corruption.
  • Enhanced Test Coverage: New comprehensive tests have been added to src/query/hybrid.rs and src/query/semantic_pathfinding.rs to specifically verify the robustness of these fixes, including scenarios simulating data corruption with NaN values.
Changelog
  • src/query/hybrid.rs
    • Introduced MAX_HYBRID_K constant to define the maximum allowed k value.
    • Added validation for the k parameter in traverse_and_rank to prevent excessive resource usage.
    • Implemented filtering of NaN similarity scores in traverse_and_rank to avoid undefined sorting.
    • Added new test cases to verify NaN handling and k limit enforcement.
  • src/query/semantic_pathfinding.rs
    • Modified calculate_semantic_cost to return a fallback cost of 1.0 when cosine_similarity yields NaN.
    • Added a new test case to confirm correct behavior of semantic pathfinding with NaN embeddings.
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively hardens the hybrid search and semantic pathfinding functionalities against potential DoS attacks and data corruption issues. It introduces a limit on the k parameter in traverse_and_rank to prevent memory exhaustion and adds robust handling for NaN similarity scores in both traverse_and_rank and SemanticPathfinder. The accompanying tests are comprehensive and validate the new hardening measures. The feedback regarding duplicated logic for NaN handling in semantic_pathfinding.rs remains a valid point for refactoring to improve maintainability.

Comment on lines 254 to 264
let semantic_cost = if let Some(emb) = target_embedding {
1.0 - cosine_similarity(emb, query_embedding)?
let sim = cosine_similarity(emb, query_embedding)?;
// SENTRY: Handle NaN similarity by assigning high cost
if sim.is_nan() {
1.0
} else {
1.0 - sim
}
} else {
1.0 // High cost if no embedding
};
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's a duplication of logic for calculating semantic cost here and in the calculate_semantic_cost function. Both now handle NaN similarity scores by assigning a high cost, but they do so in separate implementations. This could lead to maintenance issues if one is updated and the other is forgotten.

To improve maintainability and reduce code duplication, consider refactoring this logic into a shared helper function. This function could take an Option< &[f32]> embedding and the query embedding, and return the calculated cost. Both find_path_at_time and calculate_semantic_cost could then call this helper.

For example:

fn calculate_semantic_cost_from_embedding(embedding: Option< &[f32]>, query: &[f32]) -> Result<f32> {
    if let Some(emb) = embedding {
        let sim = cosine_similarity(emb, query)?;
        if sim.is_nan() {
            Ok(1.0)
        } else {
            Ok(1.0 - sim)
        }
    } else {
        Ok(1.0)
    }
}

Then find_path_at_time could be simplified to:

let semantic_cost = calculate_semantic_cost_from_embedding(target_embedding, query_embedding)?;

And calculate_semantic_cost could also be refactored to use this helper.

@github-actions
Copy link

🚀 Benchmark Results

Benchmarks have been run for this PR.

📊 Performance Summary (Top 10)

Benchmark Base (trunk) New (PR) Change % Std Dev
target_3_hop/traverse_three_hops N/A 160.47 ns New ± 4.41 ns
target_batch_insertion/insert_1000_edges N/A 366.03 µs New ± 10.12 µs
target_single_hop/traverse_one_hop N/A 19.66 ns New ± 2.72 ns
target_time_travel/at_anchor N/A 213.41 ns New ± 1.77 ns
target_time_travel/with_5_deltas N/A 212.71 ns New ± 2.86 ns
target_time_travel/worst_case_9_deltas N/A 220.75 ns New ± 4.94 ns

Full benchmark results available in workflow artifacts

📊 View detailed results

@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

❌ Patch coverage is 95.74468% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.05%. Comparing base (ee7793e) to head (16e0f5b).

Files with missing lines Patch % Lines
src/query/hybrid.rs 92.15% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##            trunk    #1013      +/-   ##
==========================================
+ Coverage   92.03%   92.05%   +0.02%     
==========================================
  Files         126      126              
  Lines       72697    72994     +297     
==========================================
+ Hits        66904    67197     +293     
- Misses       5793     5797       +4     
Flag Coverage Δ
unittests 92.05% <95.74%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/query/semantic_pathfinding.rs 92.85% <100.00%> (+1.02%) ⬆️
src/query/hybrid.rs 97.74% <92.15%> (+0.15%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ace42cb22f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +298 to +299
if sim.is_nan() {
return Ok(1.0);

Choose a reason for hiding this comment

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

P2 Badge Validate query embeddings before masking NaN similarities

The new sim.is_nan() fallback in calculate_semantic_cost turns invalid query vectors into a normal cost (1.0) instead of surfacing an error. Because sim can be NaN when the caller-provided query contains NaN/Inf values, find_path (and the analogous temporal branch) can now return an apparently valid path for malformed input, producing misleading semantic results rather than failing fast. Please validate query_embedding at the API boundary (or return an error when similarity is NaN) so this guard only handles corrupted stored node embeddings.

Useful? React with 👍 / 👎.

Ran `cargo fmt` to resolve CI linting failures in `src/query/hybrid.rs` and `src/query/semantic_pathfinding.rs`.
Verified with `cargo clippy`.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@github-actions
Copy link

🚀 Benchmark Results

Benchmarks have been run for this PR.

📊 Performance Summary (Top 10)

Benchmark Base (trunk) New (PR) Change % Std Dev
target_3_hop/traverse_three_hops N/A 151.08 ns New ± 4.51 ns
target_batch_insertion/insert_1000_edges N/A 362.28 µs New ± 7.66 µs
target_single_hop/traverse_one_hop N/A 19.02 ns New ± 0.62 ns
target_time_travel/at_anchor N/A 218.37 ns New ± 5.77 ns
target_time_travel/with_5_deltas N/A 216.67 ns New ± 5.47 ns
target_time_travel/worst_case_9_deltas N/A 224.24 ns New ± 4.61 ns

Full benchmark results available in workflow artifacts

📊 View detailed results

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant