Skip to content

[FEATURE/CORE-ENGINE] Extract a shared, scope-aware spatial correlation primitive and make threat_locations the persisted ledger #346

Closed

Description

@squid-protocol

🛑 Problem Statement

The "spatial taint tracker" this epic (#102) wants fully integrated currently exists as three independent, disconnected systems:

  1. detector.py::_correlate_signals — a char-offset proximity sweep, used inline six separate times inside coding_analysis(), each hand-written for one specific signal pair. Its raw position data (spatial_map) is discarded the moment coding_analysis() returns.
  2. security_lens.py::scan_content — a genuine variable-identity echo check (tracks assigned variable names across threat-flagged lines), with its own siloed line-position math that never leaves the file.
  3. threat_locations — a rule_name -> [line_numbers] dict that does survive to the end of the pipeline (into telemetry, SARIF, etc.), but nothing correlates against it today. It's write-only.

None of the six existing _correlate_signals calls have access to real function-level scope, because coding_analysis() (where they run) executes before _function_slice() (which computes satellite/function boundaries) in detector.py::splice(). They all use a flat character radius as a scope proxy, which produces both false positives (radius bleeds into a neighboring short function) and false negatives (a real same-function correlation exceeds the radius in a long function) — notably on the dampener side (safety/danger, sync_locks/concurrency, cleanup/memory_alloc), where a scope error silently suppresses real risk rather than just adding noise.

This also blocks #105 and #106 as currently written: both propose a new one-off correlation inside coding_analysis/prism.py, but #106's consumer (dev_agent_firewall.py) runs post-hoc over parsed_files at the same late pipeline stage as ai_appsec_sensor.py (galaxyscope.py:802-806) — well after coding_analysis()'s transient spatial_map is gone. A post-hoc tool structurally cannot consume spatial_map; it can only consume whatever survives into telemetry/threat_locations. So #106 cannot be implemented as literally scoped without this landing first.

🎯 Objective

Replace the three disconnected systems with one shared, reusable, scope-aware correlation primitive, and one persisted spatial ledger that survives to every pipeline stage — not just internal to detector.py.

🛠️ Proposed Implementation

  • Split detect from correlate: Move all spatial correlation (the six existing _correlate_signals calls) into a new pass that runs after both coding_analysis() and _function_slice(), so it can filter each signal's hit positions down to the owning satellite's [start_idx, end_idx] before correlating — instead of running mid-scan before satellites exist.
  • Extract the primitive: Pull _correlate_signals out of detector.py into its own module so it's callable from post-hoc tools (dev_agent_firewall.py, ai_appsec_sensor.py, signal_processor.py), not just from inside coding_analysis.
  • Upgrade the ledger: Extend threat_locations to carry char offset and owning-satellite/function id per hit, not just line number, and merge security_lens.py's already-computed line positions (e.g. for db_hooks) into it instead of discarding them after producing a flat count.
  • Migrate the six existing calls onto the new primitive, prioritizing the three dampener pairs first (safety/danger, sync_locks/concurrency, cleanup/memory_alloc) since scope errors there are false negatives, not just noise.

✅ Acceptance Criteria

Part of #102. Depends on #344 landing first (trusting sec_tainted_injection before building more on top of it).

Activity

  1. added
    enhancementNew feature, sensor, or structural signature
    appsecAgentic guardrails, prompt injection, and RCE sensors
    core-engineModifications to the central physics and parsing engine
    on Jul 24, 2026
  2. squid-protocol commented on Jul 24, 2026

    @squid-protocol
    OwnerAuthor

    Splitting this into two smaller PRs rather than one large one, to ship the safety-critical part sooner with lower regression risk.

    This issue (346) now covers phase 1 only:

    • Extract _correlate_signals into a shared module.
    • Scope the three dampener pairs (safety/danger, sync_locks/concurrency, cleanup/memory_alloc) to require the mitigation fall within the same satellite/function, not just the flat character radius — this is the false-negative risk (a wrong-scope mitigation silently suppressing real risk), which was the main correctness argument for this work. The existing flat-radius behavior remains the fallback for code outside any detected satellite, so this is strictly additive/stricter, not a capability regression.
    • The three amplifier-only pairs are left as-is for now — a false positive there just costs one extra review item, which is an accepted tradeoff already, so scoping them isn't safety-critical the way the dampener side is.

    Phase 2, filed separately as #348, covers what's actually needed to unblock #105/#106: persisting a satellite-aware ledger that survives to post-hoc pipeline stages (outside detector.py), folding in security_lens.py's own position data (e.g. db_hooks), and migrating the three amplifier pairs onto the same shared primitive.

    Starting on phase 1 now.

  3. squid-protocol commented on Jul 24, 2026

    @squid-protocol
    OwnerAuthor

    Opened PR #349 for phase 1 (the dampener-pair scoping fix described above). Phase 2 (persisted ledger, amplifier-pair scoping) stays tracked in #348.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    appsecAgentic guardrails, prompt injection, and RCE sensorscore-engineModifications to the central physics and parsing engineenhancementNew feature, sensor, or structural signature

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions