Skip to content

fix(#729): escape names embedded in OSGi service filters - #738

Open
oscerd wants to merge 1 commit into
apache:mainfrom
oscerd:fix/729-osgi-filter-escaping
Open

fix(#729): escape names embedded in OSGi service filters#738
oscerd wants to merge 1 commit into
apache:mainfrom
oscerd:fix/729-osgi-filter-escaping

Conversation

@oscerd

@oscerd oscerd commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #729

What

Six lookups in camel-core-osgi built an OSGi service filter by concatenating a
name straight into it:

file filter
OsgiBeanRepository:60 (name=<name>)
OsgiBeanRepository:83 (service.pid=<name>)
OsgiComponentResolver:53 (component=<name>)
OsgiLanguageResolver:62 (language=<name>)
OsgiLanguageResolver:82 (resolver=<name>)
OsgiDataFormatResolver:62 (dataformat=<name>)

Filter metacharacters in the name were read as filter syntax rather than matched
as text. A name of * becomes a presence assertion matching every registered
service, and since each site takes refs[0], the lookup returned an arbitrary
service instead of not resolving. A name containing )( made the framework
reject the filter, faulting the exchange with a syntax error rather than giving
a clean not-found.

How

All six go through OsgiFilterHelper.createFilter(key, value), which escapes
the value before embedding it.

Escaping only. The FQCN and service.pid interpretations in lookupByName
are the documented purpose of OsgiBeanRepository and are left intact —
narrowing them would be a behaviour change for existing deployments, and is a
separate discussion. getServiceReference(name) at OsgiBeanRepository:80
takes an exact interface name rather than a filter, so it needs nothing.

For every legitimate name (jms, aws2-s3, org.apache.camel.MyBean, …) the
helper returns the string unchanged, so there is no behaviour change on the
normal path.

A correction worth flagging

#729 suggested RFC 4515 escaping. That is the wrong grammar for OSGi and I
had written it that way first — the tests caught it.

The OSGi Core specification defines its own filter grammar in which a value
escapes (, ), * and \ with a single preceding backslash. The RFC 4515
hex form \2a is read by an OSGi Filter as the two literal characters 2a,
so escaping * as \2a would have stopped a wildcard matching everything but
would also have stopped it matching a service genuinely named * — silently
wrong rather than safe. The helper now emits \*, \(, \), \\ and the
javadoc says why.

Tests

OsgiFilterHelperTest (13 cases). The important ones do not assert on the
rewritten string — they build a real Filter via FrameworkUtil.createFilter
and check what it actually matches:

  • (name=*) escaped no longer matches name=someRegisteredBean, but still
    matches a service whose name really is *
  • a name of x)(objectClass=org.apache.karaf.features.FeaturesService produces
    a valid filter that matches neither an unrelated name nor the injected
    objectClass clause, and matches only the literal name
  • )( no longer makes createFilter throw
  • one test pins the pre-fix behaviour ((name=*) unescaped does match an
    arbitrary service) so the regression is visible if the escaping is ever lost
Tests run: 25, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

(25 = 13 new + the 12 pre-existing camel-core-osgi tests, all still passing.)

Also adds the junit-jupiter-params test dependency.


Claude Code on behalf of Andrea Cosentino

Six lookups in camel-core-osgi built a service filter by concatenating a
name straight into it: OsgiBeanRepository (name= and service.pid=),
OsgiComponentResolver (component=), OsgiLanguageResolver (language= and
resolver=) and OsgiDataFormatResolver (dataformat=).

Filter metacharacters in the name were therefore read as filter syntax
rather than matched as text. A name of "*" becomes a presence assertion
matching every registered service, and since each site takes refs[0] the
lookup returned an arbitrary service instead of not resolving. A name
containing ")(" made the framework reject the filter, faulting the
exchange with a syntax error instead of a clean not-found.

Route this through OsgiFilterHelper.createFilter, which escapes the value
first. Escaping only: the FQCN and service.pid interpretations in
lookupByName are the documented purpose of the class and are left alone,
since narrowing them would change behaviour for existing deployments.
getServiceReference(name) at OsgiBeanRepository:80 takes an exact
interface name rather than a filter, so it needs nothing.

Note the escaping is the OSGi filter grammar's backslash-before-character
form, not the RFC 4515 "\2a" hex form - an OSGi Filter reads the latter as
the two literal characters 2a. The tests caught this: they assert against
a real FrameworkUtil.createFilter, so they check the filter actually stops
matching rather than just that a string was rewritten.
@oscerd
oscerd requested review from essobedo and jbonofre August 24, 2026 20:05
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.

camel-core-osgi: escape or validate names embedded in OSGi service filters

1 participant