Back to skill

Security audit

vryfik skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated search-helper purpose, but its web-probing and source-validation safeguards have real flaws that warrant review before installation.

Review this skill before installing in environments with access to internal networks or sensitive search topics. Its local cache is disclosed and bounded, but it stores recent queries and assembled snippets; its source checks should be fixed before relying on them for SSRF prevention or prompt-injection resistance.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/parallel-probe.js:87
Finding

SSRF Protection Can Be Bypassed Through DNS Rebinding and Incomplete IPv6 Filtering

Content
View full analysis
{ const options = { method: 'HEAD', hostname: parsed.hostname, port: parsed.port || (parsed.protocol === 'https:' ? 443 : 80), path: parsed.pathname + parsed.search, timeout: TIMEOUT_MS, headers: { 'User-Agent': 'search-skill-probe/1.0 (availability-check)' } }; const req = lib.request(options, res => { ``` The associated address blocklist is incomplete: ```javascript const BLOCKED_HOST_PATTERNS = [ /^localhost$/i, /^127\./, /^0\.0\.0\.0$/, /^10\./, /^172\.(1[6-9]|2\d|3[01])\./, /^192\.168\./, /^169\.254\./, /^::1$/, /^fc[0-9a-f]{2}:/i, /^fe80:/i, /^0::/, ]; ``` ### Technical Analysis The code resolves the supplied hostname with `dns.lookup()` and checks the resulting address against a private-address blocklist. However, the validated address is not used to establish the connection. Instead, `http.request()` or `https.request()` receives the original hostname and may perform another DNS resolution. This creates a time-of-check/time-of-use gap. An attacker who controls DNS for a supplied hostname can return a public address during the explicit validation lookup and an internal address when the HTTP ...[truncated 2061 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/credibility-arbiter.js:105
Finding

Caller-Supplied Domain Can Spoof Source Credibility

Content
View full analysis
{ const domain = src.domain || extractDomain(src.url || ''); const { tier, score: domainScore } = scoreDomain(domain); const contentMult = scoreContent(src.content); const finalScore = +(domainScore * contentMult).toFixed(3); return { domain, tier, domainScore, contentMultiplier: +contentMult.toFixed(3), finalScore, verdict: finalScore >= 0.7 ? 'trust' : finalScore >= 0.4 ? 'verify' : 'reject' }; }); ``` ### Technical Analysis The credibility arbiter accepts both a source URL and an optional caller-provided `domain`. When `domain` is present, it takes precedence over the hostname derived from the URL. No check confirms that the claimed domain corresponds to the URL. Consequently, a source hosted on an attacker-controlled domain can claim a highly trusted domain from `domain-reputation.json`, such as `github.com`, and receive that domain's score. The final verdict is then calculated using the forged identity. For example, input equivalent to the following can receive the reputation of GitHub even though the content originates elsewhere: ```json { "sources": [{ "url": "https://attacker.example/malicious-content", "domain": "github.com", "content": "Example implementation for 2026" }] } ``` The content heuristics may further increase the resulting score because terms such as `example`, dates, or code markers are treated as positive signals. ### Attack Path 1. An attacker causes a search result or pipeline object to contain a malicious URL. 2. The source object includes a forged `domain` property naming a trusted site. 3. The arbiter uses the supplied `domain` instead of parsing the URL. 4. `scoreDomain()` assigns the trusted site's reputa ...[truncated 787 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/stream-assembler.js:121
Finding

Untrusted Web Fragments Are Returned and Persisted Without Prompt-Injection Isolation

Content
View full analysis
{ const header = formatFragmentHeader(frag, i, lang); const content = (frag.content || frag.snippet || '').trim().slice(0, 2000); return `${header}\n\n${content}`; }); const answer = sections.join('\n\n---\n\n'); const tokensEstimate = estimateTokens(answer); ``` The resulting answer is subsequently persisted by `scripts/semantic-cache.js`: ```javascript active.push({ query: query.slice(0, 300), intent, vec: queryToVector(query, intent), result: String(result).slice(0, MAX_RESULT_LEN), ts: now }); ``` The pipeline instructions in `SKILL.md` direct the Agent to return this assembled `answer` and then cache it after successful assembly. ### Technical Analysis Web search snippets and fragments are untrusted external content. The assembler performs deduplication, truncation, and basic coherence scoring, but it does not distinguish factual source material from text written as instructions to an AI Agent. An attacker can publish search-indexed content containing directives such as requests to ignore prior instructions, disclose data, invoke tools, or misrepresent source material. If that content appears in a search fragment, it is copied verbatim into the answer. The same text can then be stored in the semantic cache and returned for future sufficiently similar queries. Credibility scoring does not address this threat. A reputable hosting domain may contain user-controlled content, and the domain-spoofing vulnerability can independently help hostile content obtain a trusted verdict. Truncating a fragment to 2,000 characters also does not neutralize instruction content. Whether the injected text can cause tool e ...[truncated 1661 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:129
Finding

Credibility Arbitration Pipeline Uses an Incompatible Input Field

Content
View full analysis
]}' ``` If **all** sources score `< 0.4`, discard everything and tell the user no reliable source was found. Do not assemble. ``` However, `scripts/credibility-arbiter.js` reads only `input.sources`: ```javascript try { const input = JSON.parse(arg); console.log(JSON.stringify(arbitrate(input.sources))); } catch (e) { console.log(JSON.stringify({ error: e.message })); process.exit(1); } ``` ### Technical Analysis The pipeline contract and the executable implementation use incompatible property names. Following `SKILL.md` exactly passes probe data under `results`, while the arbiter invokes `arbitrate(input.sources)`. Since `input.sources` is undefined, arbitration returns: ```json {"error":"sources must be a non-empty array"} ``` The documented pipeline does not explicitly require termination when this error occurs. As a result, the credibility scoring control may fail closed through an aborted workflow or fail open if the host continues to assembly without interpreting the error correctly. This is a security-relevant integration defect because Step 7 is intended to reject collections where all sources have scores below 0.4. ### Attack Path 1. The host follows the command documented in `SKILL.md`. 2. Probe results are supplied under the `results` property. 3. The arbiter looks for the nonexistent `sources` property. 4. Credibility arbitration returns an error instead of source scores. 5. If the host does not explicitly stop on this error, it may proceed to assembly without enforcing the all-sources-below-0.4 rejection rule. 6. Low-credibility or hostile fragments may ...[truncated 584 chars]
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 156)May include surrounding context.

md
node scripts/stream-assembler.js '{"fragments":[<trusted_fragments>],"query":"<original_query>"}'

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 209)May include surrounding context.

md
node scripts/stream-assembler.js '{"fragments":[<trusted_fragments>],"query":"<original_query>"}'

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger description is broad enough to match many normal queries about web search, documentation, pricing, and current information, which can cause the skill to activate in more contexts than necessary. In a skill with shell, network, and local read/write permissions, unintended invocation increases exposure to side effects such as persistent storage of queries and outbound probes.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill persistently stores query text and result snippets in a local cache under the user's home directory, creating session persistence of potentially sensitive search content. Even with restrictive file permissions, retained queries can expose private interests, internal research topics, API lookups, or other sensitive context to later processes or local compromise.

Content

Scanner excerpt · SKILL.md (reported line 30)May include surrounding context.

md
bins: ["node"]  # required runtime; scripts are invoked via shell tool

io:
  cache_path: "~/.antigravity/search-cache/"   # semantic-cache.js read/write scope
                                               # stores query text + result snippets (0o600)
                                               # created automatically on first write
  network_method: "HEAD only"                  # parallel-probe.js; no response body stored

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The overview section presents core operational instructions in Chinese without indicating that language choice is optional or user-selected. This can violate language or locale policy because the skill imposes a specific language presentation without documented opt-in or justification.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The web_search rules include very broad conversational keywords such as "why", "compare", and "vs" that commonly appear in ordinary user questions unrelated to live web retrieval. This can cause unintended routing to web search, exposing user queries to external systems, increasing data leakage risk, and producing behavior that is broader than the user intended.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language logic in detectLang returns 'zh' for Han characters and 'en' for everything else, which effectively forces an English locale for many users and languages. This is a language-policy concern because the file does not offer a user choice or document that the tool is intentionally limited to English and Chinese.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/semantic-cache.js (reported line 8)May include surrounding context.

js
* Semantic Cache — Vector similarity cache backed by local JSON file
 *
 * ClawHub Security: FILE SYSTEM ONLY.
 * Read/write limited to CACHE_DIR (default: ~/.antigravity/search-cache/).
 * No network access. No eval. No dynamic code.
 *
 * Commands:

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
71% confidence
Finding

The file embeds mixed English and Chinese trigger vocabularies throughout the routing rules, but does not indicate whether language selection is user-driven or whether the skill is intentionally limited to these locales. This can reflect an implicit language policy choice without explicit opt-in or justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module documentation explicitly states the skill is 'Pure synchronous computation.' However, the stdin mode implemented later uses asynchronous event listeners on process.stdin ('data' and 'end'), so the documented execution model contradicts the actual code behavior. This is a documentation-to-code mismatch, though it does not introduce a major security impact by itself.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The code contains a hardcoded Chinese-to-English bridging path and only special-cases the 'zh' locale, while all other languages fall back to no equivalent handling. This is a natural-language locale preference embedded in the skill behavior without any user opt-in mechanism or documented justification for why Chinese is singled out.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The stopword list embeds specific language handling for English and Chinese, which affects how user input is interpreted and cached. Because the file provides no user choice or documented locale constraint, this is a natural-language policy concern under the language/locale rule.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The code sets lang = 'en' by default, which imposes a specific language when the caller does not provide a preference. The policy allows language constraints when the user is offered a choice or opts in, but here the default silently selects English.

Content

No source excerpt is available for this finding.