# Recog identifies a product from the banner it returns

> Rapid7's Recog matches network probe output against XML fingerprint files to name the operating system, product or hardware behind a service, and the repository was split in 2022 so the fingerprints and the language implementations could move at their own speeds.

**rapid7/recog** — Pattern recognition for hosts, services, and content

- Repository: https://github.com/rapid7/recog
- Stars: 796 · Forks: 215
- Language: Ruby
- License: NOASSERTION
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/rapid7-recog

## A fingerprint is a regex plus a set of extracted parameters

The core idea is small enough to hold in your head. A fingerprint file is an XML document designed to match a specific protocol response string or field, and the example given is ssh_banners.xml, which can determine the operating system, vendor and sometimes hardware product by matching the initial SSH daemon banner string. The format is a fingerprints element with a matches attribute, then one or more fingerprint elements, each carrying a pattern attribute holding the regular expression matched against the data, and an optional flags attribute controlling how the regular expression is interpreted. The example makes the parameter mechanism visible.

```xml
<fingerprints matches="ssh.banner">
  <fingerprint pattern="^RomSShell_([\d\.]+)$">
    <description>Allegro RomSShell SSH</description>
    <example service.version="4.62">RomSShell_4.62</example>
    <param pos="0" name="service.vendor" value="Allegro"/>
    <param pos="0" name="service.product" value="RomSShell"/>
    <param pos="1" name="service.version"/>
  </fingerprint>
</fingerprints>
```

The param elements are what make this more than a string match. A param with a pos and a name pulls a capture group out of the match and assigns it to a CPE style name, and a param with a value hardcodes one. So a single pattern yields a vendor, a product and a version, and the version comes from the data rather than from a hand maintained table.

## The matches attribute is the naming contract

The first line of a fingerprint file should always be the XML version declaration, and the first element should always be a fingerprints block whose matches attribute indicates what data the file is meant to match. The README says the matches attribute is normally in the form protocol.field, and the example uses ssh.banner. That convention is what lets a caller route a probe result to the right file without hardcoding a filename per protocol, and it is why the identifiers/ directory in the repository is part of the same picture. The naming scheme also tells you the scope of the corpus. The README mentions web server banners, snmp system description fields and a whole lot more, and the features/ directory and the documentation index in the README list the fingerprint families that get their own test suites, including ftp_banners, http_cookies, http_servers, favicons, http_wwwauth and tls_jarm. A TLS JARM fingerprint and an HTTP cookie fingerprint are very different pieces of data, and having a named, tested family for each is what makes the corpus usable rather than a pile of regexes.

## The 2022 split separated the data from the code

The repository layout is a direct consequence of a decision. On March 31, 2022, the Recog content, meaning the XML fingerprint files and utilities, were split from the Recog framework library implementation. The original repository now contains the content, and the Ruby implementation moved to a separate Recog-Ruby repository. The content is included in Recog-Ruby as a git submodule nested under the recog directory, so a language implementation carries the corpus with it without vendoring it as a copy. The gem versions equal to or greater than 3.0.0 therefore contain the XML fingerprint directory under the recog directory, and only include the recog_match tool, since the other tools are focused on fingerprint management. That explains the current shape of this repository, with xml/ at the root holding the corpus, tools/ holding the utilities, and the gemspec named recog-content.gemspec rather than something matching the framework. It is a rare and useful split, because the corpus is now usable by anyone regardless of language.

## Three language implementations, and they are not equally capable

There are three implementations listed, and the feature parity table is more informative than the list. Ruby lives at rapid7/recog-ruby, Java at rapid7/recog-java, and Go is a third party implementation at runZeroInc/recog-go. The table compares five features. The fingerprint verification CLI tool is present in all three, as is support for base64 encoded examples and for filesystem based external examples. The fingerprint match CLI tool is present in Ruby and Go but blank for Java. Fingerprint match CPE param interpolation is present in Ruby and Go and blank for Java as well. So the Java implementation is the one to check first, and the difference is not cosmetic, since param interpolation is how a captured group becomes a CPE field. For a team choosing a stack, that table is the decision, not the language preference.

## Installing it, and what the maturity note asks of you

The install path for the Ruby code is a clone and a bundle install, and the README asks for a recent version of Ruby along with Rubygems and the bundler gem.

```shell
$ git clone git@github.com:rapid7/recog.git
$ cd recog
$ bundle install
```

Then there is the paragraph that matters more than the commands. The README says that while the XML fingerprints themselves are quite stable and well-tested, the Ruby codebase is still fairly new and subject to change quickly, and asks you to contact them at research[at]rapid7.com before leveraging the Recog code within any production projects. So the data is the product and the code is a tool around it, and the recommendation is to treat the two differently. The repository layout supports that reading, with spec/ and features/ for the test suites, a Rakefile, .rspec, .rubocop.yml with a .rubocop_todo.yml, a .snyk file for dependency scanning, and a requirements.txt pinning lxml 6.1.3 and pyyaml for the Python parts of the tooling.

## Renaming master to main broke clones, and the fix is documented

Along with the repository split, the default branch was renamed from master to main, and any clones created before the change have to be updated manually. The README gives the four commands, and the order matters because the first two rename the local branch and repoint it at the remote while the last one updates the remote HEAD reference.

```
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
```

The pruning step is offered as optional and is run as a dry run first, which is a good pattern to copy.

```
# dry-run to confirm stale references that will be deleted before proceeding
git remote prune origin --dry-run
git remote prune origin
```

The same set is given for a fork that used an upstream-master tracking branch, where the old branch is deleted and a new upstream-main branch is created with tracking. This is the kind of detail that is tedious once and then never again, and documenting it in the README rather than in a wiki page is a reasonable call for a project with a large number of forks.

## Where Recog is the wrong tool

The first limit is scope. Recog is a matching framework and a corpus, not a scanner, so if you have a banner in hand and want to know what it is, it is the right thing, and if you want to go and collect banners it is not. The second is the corpus, and the way to think about it is that you are depending on other people's knowledge of what products emit. A fingerprint for a product that has since changed its banner stops matching, and a new product is not in the corpus until somebody writes the file. The README describes the XML fingerprints as quite stable and well-tested, which is a claim about the format and the testing rather than about coverage of every product in the world, and the update_cpes.py script and the cpe-remap.yaml and cortex.yaml files in the repository root suggest that maintaining the CPE identifiers is an ongoing chore with its own tooling. The third limit is the security posture of the matching itself. Fingerprint files are regular expressions applied to hostile input, since the input is whatever a remote service chose to send, and a corpus of thousands of regexes is a large surface for catastrophic backtracking. Nothing in the README describes how that is bounded, so a scanner embedding this should treat the pattern set as untrusted input.

## Conclusion

Recog suits a security engineer who inventories hosts and needs to know what is actually running behind a service, and it suits a team that wants one fingerprint corpus shared across several language stacks, since the XML files are the same everywhere. It is the wrong tool if you are building a scanner, because it is a matching library and a corpus rather than a probing tool, and it is the wrong tool for production use in its Ruby form, because the README asks you to contact Rapid7 before leveraging the Recog code in any production project. Before depending on it, read the maturity note, because the fingerprints are described as stable while the Ruby codebase is still changing quickly, and check the feature parity table before choosing an implementation. The last push was on 2026-10-12 and the current release is v3.3.2 from the same day.

## FAQ

### What does Recog identify and how?

Recog identifies products, services, operating systems and hardware by matching fingerprints against data returned from network probes. Each fingerprint is an XML file with a fingerprints element carrying a matches attribute, and one or more fingerprint elements whose pattern attribute is the regular expression matched against the data.

### Which programming languages have a Recog implementation?

Ruby at rapid7/recog-ruby, Java at rapid7/recog-java, and Go at runZeroInc/recog-go. The feature parity table shows the fingerprint match CLI tool and CPE param interpolation present in the Ruby and Go implementations but blank for the Java one.

### Is the Recog Ruby code safe for production use?

The README says the XML fingerprints themselves are quite stable and well-tested but the Ruby codebase is still fairly new and subject to change quickly, and asks you to contact research[at]rapid7.com before leveraging the Recog code within any production projects.

### How do I install Recog?

Clone the repository, change into the recog directory and run bundle install. The README lists a recent version of Ruby along with Rubygems and the bundler gem as the requirements, and the fingerprint content is included in the language implementations as a git submodule under the recog directory.

## Sources

- [Issues](https://github.com/rapid7/recog/issues)
- [rapid7/recog on GitHub](https://github.com/rapid7/recog)
- [README](https://github.com/rapid7/recog/blob/main/README.md)
- [Releases](https://github.com/rapid7/recog/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rapid7-recog
