Skip to content
Back to skills

Argus1

ASecurity

Argus — The Hundred-Eyed. Scan your Python or JavaScript codebase for bugs, security vulnerabilities, code smells, and common anti-patterns — get a prioritised fix list with line numbers, severity ratings, and suggested corrections for every issue found. Nothing escapes Argus.

  • 11 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 10, 2026
securityjavascriptpythonrustgojavashellbashsqlnodedebugging

Works with

  • cursor
  • api

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned September 10, 2026

npx -y skills add luokai0/ai-agent-skills-by-luo-kai --skill argus1 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Argus1?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Argus1
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/luokai0-argus1/badge)](https://www.skillsdirectory.com/skills/luokai0-argus1)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: argus
description: "Argus — The Hundred-Eyed. Scan your Python or JavaScript codebase for bugs, security vulnerabilities, code smells, and common anti-patterns — get a prioritised fix list with line numbers, severity ratings, and suggested corrections for every issue found. Nothing escapes Argus."
version: "1.0.0"
metadata:
  openclaw:
    requires:
      env: []
      bins: [python3, pip3]
    primaryEnv: "SOURCE_PATH"
    homepage: https://clawhub.ai/skills/argus
    emoji: "👁️"
    tags: [code, bugs, security, scanner, python, javascript, argus, debugging, linting]
    envVars:
      - name: SOURCE_PATH
        description: "File or directory to scan"
        required: true
      - name: LANGUAGE
        description: "Language to scan: python / javascript / auto"
        required: false
        default: "auto"
      - name: SEVERITY_FILTER
        description: "Minimum severity to show: critical / high / medium / all"
        required: false
        default: "all"
---

# 🐛 👁️ Argus — Code Intelligence Scanner

Static analysis for your codebase — finds real bugs, security holes, and code smells before
they hit production. No external API needed. Works on Python and JavaScript files.

**What you get:**
- Hardcoded passwords, API keys, and tokens flagged as Critical
- SQL injection and prototype pollution detection
- Bare excepts, mutable defaults, wildcard imports, and 13 other patterns
- Severity-filtered output: focus on Critical first, drill down from there
- `bug_report_[DATE].md` + `bug_report_[DATE].json` with full fix suggestions

## Quick Start
```bash
SOURCE_PATH="./src" LANGUAGE="python" SEVERITY_FILTER="high" python skill.py
```

## Security
Reads local files only. Nothing transmitted.

---

## Step 1 — Install dependencies
```python
import subprocess, sys
subprocess.run([sys.executable,"-m","pip","install","rich","--break-system-packages","--quiet"], check=True)
```

## Step 2 — Scan for Bugs
```python
import os, re, json
from pathlib import Path
from datetime import date
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import box

console = Console()
SRC_PATH   = os.environ.get("SOURCE_PATH", ".")
LANGUAGE   = os.environ.get("LANGUAGE", "auto").lower()
SEV_FILTER = os.environ.get("SEVERITY_FILTER", "all").lower()
TODAY      = date.today()

src = Path(SRC_PATH)
if not src.exists():
    console.print(Panel(f"[red]Path not found: {SRC_PATH}[/red]", border_style="red")); raise SystemExit(1)

console.print(Panel.fit(f"[bold red]🐛 👁️ Argus — Code Intelligence Scanner[/bold red]\nScanning: [cyan]{SRC_PATH}[/cyan]  |  Language: [yellow]{LANGUAGE}[/yellow]  |  Filter: [green]{SEV_FILTER}[/green]", border_style="red"))

# Detect language
def detect_lang(path: Path) -> str:
    py = len(list(path.rglob("*.py") if path.is_dir() else [path] if str(path).endswith(".py") else []))
    js = len(list(path.rglob("*.js") if path.is_dir() else [path] if str(path).endswith(".js") else []))
    if py == 0 and js == 0:
        return "python"  # default; user can override with LANGUAGE env var
    return "python" if py >= js else "javascript"

lang = LANGUAGE if LANGUAGE != "auto" else detect_lang(src)

# Bug patterns
PYTHON_RULES = [
    ("PY001", "critical", "security",  r"eval\s*\(",              "eval() is dangerous — executes arbitrary code", "Use ast.literal_eval() for safe parsing"),
    ("PY002", "critical", "security",  r"exec\s*\(",              "exec() executes arbitrary strings", "Refactor to avoid dynamic code execution"),
    ("PY003", "critical", "security",  r'password\s*=\s*["\'][^"\']{3,}', "Hardcoded password", "Use environment variables: os.environ.get('PASSWORD')"),
    ("PY004", "high",     "security",  r"pickle\.loads?\(",       "pickle.load is unsafe with untrusted data", "Use json.loads() for safe deserialization"),
    ("PY005", "high",     "bug",       r"except\s*:",              "Bare except catches ALL exceptions including KeyboardInterrupt", "Use except Exception: or catch specific exception types"),
    ("PY006", "high",     "bug",       r"==\s*None|None\s*==",    "Use 'is None' not '== None' — can produce unexpected results", "Replace == None with is None"),
    ("PY007", "medium",   "bug",       r"def\s+\w+\(.*=\[\]", "Mutable default argument — shared across calls", "Use None as default: def f(x=None): x = x or []"),
    ("PY008", "medium",   "security",  r"shell\s*=\s*True",       "subprocess with shell=True is a command injection risk", "Use shell=False and pass args as a list"),
    ("PY009", "medium",   "smell",     r"import \*",               "Wildcard import pollutes namespace and hides dependencies", "Import only what you need: from module import func"),
    ("PY010", "low",      "smell",     r"print\s*\(",             "print() left in code — likely debug statement", "Use logging module instead of print for production code"),
    ("PY011", "critical", "security",  r"(?i)(api_key|api_secret|secret_key|access_token|auth_token)\s*=\s*[\x27\x22][^\x27\x22]{8,}", "Hardcoded API key or token", "Store in environment variable: os.environ.get('API_KEY')"),
    ("PY012", "high",     "security",  r"execute\s*\(.*%.*\)|execute\s*\(.*\.format\(|execute\s*\(.*f[\x22\x27]", "Possible SQL injection via string formatting", "Use parameterised queries: cursor.execute(sql, (value,))"),
    ("PY013", "medium",   "security",  r"open\s*\((?![^)\n]*\bencoding)[^)\n]*[\x27\x22]w[\x27\x22]", "File opened for write without encoding", "Add encoding='utf-8': open(path, 'w', encoding='utf-8')"),
]
JS_RULES = [
    ("JS001", "critical", "security",  r"eval\s*\(",              "eval() executes arbitrary code", "Remove eval — refactor logic"),
    ("JS002", "critical", "security",  r"innerHTML\s*=",           "innerHTML is an XSS vector if it contains user input", "Use textContent or sanitize input first"),
    ("JS003", "high",     "bug",       r"==\s*null|null\s*==",    "Use === null for strict equality check", "Replace == null with === null"),
    ("JS004", "high",     "bug",       r"catch\s*\(\s*\)",      "Empty catch silently swallows errors", "Log the error: catch(e) { console.error(e); }"),
    ("JS005", "medium",   "bug",       r"var\s+",                  "var has function scope and hoisting issues", "Use const or let instead of var"),
    ("JS006", "medium",   "security",  r"localStorage\.setItem.*password", "Storing passwords in localStorage is insecure", "Never store credentials in localStorage"),
    ("JS007", "critical", "security",  r"(?i)(api_key|apikey|api_secret|access_token|auth_token)\s*[:=]\s*[\x27\x22][^\x27\x22]{8,}", "Hardcoded API key or token", "Use environment variable: process.env.API_KEY"),
    ("JS008", "high",     "security",  r"__proto__|constructor\.prototype", "Prototype pollution vulnerability", "Validate input keys; use Object.create(null) for safe maps"),
    ("JS009", "high",     "security",  r"\$\{.*\}.*query|query.*\$\{|db\.query\s*\(", "Possible SQL/NoSQL injection via template literal", "Use parameterised queries or an ORM"),
]
RULES = PYTHON_RULES if lang == "python" else JS_RULES
SEV_ORDER = {"critical": 0, "high": 1, "medium": 2, "low": 3}
SEV_SHOW  = {"all": 4, "medium": 2, "high": 1, "critical": 0}.get(SEV_FILTER, 4)

# Get files
ext = "*.py" if lang == "python" else "*.js"
files = list(src.rglob(ext) if src.is_dir() else [src])
files = [f for f in files if ".git" not in str(f) and "node_modules" not in str(f) and "venv" not in str(f)][:50]
console.print(f"[dim]Scanning {len(files)} {lang} files…[/dim]")

# Scan
findings = []
for fpath in files:
    try:
        lines = fpath.read_text(encoding="utf-8", errors="ignore").splitlines()
        for i, line in enumerate(lines, 1):
            for rule_id, sev, category, pattern, message, fix in RULES:
                if SEV_ORDER.get(sev, 3) <= SEV_SHOW and re.search(pattern, line):
                    findings.append({"id": rule_id, "severity": sev, "category": category,
                                     "file": str(fpath.relative_to(src) if src.is_dir() else fpath),
                                     "line": i, "code": line.strip()[:80], "message": message, "fix": fix})
    except Exception: pass

# Dedupe and sort
seen = set(); unique = []
for f in findings:
    key = (f["id"], f["file"], f["line"])
    if key not in seen: seen.add(key); unique.append(f)
unique.sort(key=lambda x: (SEV_ORDER.get(x["severity"],3), x["file"], x["line"]))

# Stats
from collections import Counter
sev_counts = Counter(f["severity"] for f in unique)
cat_counts = Counter(f["category"] for f in unique)

console.print()
console.print(Panel(
    f"Files scanned: [cyan]{len(files)}[/cyan]  |  Issues found: [bold]{len(unique)}[/bold]\n"
    f"[red]Critical: {sev_counts['critical']}[/red]  [yellow]High: {sev_counts['high']}[/yellow]  [blue]Medium: {sev_counts['medium']}[/blue]  [dim]Low: {sev_counts['low']}[/dim]\n"
    f"Security: {cat_counts['security']}  |  Bugs: {cat_counts['bug']}  |  Smells: {cat_counts['smell']}",
    title="[bold]📊 Scan Summary[/bold]", border_style="red" if sev_counts["critical"] > 0 else "yellow"
))

if unique:
    console.print()
    display_count = min(len(unique), 25)
    title_suffix = f" — showing {display_count} of {len(unique)}" if len(unique) > 25 else ""
    t = Table(title=f"🐛 Issues Found ({len(unique)}){title_suffix}", box=box.ROUNDED, show_lines=True, border_style="red")
    t.add_column("ID", width=7, style="dim"); t.add_column("Sev", width=10); t.add_column("File:Line", style="cyan", width=28)
    t.add_column("Issue", style="white", width=35); t.add_column("Fix", style="green", width=40)
    SEV_COLOR = {"critical":"bold red","high":"yellow","medium":"blue","low":"dim"}
    for f in unique[:25]:
        col = SEV_COLOR.get(f["severity"],"white")
        t.add_row(f["id"], f"[{col}]{f['severity']}[/{col}]", f"{f['file'][:22]}:{f['line']}", f["message"][:35], f["fix"][:40])
    console.print(t)
else:
    console.print(Panel("[green]✅ No issues found matching your filter criteria![/green]", border_style="green"))

# Save
out_path = f"bug_report_{TODAY}.json"
with open(out_path,"w", encoding="utf-8") as f:
    json.dump({"scanned_files": len(files), "language": lang, "findings": unique, "generated": str(TODAY)}, f, indent=2)
md_path = f"bug_report_{TODAY}.md"
with open(md_path,"w", encoding="utf-8") as f:
    f.write(f"# Bug Hunt Report — {TODAY}\n\n**Files:** {len(files)}  |  **Issues:** {len(unique)}\n\n")
    f.write("| ID | Severity | File:Line | Issue | Fix |\n|-----|---------|-----------|-------|-----|\n")
    for fi in unique: f.write(f"| {fi['id']} | {fi['severity']} | {fi['file'][:25]}:{fi['line']} | {fi['message'][:40]} | {fi['fix'][:40]} |\n")

console.print()
console.print(Panel(f"[bold green]✅ Scan complete![/bold green]\n\n📄 [cyan]{md_path}[/cyan]\n📄 [cyan]{out_path}[/cyan]\n\n[bold]What to do next:[/bold]\n1. [yellow]Fix Critical issues first[/yellow] — security and crash bugs\n2. [yellow]Fix High severity next[/yellow] — these will cause real problems\n3. [yellow]Run again after fixes[/yellow] to confirm clean\n4. [yellow]Add to CI/CD pipeline[/yellow] so every commit is scanned",title="[bold red]🐛 👁️ Argus — Code Intelligence Scanner — Done[/bold red]",border_style="red"))
```

Files in this skill

  • .clawhub/origin.json138 B
  • SKILL.md11.1 KB
  • _meta.json125 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…