Skip to content

feat(frameworks): add detectors for ~65 additional cms, frontend, backend and hosting platforms#363

Open
TBX3D wants to merge 10 commits into
vmfunc:mainfrom
TBX3D:feat/fw-detectors-batch2
Open

feat(frameworks): add detectors for ~65 additional cms, frontend, backend and hosting platforms#363
TBX3D wants to merge 10 commits into
vmfunc:mainfrom
TBX3D:feat/fw-detectors-batch2

Conversation

@TBX3D

@TBX3D TBX3D commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

adds detection for a wide batch of previously-uncovered platforms: cms (bitrix, blogger, bolt, concrete, contao, craft, discourse, dotnetnuke, expressionengine, flarum, grav, nodebb, opencart, plone, prestashop, sitecore, squarespace, textpattern, typo3, webflow, wix, woocommerce, xenforo), static-site generators (hugo, jekyll, docusaurus, mkdocs, eleventy, hexo, vuepress, sphinx, nikola, publii), frontend libs (alpine.js, jquery, knockout, livewire, qwik, stimulus, turbo, unpoly), backend frameworks (tornado, cherrypy, play, sails.js, beego, jsf, gwt, vaadin, coldfusion), and hosting providers (vercel, github pages, fly.io, amazon s3). also tightens false-positive guards on 5 existing detectors (adonisjs, cakephp, codeigniter, phoenix, strapi).

the hosting detectors here (akamai, cloudflare, amazon cloudfront, netlify) conceptually overlap open pr #287 (feat/cdn-detection), which takes a dedicated cdn-module approach rather than a framework detector - not a hard duplicate, but worth reconciling before both land.

TBX3D added 6 commits July 9, 2026 17:06
several detectors matched a brand name as a substring across all header
names and values, so they fired on any response that merely referenced the
brand: a vendor cdn named in a link or csp value, or a cookie that shares
the brand prefix.

add an optional Header field to Signature that scopes a header-only match to
one named header's value, and apply it (or a structural anchor) per detector:

- express: "Express" scoped to x-powered-by, was firing on an
  express_checkout cookie.
- strapi: "Strapi" scoped to x-powered-by, was firing on a link naming
  strapi.io.
- flask: "Werkzeug" scoped to the server header.
- cherrypy: "CherryPy" scoped to the server header.
- symfony: dropped the bare "symfony" word (symfony sets no such header and
  it fired on symfony.com links); the x-debug-token header is the marker.
- shopify: key on the x-shopify response headers instead of the bare
  "Shopify" word, which fired on a cdn.shopify.com link.
- remix: dropped the bare "remix"/"_remix" substrings that fired on a
  track_remix.mp3 asset; window.__remixContext is the definitive marker.
- spring boot: anchor the whitelabel title in its h1 tag context so a
  tutorial discussing the error does not fire.

each false positive is folded into the detector tests as a regression.
a full fire-alone marker audit over the registry surfaced two more held
detectors whose single markers tripped on input they should not claim, each
proven with an almost-passing trap now folded into the tests as a permanent
regression.

alpine: the x-data directive marker was a bare substring that also matches
inside an unrelated hyphenated token (class="max-data", id="webflux-data"),
so it is anchored with a leading space to match the attribute form only.

flarum: the /assets/forum- bundle path is a generic forum asset path (any
site serving /assets/forum-banner.png trips it) and could only ever fire on
its own, since a real flarum page already carries the definitive id="flarum-"
marker, so it is dropped.
add a hosting.go detector group that identifies the hosting platform or
edge/cdn provider in front of a target rather than its application
framework. grouped in one file so the category can be reviewed or excluded
as a unit.

hosting (5): Vercel, Netlify, GitHub Pages, Fly.io, Amazon S3.

edge and cdn (3): Cloudflare, Amazon CloudFront, Akamai.

each keys on a response header the provider sets on every response and
that no other provider emits (x-vercel-id, x-nf-request-id,
x-github-request-id, cf-ray, x-amz-cf-id, Akamai-GRN, fly-request-id,
AmazonS3), so they carry no body-side false-positive surface. provider
names in header values are avoided: Akamai keys on its set headers not the
bare word, which appears in akamaihd.net csp values, and GitHub on
x-github-request-id not the GitHub.com server value, which can appear in a
link header. Fastly was considered but dropped because its x-served-by
cache markers are generic varnish, not fastly-exclusive.
add detectors anchored on structural markers (framework-specific
attribute, namespaced token, or generator meta) rather than a bare brand
substring, with prose and bare-brand-og traps in the tests.

wiki and cms (3): XWiki, Bolt CMS, ExpressionEngine.

static site generators (2): Nikola, Publii.

every fingerprint was verified against the vendor's own live output.
XWiki keys on its data-xwiki- attributes and /xwiki/bin/ route,
ExpressionEngine on its exp_ namespaced csrf token and session cookies,
and Bolt, Nikola, and Publii on the generator-attribute prefix so a share
card whose title is the brand cannot trip them. registers the new names in
the registry check.
add detectors anchored on structural markers (bootstrap element id, asset
path, framework-specific attribute, or script reference) rather than a
bare brand substring, with prose and substring-collision traps in the
tests.

forums (2): Flarum, NodeBB.

frontend (4): Stimulus, Turbo, Knockout.js, Unpoly.

every fingerprint was verified against the vendor's own live output.
Stimulus keys on its data-controller directive and Turbo on the
turbo-frame element and data-turbo attributes (both ship with Hotwire),
Knockout on data-bind and ko.applyBindings, Flarum on its flarum- prefixed
bootstrap id and /assets/forum- bundle path, and NodeBB on its
assets/nodebb path. Unpoly is anchored on its unpoly.min.js script rather
than its up- attributes, which are substrings of common words (popup,
sign-up) and of Stimulus's data-name-target. adds a Knockout version
pattern and registers the new names in the registry check.
add detectors across forum/wiki/lms, cms, and frontend categories, each
anchored on a structural marker (generator meta, response header, cookie,
or a framework-specific dom attribute) rather than a bare brand substring,
with prose and bare-brand-og traps in the tests.

forums, wiki, and lms (4): MediaWiki, Discourse, XenForo, Moodle.

cms (5): Plone, Grav, Textpattern, October CMS, Statamic.

frontend (1): Livewire.

every fingerprint was verified against the vendor's own live output. the
generator-meta detectors (MediaWiki, Discourse, Plone, Textpattern) anchor
on the attribute prefix, Grav keys on its compound content="GravCMS"
token, XenForo on the data-xf-init attribute and /js/xf/ script path, and
Moodle and October on their session cookies. Moodle stays cookie-only
because the M.cfg config global is short enough to collide with minified
javascript. adds version patterns for MediaWiki and Discourse, and
registers the new names in the registry check.
@TBX3D
TBX3D requested a review from vmfunc as a code owner July 10, 2026 00:10
@codecov-commenter

codecov-commenter commented Jul 10, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 99.78284% with 2 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@7ea1cd2). Learn more about missing BASE report.

Files with missing lines Patch % Lines
internal/scan/frameworks/detectors/backend.go 98.54% 1 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #363   +/-   ##
=======================================
  Coverage        ?   60.35%           
=======================================
  Files           ?       82           
  Lines           ?     7792           
  Branches        ?        0           
=======================================
  Hits            ?     4703           
  Misses          ?     2820           
  Partials        ?      269           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot added scan changes to scan engine tests test changes size/xl 500+ lines changed labels Jul 10, 2026
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

pr summary

12 files changed (+2235 -48)

category files
go source 12
tests 6

TBX3D added 4 commits July 9, 2026 20:06
add fingerprints across three categories, each anchored on a structural
marker (cookie, response header, generator meta, or a framework-specific
DOM attribute) rather than a bare brand substring, with prose and
reversed/minified-attribute traps in the tests.

backend (9): Tornado, CherryPy, Play Framework, Sails.js, Beego,
JavaServer Faces, Google Web Toolkit, Vaadin, ColdFusion.

cms and site builders (10): TYPO3, Contao, Wix, Webflow, HubSpot,
PrestaShop, Sitecore, OpenCart, DotNetNuke, Liferay.

static site generators (4): Hugo, Jekyll, Docusaurus, MkDocs.

the generator-meta detectors anchor on a structural slice of the real
tag (content="Hugo 0., content="mkdocs-, generator" content="TYPO3) so a
page that merely names the brand in an og or twitter title cannot trip
them, while still surviving the attribute-name minification and reversed
attribute order seen in the wild. Webflow keys on the data-wf-page
attribute so it catches published sites that drop the generator meta.
adds generator version patterns for Hugo, Jekyll, Docusaurus, MkDocs, and
TYPO3, a Server-header version helper for Tornado and CherryPy, and
registers the new names in the registry check.
both detectors matched a bare lowercase body substring, so any page that
named the framework in prose or a tag link scored as a positive: cakephp
fired on the stackoverflow tag page, strapi on any article mentioning it.

drop the body substrings and key on structural markers instead:
- cakephp: the CAKEPHP session cookie
- strapi: the X-Powered-By Strapi response header

extends the bare-substring cleanup from vmfunc#133. adds prose-trap negatives
and corrects the integration fixtures that encoded the old behaviour.
…tives

stimulus: the data-controller= marker had enough weight to clear the
detection threshold alone, so a generic hand-rolled data-controller
attribute with no other Hotwire markers fired at 0.76 confidence. lower
data-controller= and data-action= so neither fires solo; only their
combination or the definitive @hotwired/stimulus import clears 0.5 now.

symfony: the bare "sf_" cookie substring scored exactly 0.5 against an
unrelated cookie like misfa_sf_token, one float away from a false
positive. drop it and key on the "_sf2_" session-cookie prefix instead,
which is specific to symfony's own naming.

each fix is folded into the detector tests as a regression, alongside a
positive case proving the real marker still fires.
roughly half the one-line comments over the batch-2 detector structs just
restated the type name (e.g. "wordpressDetector detects WordPress CMS"),
adding nothing a glance at the struct wouldn't already tell you. drop
those and keep the ones that add real information: abbreviation
expansions, vendor/former-name notes, and framework-relationship context.
@TBX3D
TBX3D force-pushed the feat/fw-detectors-batch2 branch from a1c1172 to 2c432ab Compare July 10, 2026 04:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scan changes to scan engine size/xl 500+ lines changed tests test changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants