Back to skill

Security audit

Klaus IOC Scanner

Security checks for vulnerabilities and agentic risk

Overview

This IOC scanner does what it claims, but it can send full user-provided URLs to VirusTotal automatically without a clear consent step or privacy warning.

Review before installing. Use this only for indicators you are comfortable sharing with VirusTotal and AbuseIPDB. Do not submit internal URLs, password-reset links, signed cloud-storage URLs, customer data, or URLs containing tokens unless you have approval. Prefer adding an explicit confirmation or lookup-only mode before use.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
src/ioc_scan.py:153
Finding

Unsanitized URLs and API credentials are transmitted to VirusTotal

Content
View full analysis
Optional[Dict]: """Consulta URL no VirusTotal (relatório existente).""" if not VIRUSTOTAL_API_KEY: return None url_encoded = urllib.parse.quote(url, safe='') url_api = f"{VT_API_URL_V2}/url/report" params = { 'apikey': VIRUSTOTAL_API_KEY, 'resource': url } try: response = requests.get(url_api, params=params, timeout=30) if response.status_code == 200: data = response.json() if data.get('response_code') == 1: return data return None except Exception as e: print(f"[VirusTotal] Erro: {e}") return None def scan_url_virustotal(url: str) -> Optional[Dict]: """Submete URL para scan no VirusTotal.""" if not VIRUSTOTAL_API_KEY: return None url_api = f"{VT_API_URL_V2}/url/scan" data = { 'apikey': VIRUSTOTAL_API_KEY, 'url': url } try: response = requests.post(url_api, data=data, timeout=30) if response.status_code == 200: result = response.json() # Aguarda e consulta novamente time.sleep(3) return check_url_virustotal(url) return None except Exception as e: print(f"[VirusTotal Scan] Erro: {e}") return None ``` The automatic submission behavior is invoked by the following logic in `scan_ioc`: ```python elif ioc_type == 'url': print(f"[*] Consultando URL: {ioc}") vt_data = check_url_virustotal(ioc) if not vt_data: print(f"[*] Nenhum resultado, submetendo para scan...") vt_data = scan_url_virustotal(ioc) ``` ### Technical Analysis The scanner sends the complete user-supplied URL to VirusTotal w ...[truncated 3575 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (12)

Tainted flow: 'params' from os.environ.get (line 156, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · src/ioc_scan.py (reported line 92)May include surrounding context.

python
}
    
    try:
        response = requests.get(url, params=params, headers=headers, timeout=30)
        if response.status_code == 200:
            return response.json()
        else:

Tainted flow: 'params' from os.environ.get (line 156, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · src/ioc_scan.py (reported line 115)May include surrounding context.

python
}
    
    try:
        response = requests.get(url, params=params, timeout=30)
        if response.status_code == 200:
            data = response.json()
            if data.get('response_code') == 1:

Tainted flow: 'params' from os.environ.get (line 156, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · src/ioc_scan.py (reported line 138)May include surrounding context.

python
}
    
    try:
        response = requests.get(url, params=params, timeout=30)
        if response.status_code == 200:
            data = response.json()
            if data.get('response_code') == 1:

Tainted flow: 'params' from os.environ.get (line 156, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · src/ioc_scan.py (reported line 162)May include surrounding context.

python
}
    
    try:
        response = requests.get(url_api, params=params, timeout=30)
        if response.status_code == 200:
            data = response.json()
            if data.get('response_code') == 1:

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill documentation does not warn users that submitted URLs, domains, and IPs will be transmitted to VirusTotal and AbuseIPDB. This is dangerous because IOCs may contain sensitive investigation data, internal infrastructure details, or unreleased phishing samples, and submitting them to external reputation services can leak confidential information and potentially make the artifacts visible to third parties.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad enough that ordinary user requests like 'verificar', 'scan', or 'é malicioso?' could invoke the skill unintentionally. Because this skill sends submitted indicators to external services, accidental invocation can cause unintended disclosure of user-provided URLs, domains, or IPs and create confusing or privacy-impacting behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest explicitly states that URLs, domains, and IPs will be scanned using VirusTotal and AbuseIPDB, which implies user-supplied indicators are transmitted to third-party services. Without a clear warning in the skill description or metadata, users may unknowingly disclose sensitive internal infrastructure indicators, creating privacy, confidentiality, and operational exposure risks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · src/ioc_scan.py (reported line 23)May include surrounding context.

python
VIRUSTOTAL_API_KEY = os.environ.get("VIRUSTOTAL_API_KEY", "")
ABUSEIPDB_API_KEY = os.environ.get("ABUSEIPDB_API_KEY", "")
VT_API_URL_V2 = "https://www.virustotal.com/vtapi/v2"
ABUSEIPDB_URL = "https://api.abuseipdb.com/api/v2"


def extract_iocs(text: str) -> List[Tuple[str, str]]:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When no existing VirusTotal report is found, the script automatically submits the full user-provided URL to VirusTotal for scanning. That creates a real privacy and operational risk because sensitive internal, pre-release, customer, or incident-response URLs may be disclosed to a third party without an explicit warning or consent at the point of action.

Content

No source excerpt is available for this finding.

Tainted flow: 'data' from requests.post (line 164, network input) → requests.post (network output)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · src/ioc_scan.py (reported line 185)May include surrounding context.

python
}
    
    try:
        response = requests.post(url_api, data=data, timeout=30)
        if response.status_code == 200:
            result = response.json()
            # Aguarda e consulta novamente

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The visible natural-language fields in the manifest are written in Portuguese, including the main description and command description, with no indication that language choice is configurable or that the skill is intentionally restricted to Portuguese-speaking users. Under the stated policy, forcing a specific language without opt-in can be a locale-policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The usage/help text includes a hard-coded Chinese label ("用法:") while the rest of the script is primarily Portuguese and English, with no user option to choose language or locale. This imposes a specific locale presentation without opt-in and may violate language/locale policy requirements.

Content

No source excerpt is available for this finding.