Skip to content

Matcher coverage: Falcon + async-grpc Ruby services (no web framework gate fires) #87

@mkamranii

Description

@mkamranii

The pattern

DeepSec's Ruby matchers (`rb-rails-controller`, `rb-sinatra-route`, `rb-grape-endpoint`, `rb-hanami-action`, `rb-roda-route`) are all gated on a request/response web framework being detected. Modern async-Ruby services that use Falcon as the server with async-grpc (or plain gRPC) for RPC don't trigger any of those gates, so no Ruby matchers activate and the LLM never gets candidates to investigate.

Concretely, on a Falcon/async-grpc service (~80 Ruby files), DeepSec produced:

```
[deepsec:scan] docker, github-actions, ruby
[deepsec:scan] ruby N files 0 hits 0.00%
⚠ Low matcher coverage for ruby (very low)
deepsec may not have built-in matchers for your ruby stack.
```

The only findings on the scan came from generic matchers (`github-workflow-security`, `dockerfile-from-mutable-tag`). The actual Ruby business logic was never investigated.

Example shapes worth catching

1. gRPC service entry points (the equivalent of a Rails controller action for these apps):

```ruby

lib/example_service.rb

class ExampleService < ::ExampleGen::Service
def lookup(request, call)
# ← request is attacker-controlled, call.metadata holds auth headers
# Equivalent role to a Rails controller action — but no gate fires today
BackendClient.new(request.payload).run
end
end
```

2. async-websocket handlers:

```ruby

lib/stream_handler.rb

Async::WebSocket::Adapters::Rack.open(env) do |connection|
while message = connection.read
# ← attacker-controlled message; no auth gate here unless app adds one
handle_message(message.buffer)
end
end
```

3. JWT verification in gRPC interceptors — analogous to `before_action :authenticate_user!` in Rails, but DeepSec doesn't know to expect it.

CWE / category

Mostly framework / entry-point coverage rather than a single CWE. The downstream sinks DeepSec already knows about (CWE-89 SQLi, CWE-918 SSRF, CWE-78 OS command, CWE-79 XSS-in-API-responses, CWE-287 missing auth) all apply — they're just unreachable today because no candidates exist for the LLM to start from.

Closest CWE for the missing-auth shape: CWE-306 (Missing Authentication for Critical Function) — gRPC services exposing privileged operations without a per-method interceptor check.

Languages / frameworks

  • Language: Ruby
  • Server: Falcon (async, multi-tenant web server; HTTP/2 + WebSocket native)
  • RPC: async-grpc or plain `grpc` gem
  • Common companions: `async`, `async-websocket`, `zeitwerk`, `jwt`

Detection sentinels that distinguish Falcon/async-grpc apps from Rails:

  • `Gemfile` contains `gem "falcon"` or `gem "async-grpc"` or `gem "grpc"` without `gem "rails"`
  • `config.ru` present at repo root with no `config/routes.rb` or `bin/rails`
  • `proto/` directory with `.proto` files (gRPC service definitions)
  • Service classes inheriting from generated `*Service::Service` parent classes (the `_services_pb.rb` files `grpc_tools_ruby_protoc` emits)

Generic vs org-specific

Generic — this is a widely-used Ruby async-IO stack from the `socketry` ecosystem, not org-specific. Anyone running a Ruby gRPC microservice today is likely on Falcon + async-grpc and would benefit. The patterns are stable across projects because they all extend the same auto-generated gRPC base classes.

Closest existing analogue is `js-fastify-route` / `js-hono-route` — framework-gated entry-point matchers that activate only when the framework is detected.

Have you tried writing it yourself?

Not yet — wanted to confirm appetite for upstream coverage first. `docs/supported-tech.md` lists `sinatra`, `grape`, `hanami`, `roda` as "Roadmap" but Falcon / async-grpc aren't on that list. If you'd take a PR, happy to draft a detector + matcher + prompt-highlight block (Rails plus the four roadmap frameworks all follow the same shape, so it's a small, well-scoped add).

Suggested matcher slugs:

  • `rb-grpc-service` — gated on `tech: ["grpc-ruby"]`, file pattern `lib/**/service.rb`, regex on `class \w+ < \S+(?:Service|Service::Service)\b`
  • `rb-async-websocket-handler` — gated on `tech: ["async-websocket"]`, regex on `Async::WebSocket::Adapters::Rack\.open`
  • `rb-falcon-rack-app` — gated on `tech: ["falcon"]`, weak entry-point candidate for the `config.ru` rack app boundary

Prompt highlights would mirror the Rails ones: confirm a per-RPC auth interceptor exists, confirm request fields aren't passed unsanitized to subprocess/SQL/HTTP sinks, confirm error responses don't leak stack traces.


Happy to send a PR if there's interest.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions