Back to skill

Security audit

Kazakhstan tax assistant

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed Kazakhstan tax helper, but its scripts can read or overwrite broader local files and can update legal data through insecure downloads.

Install only if you are comfortable treating it as a local legal-text helper, not a professional tax authority. Do not let untrusted prompts choose --file, --out, --html, or --insecure arguments; keep file paths inside the skill's data directory, prefer manually saved and verified HTML from adilet.zan.kz, and verify important tax answers against official sources before acting on them.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/_shared.mjs:108
Finding
Process-Wide TLS Certificate Verification Disabled for Authoritative Legal Downloads<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_shared.mjs:108-114` **Related Locations**: `scripts/fetch.js:49-60`, `scripts/update.js:50-59`, `SKILL.md:38-41,179-185` **Vulnerability Type**: Improper certificate validation **Risk Level**: High ### Vulnerable Code ```js // ── Apply --insecure flag ────────────────────────────────────────────────────── export function applyInsecure(insecure) { if (insecure) { console.warn("⚠️ --insecure: проверка TLS отключена. Используйте только в доверенной сети."); process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; } } ``` The flag is consumed by the download scripts as follows: ```js const insecure = args["insecure"] === true || args["insecure"] === "true"; if (!htmlFile && !insecure) { console.error([ "Ошибка: для скачивания с adilet.zan.kz укажите --insecure (только в доверенной сети).", "Рекомендуется: скачайте HTML вручную и передайте через --html=./file.html", ].join("\n")); process.exit(1); } applyInsecure(insecure); ``` ### Technical Analysis Setting `NODE_TLS_REJECT_UNAUTHORIZED` to `"0"` disables TLS certificate verification for all HTTPS requests made by that Node.js process. The code then downloads legal documents that are treated as authoritative input by the Skill. The only relevant content-integrity checks are minimum document length in `fetch.js` and minimum article count in `update.js`. These checks establish neither authenticity nor integrity. An attacker can construct forged legal content that satisfies both conditions. The HTTP client also follows redirects under the default Fetch behavior, while the implementation performs no validation of the final response URL. There is no certificate pinning, trusted custom CA configuration, cryptographic signature, or checksum verification. This behavior is particularly sensitive because `update.js` can replace the current tax-code corpus with downloaded content. Although the TLS setting is limited to the script pro ...[truncated 1279 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove support for globally disabling certificate validation. 2. Add the required Kazakhstan CA certificate explicitly through a narrowly scoped HTTPS agent or `NODE_EXTRA_CA_CERTS`. 3. Keep normal hostname and certificate-chain verification enabled. 4. Reject redirects to hosts other than the approved `adilet.zan.kz` origin, or disable automatic redirects and validate each redirect target. 5. Validate document identifiers against a strict allowlist pattern before constructing the URL. 6. Verify downloaded documents against a trusted digital signature, published checksum, or independently authenticated metadata where available. 7. Preserve the manual HTML-import workflow as the fallback, but clearly require users to confirm the browser origin and certificate status. 8. Perform updates transactionally: validate both language versions first, write temporary files, then atomically replace the current corpus only after all checks pass. 9. Retain backups and provide an integrity manifest so poisoned updates can be detected and rolled back. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/search.js:187
Finding
Arbitrary Readable Local Files Can Be Searched and Disclosed Through Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/search.js:187-196` **Related Location**: `scripts/search.js:493-550` **Vulnerability Type**: Unrestricted local file access **Risk Level**: Medium ### Vulnerable Code ```js function loadCustomFile(filePath) { // Резолвим относительно CWD (рабочей директории), а не scripts/. // Это позволяет запускать из корня workspace: // node skills/kz-tax-code/scripts/search.js --file=skills/kz-tax-code/data/budget.md const resolved = filePath.startsWith("/") || filePath.match(/^[A-Za-z]:/) ? filePath : join(process.cwd(), filePath); if (!existsSync(resolved)) { throw new Error(`Файл не найден: ${resolved}`); } return readFileSync(resolved, "utf-8"); } ``` The resulting matches are returned through standard output: ```js console.log(JSON.stringify({ version: versionLabel, versionName, lang, query: { article, keyword, topic, file: customFile ?? undefined }, totalArticles: articles.length, found: results.length > 0, results, ...(externalHints ? { externalHints } : {}), }, null, 2)); ``` ### Technical Analysis The `--file` option accepts absolute paths and relative paths outside the Skill’s data directory. No canonicalization, approved-root check, file-type restriction, or symbolic-link check is applied. The script reads the selected file using the full privileges of the Node.js process. Search results, matching paragraphs, surrounding context, and—in article mode—full article-shaped blocks are serialized to standard output. In an agent environment, standard output commonly returns to the model and can subsequently be exposed to a requesting user. This is not direct network exfiltration: `scripts/search.js` contains no network request. Therefore, the static pre-scan warning about sending sensitive data over the network is a false positive. The actual issue is a local disclosure primitive that may become externally visible through the surround ...[truncated 1323 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict `--file` to an approved directory, preferably the Skill’s `data/` directory. 2. Resolve the requested path with `realpath()` and verify that the canonical result remains beneath the canonical approved root. 3. Reject absolute paths, traversal components, device paths, and symbolic links that escape the approved root. 4. Optionally allow external files only through a separate, explicitly privileged mode requiring user confirmation. 5. Restrict accepted extensions and reject non-regular files. 6. Apply file-size limits before reading content. 7. Avoid returning the supplied absolute path in output metadata. 8. Document that agent-controlled or user-controlled paths must never be passed directly to the script. 9. Add tests covering `../` traversal, absolute paths, nested symlinks, and platform-specific path forms. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/fetch.js:32
Finding
Caller-Controlled Output Path Allows Overwriting Arbitrary Writable Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch.js:32-33,81` **Vulnerability Type**: Unrestricted file write **Risk Level**: Medium ### Vulnerable Code ```js const args = parseArgs(); const docId = args["doc"]; const outFile = args["out"]; ``` After downloading or reading and parsing the HTML, the script writes directly to the caller-selected path: ```js writeFileSync(outFile, md, "utf-8"); console.log(`\n✅ Сохранено: ${outFile}`); ``` The content source may also be a caller-selected local HTML file: ```js let html; if (htmlFile) { console.log(` Читаю локальный файл: ${htmlFile}`); html = readFileSync(htmlFile, "utf-8"); } else { html = await fetchHtml(docId, lang); } process.stdout.write(` Парсинг HTML → Markdown ...`); const md = parseHtml(html); ``` ### Technical Analysis The `--out` argument is written without path canonicalization, approved-directory enforcement, symbolic-link protection, exclusive creation, or confirmation before replacing an existing file. Consequently, the script can overwrite any path writable by the executing account. Relative traversal paths, absolute paths, and symlinks can direct the output outside the intended law-data directory. The output must be Markdown produced by `parseHtml()`, and the script rejects parsed documents shorter than 1,000 characters. These constraints prevent a fully unrestricted byte-for-byte write, but they do not prevent destructive replacement or the creation of attacker-influenced text files. This capability exceeds the minimum privilege needed to download legislation into the Skill’s data directory. ### Attack Path 1. An attacker induces the agent to invoke `fetch.js` with a malicious `--out` value. 2. The value identifies an existing writable workspace file, a path reached through traversal, or a symlink to a writable target. 3. The attacker supplies a local HTML file through `--html`, or combines the operation with manipulated downloaded content. 4. The ...[truncated 798 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict output to a dedicated approved data directory. 2. Resolve the destination’s parent directory canonically and verify that it remains beneath the approved root. 3. Reject absolute paths, traversal paths, and symlink destinations. 4. Open new files with exclusive creation where replacement is not expected. 5. For intended replacements, require an explicit overwrite flag and display the canonical target path for confirmation. 6. Write to a temporary file in the same approved directory, validate the result, and atomically rename it into place. 7. Set conservative file permissions explicitly. 8. Enforce expected filename extensions and reasonable size limits. 9. Separate trusted update operations from ordinary search/download operations so routine Skill use does not receive general workspace write capability. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented maintenance features fetch remote content, update on-disk corpora, and modify version metadata, which materially differs from the declared purpose of answering tax questions. In context, this is dangerous because users or orchestration logic may invoke the skill expecting safe retrieval while it can perform side effects and ingest untrusted remote data.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented maintenance features fetch remote content, update on-disk corpora, and modify version metadata, which materially differs from the declared purpose of answering tax questions. In context, this is dangerous because users or orchestration logic may invoke the skill expecting safe retrieval while it can perform side effects and ingest untrusted remote data.

Ae5

High
Category
analysis-evasion
Confidence
100% confidence
Finding
Instruction-capable artifact exceeds whole-file semantic analysis limits

Ae5

High
Category
analysis-evasion
Confidence
100% confidence
Finding
Instruction-capable artifact exceeds whole-file semantic analysis limits

Ae5

High
Category
analysis-evasion
Confidence
100% confidence
Finding
Instruction-capable artifact exceeds whole-file semantic analysis limits

Ae5

High
Category
analysis-evasion
Confidence
100% confidence
Finding
Instruction-capable artifact exceeds whole-file semantic analysis limits

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The file explicitly states the tax code has lost force and is outdated, while the skill metadata claims to use the current edition. In a tax assistant, this is dangerous because users may receive incorrect legal guidance, rates, filing obligations, or compliance advice, causing financial loss, reporting errors, or regulatory violations.

Context-Inappropriate Capability

High
Confidence
95% confidence
Finding
The --file parameter is resolved relative to the workspace CWD and passed directly to readFileSync with only an existence check, allowing the skill to read arbitrary files from the workspace. In an agent setting, this can expose unrelated sensitive data such as secrets, prompts, source code, or user documents, far beyond the tax-assistant purpose.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger scope claims applicability to 'any tax question', but the actual corpus is limited to the tax code and a few related laws. Overbroad routing can send unrelated or high-stakes tax/compliance questions to a tool that may respond from an incomplete corpus, potentially causing incorrect advice or unnecessary execution of its auxiliary workflows.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The file states that language is determined automatically from the request content and that explicit language selection is unnecessary. This imposes a locale/language behavior without user opt-in, which can mis-handle bilingual or preference-sensitive users and fits the language-policy violation category.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
SQP-3 applies to all file types and covers natural-language policy violations such as forcing a specific language without user opt-in. This file presents all content only in Kazakh and does not indicate that the skill is region-specific or that users can choose another language.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The entire skill content is presented exclusively in Russian, and there is no surrounding instruction offering users a language or locale choice. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The skill description promises Russian and Kazakh support, but this file is entirely Russian and offers no user-choice mechanism or equivalent Kazakh source in the analyzed artifact. In a legal/tax context, language asymmetry can mislead users, degrade accessibility, and increase the risk of misunderstanding compliance-critical obligations, especially for Kazakh-language queries.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The code forces requests to use only "kaz" or defaults everything else to "rus", which is a locale constraint embedded in logic rather than offered as a user choice. Under the policy, language or locale restrictions should be opt-in or clearly documented as region-specific; this file contains no such justification.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The helper exposes a code path that disables TLS certificate validation globally by setting NODE_TLS_REJECT_UNAUTHORIZED=0. That makes HTTPS requests vulnerable to man-in-the-middle interception and tampering, which is especially risky here because the skill fetches legal/tax content from a remote government-related site and could ingest falsified statutes or rules.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
export function applyInsecure(insecure) {
  if (insecure) {
    console.warn("⚠️  --insecure: проверка TLS отключена. Используйте только в доверенной сети.");
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
  }
}
Confidence
99% confidence
Finding
Setting NODE_TLS_REJECT_UNAUTHORIZED to 0 disables certificate verification for TLS connections, weakening transport security for the entire Node.js process. An attacker on the network path could spoof the remote server, alter downloaded legal content, or capture sensitive traffic, and the tax-assistant context makes content integrity important because users may rely on the returned legal guidance.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The manifest describes a skill focused on answering tax questions about the Kazakhstan Tax Code, KGD rules, rates, deductions, and specific tax declarations. The script documentation explicitly says it can download 'any document' from adilet.zan.kz and lists non-tax laws such as budget, health insurance, social insurance, and pension statutes, which broadens the implemented scope beyond the stated tax-focused purpose.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The '--insecure' mode explicitly enables less secure network retrieval for remote HTML fetching, which can expose the process to man-in-the-middle tampering if used on untrusted networks. Because the fetched content is then parsed and written into the skill’s knowledge base as Markdown, an attacker could poison source documents and cause downstream misinformation or prompt/data contamination.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding
Suspicious Unicode normalization or mixed-script content

Static analysis

Detected: suspicious.env_credential_access, suspicious.insecure_tls_verification

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/_shared.mjs:113

HTTPS certificate verification is disabled.

Warn
Code
suspicious.insecure_tls_verification
Location
scripts/_shared.mjs:113