# Markdown Here Browser Permissions: How Host Access is Configured

> Understand Markdown Here browser permissions. Learn how host permissions are configured and why activeTab storage and scripting are needed. Get the details now.

- Repository: [Adam Pritchard/markdown-here](https://github.com/adam-p/markdown-here)
- Tags: deep-dive
- Published: 2026-03-05

---

**Markdown Here requires `activeTab`, `contextMenus`, `storage`, and `scripting` permissions by default, using optional host permissions to request access to specific websites only when users initiate markdown conversion.**

The `adam-p/markdown-here` repository implements a WebExtension that runs across Chrome, Edge, Firefox, and other Chromium-based browsers. Instead of requesting blanket access to all websites at installation, the extension follows the principle of least privilege by declaring broad host patterns as optional permissions in [`src/manifest.json`](https://github.com/adam-p/markdown-here/blob/main/src/manifest.json) and dynamically requesting them at runtime through the Chrome permissions API.

## Core Permissions Declared in the Manifest

The foundation of Markdown Here's security model lies in its [`src/manifest.json`](https://github.com/adam-p/markdown-here/blob/main/src/manifest.json), where four primary permissions enable basic functionality without granting unrestricted website access.

**`activeTab`** allows the extension to inject scripts into whichever tab the user has explicitly activated via the toolbar button or context menu. This provides temporary access to the current page without requiring permanent host permissions for every site.

**`contextMenus`** enables the "Convert Markdown to HTML" entry that appears when users right-click editable fields, creating the primary user interface for triggering conversions.

**`storage`** persists user preferences including the "forgot-to-render" check and theme settings across browser sessions.

**`scripting`** (required by Manifest V3) authorizes programmatic script injection through `chrome.scripting.executeScript`, which the extension uses to load [`chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/main/chrome/contentscript.js) into active tabs.

## How Host Permissions Are Configured

Unlike many extensions that request broad host access during installation, Markdown Here configures **optional host permissions** covering `http://*/*` and `https://*/*` patterns. This declaration in [`src/manifest.json`](https://github.com/adam-p/markdown-here/blob/main/src/manifest.json) makes these permissions available but not granted until explicitly requested.

The runtime permission management logic resides in [`src/common/content-permissions.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/content-permissions.js), which wraps the Chrome permissions API. When the extension needs to read a page's HTML or inject CSS for markdown rendering, it first checks whether the specific origin has been granted access:

```javascript
// origin must end with a trailing slash, e.g. "https://mail.google.com/"
const origin = `${window.location.protocol}//${window.location.host}/`;

ContentPermissions.hasPermission(origin).then(granted => {
  if (!granted) {
    // Ask the user for permission
    ContentPermissions.requestPermission([origin]).then(result => {
      if (result) {
        console.log('Permission granted – can render markdown now.');
      } else {
        console.warn('User denied permission.');
      }
    });
  } else {
    console.log('Already have permission for', origin);
  }
});

```

If `ContentPermissions.hasPermission()` returns false, the extension calls `ContentPermissions.requestPermission([origin])`, which internally invokes `chrome.permissions.request({origins: [...]})`. The browser then displays a native permission prompt asking the user to allow access to that specific site.

## The Host Permission Workflow in Action

The escalation from minimal privileges to full host access follows a strict user-initiated workflow designed to respect user privacy:

1. **Initial State**: Upon installation, the extension only possesses `activeTab` privileges, giving it temporary access only when the user clicks the extension button on the current tab.

2. **Conversion Trigger**: When a user selects "Convert Markdown" from the context menu or toolbar, [`src/chrome/backgroundscript.js`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/backgroundscript.js) queries the active tab and attempts to inject [`src/chrome/contentscript.js`](https://github.com/adam-p/markdown-here/blob/main/src/chrome/contentscript.js):

```javascript
chrome.tabs.query({active: true, currentWindow: true}, tabs => {
  const tabId = tabs[0].id;
  chrome.scripting.executeScript({
    target: {tabId},
    files: ['chrome/contentscript.js']
  });
});

```

3. **Permission Check**: The content script needs to read the page's DOM and inject CSS for rendered markdown. Before proceeding, it checks whether the required origin is granted via the `ContentPermissions` helper.

4. **Dynamic Request**: If the permission is missing, the extension triggers the browser's permission prompt. The user must explicitly approve access to that specific origin before any DOM manipulation occurs.

5. **Operational State**: Once granted, the extension can read/write the page's DOM and inject stylesheets, completing the markdown conversion for that domain until the permission is revoked.

## Summary

- **Default Permissions**: Markdown Here operates initially with only `activeTab`, `contextMenus`, `storage`, and `scripting` rights, minimizing its attack surface.

- **Optional Host Access**: Broad URL patterns (`http://*/*`, `https://*/*`) are declared as optional in [`src/manifest.json`](https://github.com/adam-p/markdown-here/blob/main/src/manifest.json) rather than required permissions.

- **Runtime Requests**: The `ContentPermissions` class in [`src/common/content-permissions.js`](https://github.com/adam-p/markdown-here/blob/main/src/common/content-permissions.js) manages dynamic permission checks and requests using the Chrome permissions API.

- **User Consent**: Host access is only requested when users explicitly initiate a markdown conversion on a new domain, following the principle of least privilege.

- **Revocable Access**: Users can revoke granted host permissions at any time through the browser's extension settings without breaking the extension's core functionality on other sites.

## Frequently Asked Questions

### What happens if I deny host permissions when prompted?

If you decline the permission request, the extension cannot read the page content or inject the necessary CSS for rendering markdown. The conversion will fail silently or display a notification indicating that permission is required to proceed. You can trigger the permission prompt again by attempting to convert markdown on the same site.

### Why does Markdown Here use optional permissions instead of requesting all sites upfront?

According to the source code implementation in [`src/manifest.json`](https://github.com/adam-p/markdown-here/blob/main/src/manifest.json), using optional host permissions respects the principle of least privilege. This design prevents the extension from accessing website data until you explicitly choose to use the tool on a specific domain, reducing security risks and privacy concerns compared to extensions that request `<all_urls>` at installation.

### How can I revoke permissions granted to Markdown Here?

You can revoke specific host permissions through your browser's extension management interface. Navigate to the extension details page for Markdown Here, locate the "Site access" or "Permissions" section, and remove individual domains or reset permissions entirely. The extension will continue to function on other sites where permissions remain granted, or you can grant access again later when needed.

### Does Markdown Here work without any host permissions?

The extension can partially function using only the `activeTab` permission, which provides temporary access when you click the extension button. However, for persistent functionality across page reloads or for sites where you want seamless markdown conversion without clicking the toolbar each time, granting the specific host permission provides a smoother experience.