# SIGIL — Comprehensive Technical Reference SIGIL by NOMARK. A protective mark for every line of code. ## Product Summary Sigil quarantines and scans AI agent code before it runs. Supply chain security CLI for Python, JavaScript, TypeScript, and Shell code. Runs eight local security analysis phases with no external dependencies. Free open-source tier, plus Pro ($29/mo) and Team ($99/mo) plans with cloud threat intelligence, web dashboard, and team management. GitHub: NOMARJ/sigil | Website: sigilsec.ai | API: https://api.sigil.nomark.dev/v1 --- ## Install ### curl (Linux / macOS) ```bash curl -sSL https://sigilsec.ai/install.sh | sh ``` ### Homebrew ```bash brew tap nomark/tap && brew install sigil ``` ### npm ```bash npm install -g @sigilsec/cli ``` --- ## CLI Reference ### Setup Commands #### `sigil install` Install Sigil and set up default directory structure under `~/.sigil`. Creates: quarantine/, approved/, logs/, reports/, config #### `sigil aliases [--print]` Output shell alias configuration. Add to .bashrc / .zshrc with `eval "$(sigil aliases)"`. Available aliases: gclone, safepip, safenpm, safefetch, audit, audithere, qls, qapprove, qreject #### `sigil config [--init]` View or modify configuration. `--init` generates default config file. #### `sigil hooks [path]` Install pre-commit hook that scans staged changes before every commit. ### Audit Commands #### `sigil clone [directory] [flags]` Clone git repository into quarantine, scan it, then move to workspace if approved. Drop-in replacement for `git clone`. #### `sigil pip [flags]` Install Python package into quarantine, scan it, then install to environment if approved. Drop-in replacement for `pip install`. #### `sigil npm [flags]` Install npm package into quarantine, scan it, then install to project if approved. Drop-in replacement for `npm install`. #### `sigil scan [flags]` Scan a package, directory, or URL. Runs all eight analysis phases. Output formats: text, json, sarif. Targets: npm:express, pypi:requests, ./local-directory, https://github.com/user/repo #### `sigil fetch [flags]` Download URL into quarantine, scan it, then move to workspace if approved. Works with tarballs, zip archives, and raw files. ### Quarantine Management #### `sigil list` List all items currently in quarantine. Shows ID, target, score, verdict, date. #### `sigil approve ` Approve quarantined item and move it from quarantine to approved directory. #### `sigil reject ` Reject and permanently delete quarantined item. ### Account Commands #### `sigil login [--email ] [--password]` Authenticate with Sigil cloud API (Pro/Team features). Interactive login opens browser. Non-interactive: `sigil login --email user@example.com --password` (reads password from stdin). #### `sigil logout` Clear stored authentication token. Reverts CLI to open-source mode. --- ## Exit Codes | Code | Verdict | Meaning | |------|---------|---------| | 0 | LOW RISK | Score 0–9 or command completed successfully | | 4 | LOW | Score 1–9 | | 3 | MEDIUM | Score 10–24 | | 2 | HIGH | Score 25–49 | | 1 | CRITICAL | Score 50+ or command error | --- ## Eight Scan Phases | # | Phase | Weight | What It Scans | |---|-------|--------|---------------| | 1 | Install Hooks | 10x | setup.py cmdclass, npm postinstall, Makefile targets | | 2 | Code Patterns | 5x | eval(), exec(), pickle.loads, child_process, subprocess shell=True | | 3 | Network / Exfil | 3x | requests.post, fetch(), axios, WebSockets, ngrok, Discord/Telegram webhooks | | 4 | Credentials | 2x | os.environ, .aws/credentials, SSH keys, API key patterns | | 5 | Obfuscation | 5x | base64.b64decode, atob(), String.fromCharCode, hex escapes | | 6 | Provenance | 1-3x | Git history depth, binary files, hidden dotfiles, large files | | 7 | Prompt Injection | 5x | Hidden instructions in comments, docstrings, markdown targeting AI agents | | 8 | AI Skill Security | 10x | Malicious AI skills, MCP servers, suspicious permissions, publisher reputation | Supplementary scanners (optional): semgrep, bandit, trufflehog, safety, npm audit, dependency analysis, permission checks. --- ## Verdict System ### Scoring Total risk score = sum of (findings_in_phase * phase_weight) across all eight phases. | Score | Verdict | Meaning | Action | |-------|---------|---------|--------| | 0–9 | LOW RISK | No known malicious patterns detected | Auto-approve eligible | | 10–24 | MEDIUM RISK | Multiple findings | Manual review | | 25–49 | HIGH RISK | Significant suspicious patterns | Do not approve without review | | 50+ | CRITICAL | Multiple strong malicious indicators | Reject and report | ### Colors - LOW RISK: #22C55E (green) - MEDIUM RISK: #EAB308 (yellow) - HIGH RISK: #F97316 (orange) - CRITICAL: #EF4444 (red) --- ## API Reference Base URL: `https://api.sigilsec.ai/v1` All endpoints require Bearer token authentication. Generate API key from dashboard settings. ```bash curl -H "Authorization: Bearer sk_live_..." https://api.sigilsec.ai/v1/scans ``` ### Endpoints #### `POST /v1/scans` Submit a new scan. Returns scan ID for polling results. Auth: Pro, Team Request body: `{ "target": "npm:express@4.18.2", "policy": "default" }` Response: Includes verdict, score, phase results, and duration_ms #### `GET /v1/scans/:id` Get scan result by ID. Includes full verdict, score, and per-phase findings. Auth: Pro, Team #### `GET /v1/scans` List scan history with pagination and filtering. Supports date range, verdict, and target filters. Auth: Pro, Team #### `GET /v1/threats` Query the threat intelligence database. Returns known malicious packages and patterns. Auth: Pro, Team #### `POST /v1/policies/evaluate` Evaluate a scan result against custom policy. Returns pass/fail and policy violations. Auth: Team #### `GET /v1/team/members` List team members, roles, and scan activity. Auth: Team ### Rate Limits - Pro: 100 requests/minute - Team: 500 requests/minute ### Error Responses | Status | Meaning | |--------|---------| | 401 | Invalid or missing API key | | 403 | Endpoint not available on your plan | | 404 | Resource not found | | 422 | Invalid request body or parameters | | 429 | Rate limit exceeded | --- ## MCP Server The Sigil MCP server exposes six tools and one resource for AI agents. ### Setup 1. Install Sigil CLI (see Install section) 2. Build MCP server: `cd plugins/mcp-server && npm install && npm run build` 3. Configure your client (Claude Code, Cursor, Windsurf) ### Claude Code Configuration Add to `~/.claude/claude_desktop_config.json`: ```json { "mcpServers": { "sigil": { "command": "node", "args": ["/path/to/plugins/mcp-server/dist/index.js"], "env": {} } } } ``` Or per-project in `.mcp.json` at project root. ### Six Tools #### `sigil_scan` Scan local file or directory. Returns verdict, risk score, findings with file paths and line numbers. Parameters: - `path` (string, required): File or directory path to scan - `phases` (string, optional): Comma-separated list of phases to run (e.g. "install_hooks,code_patterns") - `severity` (string, optional): Minimum severity filter: low, medium, high, critical Response: `{ "verdict": "MEDIUM", "score": 12, "findings_count": 3, "findings": [...] }` #### `sigil_scan_package` Download and scan npm or PyPI package. Package downloaded into quarantine, scanned across all eight phases, verdict returned before installation. Parameters: - `manager` (string, required): "npm" or "pip" - `package_name` (string, required): Package name to download and scan - `version` (string, optional): Specific version to scan (defaults to latest) Response: `{ "verdict": "LOW RISK", "score": 0, "quarantine_id": "q_abc123", ... }` #### `sigil_clone` Clone git repository into quarantine and scan it. Repo held in quarantine until explicitly approved or rejected. Parameters: - `url` (string, required): Git repository URL to clone - `branch` (string, optional): Branch to clone (defaults to default branch) Response: `{ "verdict": "LOW RISK", "score": 0, "quarantine_id": "q_xyz", ... }` #### `sigil_quarantine` List all items currently held in quarantine. No parameters required. Response: ```json { "count": 3, "items": [ { "id": "q_abc123", "source": "npm:lodash@4.17.21", "status": "scanned", "score": 0, "verdict": "LOW RISK" }, { "id": "q_def456", "source": "github.com/user/repo", "status": "scanned", "score": 12, "verdict": "MEDIUM" }, { "id": "q_ghi789", "source": "pip:requests@2.31.0", "status": "pending", "score": null, "verdict": null } ] } ``` #### `sigil_approve` Approve quarantined item and release from quarantine. Parameters: - `quarantine_id` (string, required): ID of the quarantined item to approve Response: `{ "status": "approved", "id": "q_abc123", ... }` #### `sigil_reject` Reject and permanently delete quarantined item. Parameters: - `quarantine_id` (string, required): ID of the quarantined item to reject and delete Response: `{ "status": "rejected", "id": "q_def456", ... }` ### Resource #### `sigil://docs/phases` Read-only MCP resource. Returns documentation for all eight scan phases including names, weights, descriptions. ``` sigil://docs/phases ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | SIGIL_BINARY | sigil | Path to Sigil CLI binary (override if not in PATH) | ### Example Workflows **Scan and approve package:** 1. Call `sigil_scan_package("npm", "express", "4.18.2")` 2. Returns verdict, score, quarantine_id 3. Call `sigil_approve("q_abc123")` 4. Package released from quarantine **Scan repository:** 1. Call `sigil_scan(".", phases: "all", severity: "medium")` 2. Returns findings grouped by severity 3. Agent summarizes findings for user **Manage quarantine:** 1. Call `sigil_quarantine()` 2. Iterate through items 3. For LOW RISK items: `sigil_approve(id)` 4. For HIGH/CRITICAL items: `sigil_reject(id)` --- ## Claude Code Plugin Sigil Security plugin for Claude Code provides slash commands, specialized agents, and auto-scan hooks. Requires Claude Code 1.0.33+ and Sigil CLI. ### Installation ```bash # Install Sigil CLI first (see Install section) # Then add plugin claude plugin add NOMARJ/sigil ``` ### Slash Commands #### `/sigil-security:scan-repo ` Scan entire repository for malicious patterns. Runs all eight phases. Example: `/sigil-security:scan-repo .` #### `/sigil-security:scan-package ` Download and scan npm or pip package before installation. Example: `/sigil-security:scan-package express` #### `/sigil-security:scan-file ` Scan individual file for vulnerabilities. Example: `/sigil-security:scan-file src/utils/exec.js` #### `/sigil-security:quarantine-review` Review all items in quarantine. Display status, scores, options to approve/reject. ### Specialized Agents #### `@security-auditor` Expert analysis of scan results. Interprets findings, identifies threats, explains risk levels, provides remediation. Example: `@security-auditor analyze these scan results` #### `@quarantine-manager` Manages quarantine workflow. Lists items, guides approval/rejection decisions, coordinates bulk operations. Example: `@quarantine-manager approve all low-risk items` ### Auto-scan Hooks Plugin automatically suggests scans when it detects: - `git clone ` → Suggest scanning cloned repo - `pip install ` → Suggest quarantine and scan first - `npm install ` → Suggest quarantine and scan first - Mentions "security", "scan", "malware" → Offer to run scan - Mentions "clone", "install", "package" → Suggest scanning before proceeding --- ## CI/CD Integration ### GitHub Actions ```yaml name: Sigil Security Scan on: pull_request: push: branches: [main] jobs: sigil: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Run Sigil scan uses: NOMARJ/sigil@main with: path: "." threshold: medium fail-on-findings: true upload-sarif: true ``` Inputs: - `path`: Directory to scan (default: ".") - `threshold`: Verdict to trigger failure (low, medium, high, critical; default: medium) - `fail-on-findings`: Exit with non-zero code on findings (default: true) - `format`: Output format: text, json, sarif (default: text) - `phases`: Comma-separated phases or "all" (default: all) - `upload-sarif`: Upload SARIF to GitHub Code Scanning (default: false) - `sigil-token`: API token for cloud threat intelligence (Pro/Team) Outputs: - `verdict`: low, medium, high, critical - `score`: Numeric risk score - `findings-count`: Total findings - `report-path`: Path to report file ### GitLab CI ```yaml include: - remote: "https://raw.githubusercontent.com/NOMARJ/sigil/main/.gitlab/sigil.yml" sigil-scan: stage: test variables: SIGIL_SCAN_PATH: "." SIGIL_THRESHOLD: "medium" SIGIL_FAIL_ON_FINDINGS: "true" SIGIL_FORMAT: "json" artifacts: paths: - sigil-report.json ``` Variables: - `SIGIL_SCAN_PATH`: Directory to scan (default: ".") - `SIGIL_THRESHOLD`: Minimum verdict to trigger failure (default: medium) - `SIGIL_FAIL_ON_FINDINGS`: Exit with non-zero code (default: true) - `SIGIL_FORMAT`: Output format: text, json, sarif (default: text) - `SIGIL_TOKEN`: API token (Pro/Team) ### Generic CI/CD (Jenkins, CircleCI, Bitbucket) ```bash # 1. Install curl -sSL https://sigilsec.ai/install.sh | sh # 2. Scan sigil scan . --format json > sigil-report.json # 3. Gate on exit code EXIT_CODE=$? if [ $EXIT_CODE -ge 2 ]; then echo "HIGH or CRITICAL findings — failing pipeline" exit 1 fi ``` ### Docker ```bash # Volume mount docker run --rm -v "$(pwd):/workspace" ghcr.io/nomarj/sigil:latest scan /workspace # Multi-stage build FROM ghcr.io/nomarj/sigil:latest AS scanner COPY --from=builder /app /workspace RUN sigil scan /workspace --format json > /sigil-report.json ``` ### Output Formats - **text**: Human-readable, colored verdicts (terminal use) - **json**: Machine-readable for dashboards and scripting - **sarif**: Static Analysis Results Interchange Format (GitHub Code Scanning compatible) --- ## Configuration ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | SIGIL_QUARANTINE_DIR | ~/.sigil/quarantine | Quarantine directory | | SIGIL_APPROVED_DIR | ~/.sigil/approved | Approved packages directory | | SIGIL_LOG_DIR | ~/.sigil/logs | Scan logs directory | | SIGIL_REPORT_DIR | ~/.sigil/reports | Scan reports directory | | SIGIL_CONFIG | ~/.sigil/config | Config file path | | SIGIL_TOKEN | ~/.sigil/token | Auth token path | | SIGIL_API_URL | https://api.sigil.nomark.dev | Cloud API URL | ### Config File Location: `~/.sigil/config` (KEY=VALUE format) ``` API_URL=https://api.sigil.nomark.dev AUTO_APPROVE_THRESHOLD=0 DEFAULT_SEVERITY=medium ``` Generate default: `sigil config --init` ### .sigilignore Place at root of scanned directory. Uses glob syntax like .gitignore. ``` node_modules/ .git/ __pycache__/ vendor/ dist/ build/ *.min.js *.bundle.js *.lock package-lock.json yarn.lock poetry.lock ``` Default exclusions (even without .sigilignore): - node_modules/, .git/ - Test files, example files, docs files ### Scan Policies (Team Plan) Configure via dashboard or API: ```bash curl -H "Authorization: Bearer $SIGIL_TOKEN" \ https://api.sigil.nomark.dev/v1/team/policy ``` Policy options: - **auto_approve_threshold**: 0 (score 0 only), 9 (LOW RISK), 24 (MEDIUM), -1 (disable) - **required_review**: Verdicts requiring manual review (high, critical, all) - **allowlist**: Packages always approved, bypass scanning - **blocklist**: Packages always rejected, regardless of results ### Shell Aliases Auto-configure shell with convenience aliases: ```bash sigil aliases # Auto-detect shell and write sigil aliases --print # Print to stdout without modifying ``` Aliases: gclone, safepip, safenpm, safefetch, audit, audithere, qls, qapprove, qreject ### Git Hooks ```bash sigil hooks # Install in current repo sigil hooks /path/to/repo # Install in specific repo ``` Installs pre-commit hook at `.git/hooks/pre-commit`. Scans staged files for dangerous patterns before every commit. Patterns checked: eval(), exec(), __import__(), subprocess shell=True, os.system, pickle.loads, child_process ### Authentication Tokens stored at `~/.sigil/token` as JWT. Expires automatically; CLI falls back to offline mode silently. **Data sent to cloud (Pro/Team only):** - Scan rules triggered, file type distribution, risk score, package name/version/hash **Never sent:** - Source code, credentials, environment variable values, file paths All eight scan phases run locally offline. Cloud features optional. --- ## Scan Attestations Every scan produced by Sigil Bot is cryptographically signed using the in-toto attestation framework with DSSE (Dead Simple Signing Envelope). ### What Gets Signed Each scan attestation is an in-toto Statement v1 with predicate type `https://sigilsec.ai/attestation/scan/v1`. The predicate contains: - Scanner identity, version, and phases run - Full scan result: ecosystem, package name, version, verdict, risk score, findings count, files scanned, duration - Per-finding details: phase, rule, severity, file, line, weight, content digest - Metadata: source, content hash (SHA-256), registry/repository URLs, timestamps ### Signing - Algorithm: Ed25519 - Envelope: DSSE (`application/vnd.in-toto+json` payload type) - Public keys: https://sigilsec.ai/.well-known/sigil-verify.json ### Transparency Log Signed attestations are recorded in the Sigstore Rekor transparency log at https://rekor.sigstore.dev. Each scan report includes a `log_entry_id` linking to its Rekor entry. ### Verification #### API Endpoints - `GET /api/v1/attestation/{scan_id}` — Fetch the DSSE envelope for a scan - `GET /api/v1/verify?scan_id={scan_id}` — Verify attestation signature and return result #### Verification Steps 1. Fetch the scan attestation from `/api/v1/attestation/{scan_id}` 2. Decode the DSSE envelope payload (base64url to JSON) 3. Verify the in-toto Statement `_type` is `https://in-toto.io/Statement/v1` 4. Verify the `predicateType` is `https://sigilsec.ai/attestation/scan/v1` 5. Verify the subject digest matches the package archive SHA-256 from the registry 6. Verify the DSSE signature against the public key using Ed25519 7. Optionally verify the transparency log entry at Rekor #### SDKs - Node.js: `npm install @nomarj/sigil-verify` - Python: `pip install sigil-verify` - CLI: `sigil verify --attestation ` --- ## Troubleshooting FAQ **Q: Does Sigil send my source code to the cloud?** A: No. All eight phases run locally. Cloud threat intelligence sends only metadata (package names, hashes, verdicts), never source code. **Q: Can I use Sigil offline?** A: Yes. All eight scan phases run locally with no network. Cloud features require connectivity. **Q: Does Sigil replace Snyk or Dependabot?** A: No. Snyk/Dependabot scan for known CVEs. Sigil scans for malicious code patterns (install hooks, obfuscation, exfiltration) that CVE databases don't cover. **Q: What happens if I approve something malicious?** A: Approved packages move to ~/.sigil/approved/ but are not installed automatically. You explicitly install or use the package after approval. **Q: Can I undo an approval?** A: No built-in unapprove yet. Remove manually: `rm -rf ~/.sigil/approved/` **Q: How do I reset Sigil completely?** A: `rm -rf ~/.sigil && sigil config --init` (removes all approvals, tokens, config) **Q: What languages does Sigil support?** A: Python, JavaScript, TypeScript (JSX/TSX), Shell scripts, YAML, JSON, TOML. Go, Rust, Ruby planned. **Q: How is the risk score calculated?** A: Total score = sum of (findings_in_phase * phase_weight) across all eight phases. Weights: Install Hooks 10x, Code Patterns 5x, Network 3x, Credentials 2x, Obfuscation 5x, Provenance 1-3x, Prompt Injection 5x, AI Skill Security 10x. --- ## Pricing | Feature | Open Source | Pro $29/mo | Team $99/mo | |---------|-------------|-----------|-----------| | Full CLI (8 phases) | Yes | Yes | Yes | | Cloud threat intelligence | — | Yes | Yes | | Web dashboard | — | Yes | Yes | | Team management | — | — | Up to 25 | | CI/CD integration | — | — | Yes | --- ## Links - Homepage: https://sigilsec.ai - Documentation: https://sigilsec.ai/docs - CLI Reference: https://sigilsec.ai/docs/cli - API Reference: https://sigilsec.ai/docs/api - MCP Integration: https://sigilsec.ai/docs/mcp - Claude Code Plugin: https://sigilsec.ai/docs/claude-code - CI/CD Integration: https://sigilsec.ai/docs/cicd - Configuration: https://sigilsec.ai/docs/configuration - Troubleshooting: https://sigilsec.ai/docs/troubleshooting - GitHub: https://github.com/NOMARJ/sigil - API Base: https://api.sigilsec.ai/v1 --- SIGIL by NOMARK A protective mark for every line of code.