Back to skill

Security audit

ia-test-audit

Security checks for vulnerabilities and agentic risk

Overview

ClawScan’s verdict is benign with medium confidence: scans report a test-auditing skill and no clear malicious behavior, while noting questions about its tool scope and how its test-running environment is handled.

The verdict is benign, not a guarantee of zero risk. Before installing, consider whether the skill’s environment, file, and shell access fits your needs, and review the subprocess logging caveat if you rely on uninterrupted test runs. The scan reports full Skillspector component coverage, but its run also reported an exit status of 1 with serialization warnings, so the evidence should be read with the medium confidence in mind.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Although both concern test quality, the supplied script has a materially different analytical focus. Its comparisons determine whether tests have identical or similar actions and assertions, not whether those assertions validate the behavior claimed by the tests. Status, fixture, and polarity checks chiefly prevent inappropriate duplicate groupings. Local file scanning and optional multiprocessing are consistent supporting details; no unrelated resource access or malicious behavior is evident.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding

The supplied commands evaluate and diagnose the ia-test-audit skill itself. They do not visibly inspect tests, assertions, fixtures, mocks, failure handling, or test gates. Although these commands could support development of the declared auditing capability, the supplied chunk's primary behavior is meta-evaluation rather than the advertised test audit. The implementation of distiller.py is not supplied, so its internal behavior cannot be verified.

Content

No source excerpt is available for this finding.

Skill declares no tool scope ('permissions' or 'allowed-tools') but code capabilities were detected: env, file_read, file_write, shell.

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/stacks.md (reported line 10)May include surrounding context.

md
Tool names and flags below were current when written. Confirm each with `--help` or the
tool's docs before running it, and prefer the repository's pinned wrapper over a global
binary. Install audit-only tools ad hoc, for example with `uvx`, `npx`, or a scratch
Composer project. Never add them as project dependencies without approval.

Each section covers three things:
- **junit**: how to get the report `junit_census.py` reads. Produce it with the gate's

The observation-only subprocess wrapper can replace a completed subprocess result with a logging exception.

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

After the subprocess completes, opening or writing the observation log can raise an exception before the wrapper returns the original result. An unavailable output path, exhausted storage, or manipulated filesystem state can therefore turn passive instrumentation into test failures, undermining audit integrity and potentially disrupting the test run.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/duplicate_tests.py (reported line 390)May include surrounding context.

python
node = stack.pop()
        yield node
        for name in reversed(node._fields):
            value = getattr(node, name, None)
            if isinstance(value, list):
                stack.extend(v for v in reversed(value) if isinstance(v, ast.AST))
            elif isinstance(value, ast.AST) and not isinstance(value, ast.expr_context):

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/duplicate_tests.py (reported line 839)May include surrounding context.

python
while stack:
        node = stack.pop()
        for name in node._fields:
            value = getattr(node, name, None)
            if isinstance(value, list):
                for i, item in enumerate(value):
                    if isinstance(item, ast.expr) and (new := pick(item)) is not None:

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/duplicate_tests.py (reported line 489)May include surrounding context.

python
out.extend(fold(stmt.body if value else stmt.orelse))
                continue
        for name in ("body", "orelse", "finalbody"):
            if isinstance(getattr(stmt, name, None), list):
                setattr(stmt, name, fold(getattr(stmt, name)))
        if isinstance(stmt, ast.Try | ast.TryStar):
            for handler in stmt.handlers:

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/duplicate_tests.py (reported line 490)May include surrounding context.

python
continue
        for name in ("body", "orelse", "finalbody"):
            if isinstance(getattr(stmt, name, None), list):
                setattr(stmt, name, fold(getattr(stmt, name)))
        if isinstance(stmt, ast.Try | ast.TryStar):
            for handler in stmt.handlers:
                handler.body = fold(handler.body)