Firefox XPI File Structure and Manifest Guide
This article provides a comprehensive breakdown of the
.xpi file format used for Firefox browser extensions. It
covers the fundamental ZIP-based architecture of the package, the
standard internal directory structure, the critical role and syntax of
the manifest.json configuration file, and the cryptographic
security files generated by Mozilla during the signing process.
What is an XPI File?
An .xpi (pronounced "zippy" and derived from
Cross-Platform Install) file is a standard ZIP archive with a renamed
file extension. Firefox uses this format to package and distribute
browser add-ons using the WebExtensions API. Because it is a standard
ZIP file, its contents can be extracted and inspected using any standard
decompression utility.
Internal Directory Structure
While the WebExtensions API allows developers flexibility in how they
organize their code, a packaged .xpi file must follow
specific rules for mandatory files. The manifest.json file
must always reside at the exact root of the archive, not nested inside a
subfolder.
A typical, well-structured .xpi package looks like
this:
extension.xpi
├── manifest.json
├── META-INF/
│ ├── manifest.mf
│ ├── mozilla.rsa
│ └── mozilla.sf
├── _locales/
│ ├── en/
│ │ └── messages.json
│ └── es/
│ └── messages.json
├── background/
│ └── background.js
├── content_scripts/
│ └── inject.js
├── icons/
│ ├── icon-48.png
│ └── icon-96.png
└── popup/
├── popup.html
├── popup.css
└── popup.js
Key Directories Explained
- Root Directory: Must contain
manifest.json. All relative paths in the manifest start from this root. META-INF/: Contains digital signature files added by Mozilla when the extension is signed for distribution._locales/: A strictly named directory used for internationalization (i18n). If your extension supports multiple languages, the translations must go here, organized by language code.- Custom Directories (
icons/,popup/,background/, etc.): These folders are not strictly enforced by Firefox. Developers create them by convention to keep HTML, CSS, JavaScript, and image assets organized. Firefox locates the files inside these folders based on the paths defined inmanifest.json.
The manifest.json
Structure
The manifest.json file is the blueprint of the
extension. It is the only file that every extension must contain at the
root level. It provides Firefox with metadata (name, version), defines
the extension's capabilities, declares permissions, and points to the
files that run in the background or on web pages.
Here is an example of a standard Firefox manifest.json
file:
{
"manifest_version": 3,
"name": "Sample Firefox Extension",
"version": "1.0.0",
"description": "A clear example of a Firefox manifest.",
"icons": {
"48": "icons/icon-48.png",
"96": "icons/icon-96.png"
},
"browser_specific_settings": {
"gecko": {
"id": "addon@example.com",
"strict_min_version": "109.0"
}
},
"permissions": [
"storage",
"activeTab"
],
"background": {
"scripts": ["background/background.js"]
},
"action": {
"default_popup": "popup/popup.html",
"default_icon": "icons/icon-48.png"
},
"content_scripts": [
{
"matches": ["*://*.mozilla.org/*"],
"js": ["content_scripts/inject.js"]
}
]
}Breakdown of Manifest Keys
manifest_version: An integer specifying the version of the manifest file format (currently 2 or 3).name,version,description: Basic strings identifying the extension in the Firefox Add-ons Manager.icons: Maps icon pixel sizes to their relative file paths inside the.xpiarchive.browser_specific_settings: A key unique to Firefox (which uses the Gecko rendering engine). It defines the extension's uniqueidand the minimum Firefox version required.permissions: An array of strings requesting access to specific browser APIs (likestorage,tabs, orbookmarks).background: Specifies long-running scripts or service workers that maintain the extension's state independent of any specific web page.action(orbrowser_actionin MV2): Defines the toolbar button, its icon, and the HTML file to load when a user clicks the button (default_popup).content_scripts: Tells Firefox to inject specific JavaScript or CSS files into web pages that match the defined URL patterns.
The
META-INF Directory (Cryptographic Signing)
For an .xpi file to be installed in standard release
versions of Firefox, it must be cryptographically signed by Mozilla.
When a developer uploads their ZIP file to Mozilla Add-ons (AMO),
Mozilla verifies the code, generates the META-INF
directory, packages everything together, and outputs the final
.xpi file.
This directory contains three specific files that prevent tampering:
manifest.mf: Contains a list of every file in the.xpiarchive along with its cryptographic hash (usually SHA-256).mozilla.sf: A signature file that contains the cryptographic hash of themanifest.mffile itself.mozilla.rsa: The binary cryptographic signature of themozilla.sffile, generated using Mozilla's private key, along with the certificate chain needed by Firefox to verify the signature.
When you install the .xpi file, Firefox checks
mozilla.rsa to verify Mozilla signed it, uses
mozilla.sf to verify manifest.mf hasn't
changed, and finally checks manifest.mf to ensure none of
the extension's scripts or assets were modified after signing. If any
file is altered, the signature breaks, and Firefox will refuse to
install or run the extension.