Repository navigation
Description
Problem: SCA reachability today is a static guess. The sca-reachability skill reads the code and labels each vulnerable dependency Reachable, Conditionally reachable or Not reachable (sca_findings.reachability). Nothing confirms whether the vulnerable code actually runs, or whether real traffic reaches it in the applications Secfoo has threat-modeled and assessed.
Why: Secfoo exists to cut security impact at the developer stage. Static findings are many, and developers need to know which ones to fix first. Runtime evidence from the deployed app answers that, and feeds it back into the developer's CLI, PR and CI (#80).
Who and how: a DevOps engineer:
- connects once with
secfoo cloud login --api-key <key>; - scans the code with
secfoo run; - optionally, deploys the runtime sensor as a sidecar (or another mode in Deploy the runtime sensor anywhere: containers, Kubernetes, VMs, Windows, PaaS, serverless #71) with the same API key;
- sees every issue for the project in one place: SAST, SCA and threat model findings, with runtime evidence attached (Runtime evidence in the SCA dashboard #57, Runtime page: sensor health, live activity and alerts #72), plus the same view in the CLI (Runtime evidence at the developer stage: CLI, SARIF and CI gate #80).
Goal: a lightweight, observe-only sensor that runs alongside the user's application in production (or staging), whatever its runtime and wherever it is deployed: containers, Kubernetes, VMs, Windows hosts, PaaS or serverless. It records which vulnerable packages are loaded, which vulnerable functions are called, which live routes reach them, and how much of the app the observed traffic covered. Results attach to the existing SCA findings and threat models as runtime evidence, in near real time.
Runtime evidence ladder. Each step is stronger evidence than the one before:
| State | Meaning | Source |
|---|---|---|
| Present | In the scanned manifest/lockfile | existing SCA run |
| Loaded | Package and version loaded in a running process | #68 |
| Executed | A watched vulnerable symbol was called | runtime probes (below), #54 |
| Reached from traffic | Called while handling an inbound request, on route X, anonymous or authenticated | #69 |
| Reached via exposed entry point | That route is a threat-model entry point on an internet-facing boundary | #70 |
Architecture:
OSV / GHSA advisories ──► watchlist (#52) ◄── GET /api/runtime/v1/watchlist
│
app process ── in-process probe (any runtime) ── #73 protocol ──► secfoo sensor (#67)
(count, sample, route tag) unix socket / tcp loopback / pipe (sidecar / host daemon / extension)
or direct HTTPS (serverless)
│ HTTPS batches
coverage files (#54) ── secfoo runtime ingest ──┐ ▼
└──► events (#53) ──► secfoo serve (#66)
│
SCA dashboard (#57) · threat model correlation (#70) · runtime page & alerts (#72)
The probe inside the app stays thin. Aggregation, buffering, the watchlist and the network all live in the separate sensor process. The sensor is the same for every runtime, and only the thin probe is runtime-specific. Every probe speaks one protocol and passes one conformance kit (#73). Deployment covers sidecar, host daemon, direct (serverless/PaaS) and offline modes (#71).
Runtime support:
| Runtime | Loaded (inventory) | Executed (function hits) | Routes | Issue |
|---|---|---|---|---|
| Python 3.10+ | importlib.metadata |
sys.monitoring / setprofile |
WSGI/ASGI, FastAPI, Flask, Django | #55 |
| Node.js 18+ | package.json per resolved module |
CJS/ESM loader hooks | Express, Fastify | #56 |
| JVM 8+ (Java, Kotlin, Scala) | jar → Maven coordinates | -javaagent bytecode |
Servlet, Spring, JAX-RS | #74 |
| .NET 6+ (Framework 4.x limited) | deps.json → NuGet |
CLR profiler ReJIT | ASP.NET Core | #75 |
| Go, Rust, native | embedded build metadata | eBPF uprobes (Linux, opt-in) | net/http, gin, chi, echo middleware |
#76 |
| Ruby 3.0+ | Gem.loaded_specs |
targeted TracePoint |
Rack, Rails, Sinatra | #77 |
| PHP 8.0+ | Composer installed.json |
observer-API extension | Laravel, Symfony, WordPress | #78 |
Design rules (they apply to every sub-issue):
0. Explicit opt-in only. Nothing installs, injects or starts a sensor by default. Installing Secfoo (pip, npm, binaries, the CLI image) or running secfoo run never adds a probe or sidecar. A sensor runs only where the user deliberately deploys it, and a probe does nothing unless SECFOO_SENSOR=1 is set. Without a sensor, Secfoo works exactly as before, and findings show "No runtime data".
- Observe-only. The sensor never changes behavior, blocks requests or alters return values.
- Fail-open. Any sensor error is swallowed and logged once. The app must never crash or slow down noticeably because of it. Target: at most 1 ms p99 added latency per request.
- No argument values by default. Record function identity, counts, timestamps, stack frames, the route template and an anonymous/authenticated flag only. Never record arguments, return values, request bodies, concrete URLs, header values or user identity, which can contain secrets or personal data.
- "Not observed" never means "not reachable". Every "not observed" or "not loaded" verdict is shown next to the run's coverage and observation window.
- Goes only where your key points. Evidence goes to a local file, or to the server the user's Secfoo API key belongs to: the same place
secfoo cloudsends runs, or a self-hostedsecfoo serve. Nothing is sent anywhere without an explicitly configured key and server, and never to any third party.
Sub-issues. Phase 1 (offline evidence) needs the formats in #52 and #53 agreed first, then the rest can be built in parallel:
- Build a vulnerable-function watchlist from advisories #52 Vulnerable-function watchlist
- Runtime evidence format, storage and
secfoo runtime ingest#53 Evidence format, storage,secfoo runtime ingest - Import coverage files as runtime evidence #54 Import coverage files
- Python live sensor (
sys.monitoring) #55 Python probe - Node.js live sensor (
--requirehook) #56 Node.js probe - Runtime evidence in the SCA dashboard #57 Runtime evidence in the SCA dashboard
Phase 2 (live sensor) builds on #53:
- Runtime ingest API: sensors use your Secfoo API key #66 Runtime ingest API: sensors use your Secfoo API key
- Standalone runtime sensor (
secfoo sensor) as sidecar or host daemon #67 Standalone sensor (secfoo sensor), sidecar or daemon - Runtime package inventory: loaded versions, drift and live advisories #68 Runtime package inventory, version drift, live advisories
- Attribute runtime hits to live traffic (route, auth state) #69 Attribute hits to live traffic (route, auth state)
- Correlate live traffic with the threat model's entry points #70 Correlate live traffic with threat model entry points
- Deploy the runtime sensor anywhere: containers, Kubernetes, VMs, Windows, PaaS, serverless #71 Deploy anywhere: containers, Kubernetes, VMs, Windows, PaaS, serverless
- Runtime page: sensor health, live activity and alerts #72 Runtime page: sensor health, live activity, alerts
- Probe ↔ sensor protocol and conformance kit (one contract for every runtime) #73 Probe ↔ sensor protocol and conformance kit
- Runtime evidence at the developer stage: CLI, SARIF and CI gate #80 Runtime evidence at the developer stage: CLI, SARIF and CI gate
Phase 3 (more runtimes) builds on #73:
- JVM probe (
-javaagent): Java, Kotlin, Scala #74 JVM probe - .NET probe: startup hook + CLR profiler #75 .NET probe
- Go, Rust and native binaries: inventory from build metadata, hits via uprobes #76 Go, Rust and native binaries
- Ruby probe (TracePoint): Rails, Sinatra, Rack #77 Ruby probe
- PHP probe: observer-API extension + no-extension mode #78 PHP probe
Out of scope for now: attack/exploit detection and blocking (RASP); eBPF tracing for interpreted runtimes (it can't reliably resolve Python, Node, Ruby or PHP functions, so it is used only for compiled binaries in #76); runtime AI-BOM (models and MCP servers observed at runtime); and multi-tenant SaaS aggregation. Separate issues can be opened for these later.
Activity
[-]Tracking: Runtime reachability for SCA[/-][+]Tracking: Runtime reachability for SCA (in-app probe + live sensor)[/+]fix: address issue secfoo-com#51