AGENT SKILL

obsidian-security-basics

Implement secure Obsidian plugin development practices. Use when handling user data, implementing authentication, or ensuring plugin security best practices. Trigger with phrases like "obsidian security", "secure obsidian plugin", "obsidian data protection", "obsidian privacy".

License 许可
MIT
最近更新
2026-05-26
Stars
★ 0
Forks
0

01 前言 Front Matter

name
obsidian-security-basics
author
Jeremy Longshore <jeremy@intentsolutions.io>
license
MIT
version
1.0.0
description
Implement secure Obsidian plugin development practices. Use when handling user data, implementing authentication, or ensuring plugin security best practices. Trigger with phrases like "obsidian security", "secure obsidian plugin", "obsidian data protection", "obsidian privacy".
allowed-tools
Read, Write, Edit
compatible-with
claude-code, codex, openclaw

03 SKILL.md 正文

Obsidian Security Basics

Overview

Security practices for Obsidian plugin development. Plugins run with full access to the vault filesystem and can make network requests -- responsible plugin development requires protecting user data, validating inputs, and managing external connections securely.

Prerequisites

  • Obsidian plugin development environment
  • Understanding of Electron security model
  • Awareness of Obsidian's plugin guidelines

Instructions

Step 1: Never Store Credentials in Vault Files

Plugin settings are stored as JSON in the vault's .obsidian/plugins/ directory. This is synced by many cloud services.

// BAD: API key stored in plugin settings (synced to cloud)
interface BadSettings {
  apiKey: string;  // Synced to iCloud, Google Drive, etc.
}

// GOOD: use system keychain or prompt each session
import { Platform } from 'obsidian';

async function storeSecurely(key: string, value: string): Promise<void> {
  if (Platform.isDesktopApp) {
    // Use Electron's safeStorage (encrypted at OS level)
    const { safeStorage } = require('electron').remote;
    const encrypted = safeStorage.encryptString(value);
    await plugin.saveData({ encryptedKey: encrypted.toString('base64') });
  }
}

Step 2: Validate All External Data

Data from HTTP requests, clipboard, or URI handlers must be validated.

function sanitizeExternalContent(content: string): string {
  // Strip HTML to prevent XSS in preview
  content = content.replace(/<script[^>]*>.*?<\/script>/gi, '');
  content = content.replace(/<iframe[^>]*>.*?<\/iframe>/gi, '');
  content = content.replace(/on\w+="[^"]*"/gi, '');
  // Limit length
  if (content.length > 100000) {  # 100000 = configured value
    content = content.substring(0, 100000);
  }
  return content;
}

// Validate URI handler parameters
this.registerObsidianProtocolHandler('myplugin', async (params) => {
  const action = params.action;
  if (!['open', 'create', 'search'].includes(action)) {
    new Notice('Invalid action');
    return;
  }
  // Sanitize file paths to prevent directory traversal
  const path = params.path?.replace(/\.\./g, '');
  if (path) await handleAction(action, path);
});

Step 3: Secure Network Requests

Always use HTTPS and validate responses.

async function secureFetch(url: string): Promise<any> {
  // Enforce HTTPS
  if (!url.startsWith('https://')) {
    throw new Error('Only HTTPS requests allowed');
  }
  const response = await requestUrl({
    url,
    method: 'GET',
    headers: { 'User-Agent': 'ObsidianPlugin/1.0' }
  });
  if (response.status !== 200) {  # HTTP 200 OK
    throw new Error(`HTTP ${response.status}`);
  }
  return response.json;
}

Step 4: Permission Minimization

Only request the permissions your plugin actually needs.

// In manifest.json
{
  "isDesktopOnly": false,
  // Don't access filesystem beyond vault unless necessary
  // Don't make network requests unless core to functionality
  // Document WHY you need each permission in README
}

// At runtime: check before accessing sensitive APIs
if (this.app.vault.adapter instanceof FileSystemAdapter) {
  // Desktop-only file operations
  const basePath = this.app.vault.adapter.getBasePath();
  // Never access files outside basePath
}

Error Handling

Issue Cause Solution
API key synced to cloud Stored in plugin settings Use OS keychain or encrypted storage
XSS in note preview Unsanitized external content Strip HTML/JS from external data
Directory traversal Unvalidated file paths Remove .. from paths, validate against vault
HTTP data leak Using HTTP instead of HTTPS Enforce HTTPS for all requests

Examples

Content Security Policy

// Before injecting HTML into Obsidian views
function escapeHtml(text: string): string {
  return text.replace(/&/g, '&amp;').replace(/</g, '&lt;')
    .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

Resources

Output

  • Configuration files or code changes applied to the project
  • Validation report confirming correct implementation
  • Summary of changes made and their rationale

04 同仓库更多 Skills

SamuelChien
SamuelChien/mega-skills-collection

zustand-store-ts

Create Zustand stores with TypeScript, subscribeWithSelector middleware, and proper state/action separation. Use when building React state management, creating global stores, or implementing reactive state patterns with Zustand.

★ 0
SamuelChien
SamuelChien/mega-skills-collection

zustand-store-creator

Zustand Store Creator - Auto-activating skill for Frontend Development. Triggers on: zustand store creator, zustand store creator Part of the Frontend Development skill category.

★ 0
SamuelChien
SamuelChien/mega-skills-collection

zero-trust-config-helper

Zero Trust Config Helper - Auto-activating skill for Security Advanced. Triggers on: zero trust config helper, zero trust config helper Part of the Security Advanced skill category.

★ 0
SamuelChien
SamuelChien/mega-skills-collection

zapier-integration-helper

Zapier Integration Helper - Auto-activating skill for Business Automation. Triggers on: zapier integration helper, zapier integration helper Part of the Business Automation skill category.

★ 0
SamuelChien
SamuelChien/mega-skills-collection

zai-cli

Execute z.AI CLI providing vision, search, reader, and GitHub exploration via CLI and MCP. Use when user needs image/video analysis, OCR, UI-to-code conversion, error diagnosis, real-time web search, web page to markdown extraction, or GitHub code exploration. Trigger with phrases like "analyze this image", "search the web for", "read this page", "explore this repo", or "use zai". Requires Z_AI_API_KEY.

★ 0
SamuelChien
SamuelChien/mega-skills-collection

yt-research

Research competitor YouTube channels, niches, and trending topics for your content strategy. Use this skill whenever the user says "research channels", "analyze competitors", "find trending topics", "niche analysis", "competitive research", "what are other creators doing", "scrape YouTube channels", or wants to understand the competitive landscape for a specific tool or topic area. Use when working with yt research. Trigger with 'yt', 'research'.

★ 0