From 538a290eebe5f0f56e83b91b108fb499c0a9aa0f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2026 13:04:35 +0000 Subject: [PATCH 1/5] Chromium Browser Extensions: report ID, version, host permissions and content script matches --- bin/config.yaml | 2 + definitions/ChromiumBrowser_Extensions.yaml | 36 ++++++++++++--- .../1.2.0_0/_locales/en/messages.json | 8 ++++ .../1.2.0_0/manifest.json | 23 ++++++++++ .../2.1_0/manifest.json | 11 +++++ testing/testcases/chrome_extensions.in.yaml | 11 +++++ testing/testcases/chrome_extensions.out.yaml | 46 +++++++++++++++++++ 7 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/_locales/en/messages.json create mode 100644 test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/manifest.json create mode 100644 test_files/Chrome/Extensions/iiiijjjjkkkkllllmmmmnnnnoooopppp/2.1_0/manifest.json create mode 100644 testing/testcases/chrome_extensions.in.yaml create mode 100644 testing/testcases/chrome_extensions.out.yaml diff --git a/bin/config.yaml b/bin/config.yaml index b165787..504700e 100644 --- a/bin/config.yaml +++ b/bin/config.yaml @@ -10,6 +10,8 @@ Globs: - /root/{snap/brave/*/,}.config/BraveSoftware/Brave-Browser - /home/*/.config/microsoft-edge*/ - /root/.config/microsoft-edge*/ + - /home/*/.config/vivaldi*/ + - /root/.config/vivaldi*/ WindowsChromeProfiles: - C:\Users\*\AppData\{Roaming,Local}\*\*\User Data - C:\Windows\{System32,SysWOW64}\config\systemprofile\AppData\{Roaming,Local}\*\*\User Data diff --git a/definitions/ChromiumBrowser_Extensions.yaml b/definitions/ChromiumBrowser_Extensions.yaml index 175e57f..639f0b4 100644 --- a/definitions/ChromiumBrowser_Extensions.yaml +++ b/definitions/ChromiumBrowser_Extensions.yaml @@ -2,6 +2,11 @@ Name: Chromium Browser Extensions Description: | Parses all installed chromium extensions. + Manifest V3 extensions list the sites they can read or change in + `host_permissions` rather than `permissions`, so both are reported. + `ContentScriptMatches` lists the sites where the extension injects + its own scripts. + Author: Mike Cohen Categories: - Chrome @@ -9,9 +14,9 @@ Categories: FilenameRegex: "manifest.json" Globs: - - "{{LinuxChromeProfiles}}/*/Extensions/**/manifest.json" - - "{{WindowsChromeProfiles}}/*/Extensions/**/manifest.json" - - "{{MacOSChromeProfiles}}/*/Extensions/**/manifest.json" + - "{{LinuxChromeProfiles}}/*/Extensions/*/*/manifest.json" + - "{{WindowsChromeProfiles}}/*/Extensions/*/*/manifest.json" + - "{{MacOSChromeProfiles}}/*/Extensions/*/*/manifest.json" Sources: - Preamble: | @@ -24,20 +29,39 @@ Sources: LET ManifestData = SELECT OSPath, parse_json(data=read_file(filename=OSPath)) AS Manifest FROM Rows + -- Message names are case insensitive so lower case the keys to + -- match ResolveName() + LET LowerKeys(Item) = to_dict(item={ + SELECT lowcase(string=_key) AS _key, _value FROM items(item=Item) + }) + -- Find the Locale file to help with. LET LocaleData = SELECT *, if(condition=Manifest.default_locale, else=dict(), - then=parse_json(data=read_file( - filename=OSPath.Dirname + "_locales" + Manifest.default_locale + "messages.json"))) AS Locale + then=LowerKeys(Item=parse_json(data=read_file( + filename=OSPath.Dirname + "_locales" + Manifest.default_locale + "messages.json")))) AS Locale FROM ManifestData LET GetIcon(Manifest) = Manifest.icons.`128` || Manifest.icons.`64` || Manifest.icons.`32` || Manifest.icons.`16` + -- Flatten the matches of all content scripts into one list of unique sites. + LET ContentScriptMatches(Manifest) = SELECT * FROM foreach( + row=Manifest.content_scripts, + query={ SELECT _value FROM foreach(row=matches) }) + GROUP BY _value + VQL: | - SELECT OSPath, Manifest.author.email AS Email, + SELECT OSPath, + -- Manifests are stored in Extensions/// + OSPath.Components[-3] AS ID, + OSPath.Components[-2] AS Version, + Manifest.author.email AS Email, ResolveName(Message = Manifest.name, Locale=Locale) AS name, ResolveName(Message = Manifest.description, Locale=Locale) AS description, + Manifest.manifest_version AS ManifestVersion, Manifest.oauth2.scopes as Scopes, Manifest.permissions as Permissions, + Manifest.host_permissions AS HostPermissions, + ContentScriptMatches(Manifest=Manifest)._value AS ContentScriptMatches, Manifest.key as Key, if(condition=GetIcon(Manifest=Manifest), then=upload(file=OSPath.Dirname + GetIcon(Manifest=Manifest))) AS Image, Manifest AS _Manifest diff --git a/test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/_locales/en/messages.json b/test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/_locales/en/messages.json new file mode 100644 index 0000000..504a52c --- /dev/null +++ b/test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/_locales/en/messages.json @@ -0,0 +1,8 @@ +{ + "appName": { + "message": "Example V3 Extension" + }, + "appDesc": { + "message": "A Manifest V3 test extension" + } +} diff --git a/test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/manifest.json b/test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/manifest.json new file mode 100644 index 0000000..c07d95a --- /dev/null +++ b/test_files/Chrome/Extensions/aaaabbbbccccddddeeeeffffgggghhhh/1.2.0_0/manifest.json @@ -0,0 +1,23 @@ +{ + "manifest_version": 3, + "name": "__MSG_appName__", + "description": "__MSG_appDesc__", + "default_locale": "en", + "version": "1.2.0", + "author": "Example Author", + "permissions": ["storage", "tabs", "scripting"], + "host_permissions": [""], + "background": { + "service_worker": "background.js" + }, + "content_scripts": [ + { + "matches": ["https://*.example.com/*", "https://mail.example.net/*"], + "js": ["content.js"] + }, + { + "matches": ["https://*.example.com/*", "https://bank.example.org/*"], + "js": ["bank.js"] + } + ] +} diff --git a/test_files/Chrome/Extensions/iiiijjjjkkkkllllmmmmnnnnoooopppp/2.1_0/manifest.json b/test_files/Chrome/Extensions/iiiijjjjkkkkllllmmmmnnnnoooopppp/2.1_0/manifest.json new file mode 100644 index 0000000..1fd0fea --- /dev/null +++ b/test_files/Chrome/Extensions/iiiijjjjkkkkllllmmmmnnnnoooopppp/2.1_0/manifest.json @@ -0,0 +1,11 @@ +{ + "manifest_version": 2, + "name": "Example V2 Extension", + "description": "A Manifest V2 test extension", + "version": "2.1", + "permissions": ["storage", "https://www.example.com/*"], + "background": { + "scripts": ["background.js"], + "persistent": false + } +} diff --git a/testing/testcases/chrome_extensions.in.yaml b/testing/testcases/chrome_extensions.in.yaml new file mode 100644 index 0000000..6852011 --- /dev/null +++ b/testing/testcases/chrome_extensions.in.yaml @@ -0,0 +1,11 @@ +Queries: + # One Manifest V3 extension with a default locale and one Manifest + # V2 extension. + - | + SELECT ID, Version, name, description, ManifestVersion, + Permissions, HostPermissions, ContentScriptMatches + FROM Artifact.Generic.Forensic.SQLiteHunter( + MatchFilename=TRUE, All=FALSE, Chrome=TRUE, + CustomGlob=testFiles + '/Chrome/Extensions/*/*/manifest.json') + WHERE _Source =~ "Chromium Browser Extensions" + ORDER BY ID diff --git a/testing/testcases/chrome_extensions.out.yaml b/testing/testcases/chrome_extensions.out.yaml new file mode 100644 index 0000000..ba7f967 --- /dev/null +++ b/testing/testcases/chrome_extensions.out.yaml @@ -0,0 +1,46 @@ +# One Manifest V3 extension with a default locale and one Manifest +# V2 extension. +Query: SELECT ID, Version, name, description, ManifestVersion, + Permissions, HostPermissions, ContentScriptMatches +FROM Artifact.Generic.Forensic.SQLiteHunter( + MatchFilename=TRUE, All=FALSE, Chrome=TRUE, + CustomGlob=testFiles + '/Chrome/Extensions/*/*/manifest.json') +WHERE _Source =~ "Chromium Browser Extensions" +ORDER BY ID + +Output: [ + { + "ID": "aaaabbbbccccddddeeeeffffgggghhhh", + "Version": "1.2.0_0", + "name": "Example V3 Extension", + "description": "A Manifest V3 test extension", + "ManifestVersion": 3, + "Permissions": [ + "storage", + "tabs", + "scripting" + ], + "HostPermissions": [ + "\u003call_urls\u003e" + ], + "ContentScriptMatches": [ + "https://*.example.com/*", + "https://mail.example.net/*", + "https://bank.example.org/*" + ] + }, + { + "ID": "iiiijjjjkkkkllllmmmmnnnnoooopppp", + "Version": "2.1_0", + "name": "Example V2 Extension", + "description": "A Manifest V2 test extension", + "ManifestVersion": 2, + "Permissions": [ + "storage", + "https://www.example.com/*" + ], + "HostPermissions": null, + "ContentScriptMatches": [] + } +] + From 1247c8df8c0063d35fb292fadb57f079d6d207ef Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2026 13:15:36 +0000 Subject: [PATCH 2/5] Retrigger CI From 2e58f02426e359374b0b182aedecfb6d58a07b56 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2026 13:16:48 +0000 Subject: [PATCH 3/5] Retrigger CI From f1535b2aa6a7fcd8a0d0ca6f837214c60ab2b4f1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2026 13:24:07 +0000 Subject: [PATCH 4/5] Retrigger CI From 731cb9e539c9bc48e168f11a9edb4b02d58f2045 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Oct 2026 13:29:06 +0000 Subject: [PATCH 5/5] Retrigger CI