Add Extuno expansion module - #900
Open
projectboot wants to merge 2 commits into
Open
Conversation
added 2 commits
September 8, 2026 17:31
Looks up the reputation of a browser extension, an IDE extension or a package from its store id or its listing URL, and reports whether it appears in a known-malicious catalog and whether Extuno's own static and sandbox analysis reached a verdict on it. Browser and IDE extensions are the reason the module exists. OSV and the other public advisory databases cover package registries, so an npm or PyPI name found in a build log can already be checked. An extension id found on a workstation cannot: no public advisory database covers the Chrome Web Store, addons.mozilla, the VS Code Marketplace, JetBrains or Eclipse. This closes that gap for the 140 existing expansion modules, none of which answer for an extension today. An analyst can paste the store listing URL, or use a text attribute holding store:id. Both resolve to the same lookup. A Chrome and an Edge extension id share one 32 character format, so a bare id that misses on Chrome is also tried against Edge rather than being reported as unknown. The lookup is read-only and never submits the artifact for analysis; only the identifier being looked up leaves the MISP instance. An API key is required and is checked before any request is made.
Every one of these produced a positive-looking answer for a question the module had not actually answered, which for a reputation module is the failure that matters most. An auth failure or a rate limit on the Edge fallback was accepted as the answer. The first lookup checked for the error marker, the second did not, so a rejected key or a 429 became "not in the malicious catalog and not analysed". The fallback doubles the request rate for every bare id, so a rate limit there is the expected case rather than a rare one. Both lookups now go through one path that propagates the failure. Host matching used str.endswith(), so evil-pypi.org matched pypi.org and a lookalike delivery URL was enriched with the legitimate package's verdict. A typosquat URL is exactly the indicator a MISP event holds. The boundary is now a dot, and the genuine hosts and their subdomains still resolve. The identifier was percent-encoded here and again by requests, so a Maven coordinate reached the API as org.apache.commons%3Acommons-lang3, an artifact that cannot exist, and the guaranteed miss was reported as "no record". The same applied to Discord ids, which are URLs, and to the unicode slugs AMO publishes. A listing URL truncated at the slug fell back to the slug as the identifier, so a URL naming a real extension answered "no record". The extension id format was already defined in the module but never applied; it is now, along with the numeric id a JetBrains URL carries and the package an npm scope must be followed by. A 200 response of the wrong shape escaped as an AttributeError rather than the error dict the module contract expects. api_url is operator configurable and a proxy can rewrite a body, so the response and its nested fields are now checked before use. The Edge fallback tested the raw verdict field while the parser normalised it, so a response with no verdict, or a null one, skipped the fallback and reported a known-malicious Edge extension as unseen. Six regression tests, one per defect. Each fails against the previous revision.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an expansion/hover module that looks up the reputation of a browser extension, an IDE extension or a package, from its store id or its listing URL.
Disclosure: I am the author of Extuno. It is a commercial service with a free tier (five scan credits on signup, no card), and the module requires an API key, in the same way as the VirusTotal, Shodan and AbuseIPDB modules already in this repository.
Why
There are 140 expansion modules and none of them answer for an extension. That gap is not incidental: OSV and the other public advisory databases cover package registries, so an npm or PyPI name found in a build log can already be checked here. An extension id found on a workstation cannot. Nothing public covers the Chrome Web Store, addons.mozilla.org, the VS Code Marketplace, JetBrains or Eclipse, so an analyst holding
bidgllfieacmghieipmhgabodmljimfhhas nowhere to ask.What it does
An analyst can enrich either a store listing URL or a text attribute holding
store:id:Covered: Chrome, Firefox, Edge, VS Code, JetBrains, Eclipse, Discord client mods, and the npm, PyPI, Packagist, Maven, WordPress and Open VSX registries.
Notes on the implementation
a-pformat, so a bare id that misses on Chrome is also tried against Edge rather than being reported as unknown.Tests
tests/test_extuno.py, eight tests withrequestsmocked, covering the catalog and analysis paths, the Edge fallback, URL resolution for every supported store, and the two failure modes above. Verified against a live deployment as well.