Back to skill

Security audit

unified-invoice

Security checks for vulnerabilities and agentic risk

Overview

This invoice skill is mostly purpose-aligned, but it has real safety issues around unescaped document data, path handling, and sensitive business data storage.

Review before installing or using with real customer data. Keep the data directory and generated invoices out of shared repos, avoid untrusted client/item/notes/date values, and prefer running PDF conversion only in an isolated browser profile until HTML escaping and output path validation are fixed.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate.js:92
Finding

Unescaped Invoice Data Allows HTML and Script Injection During PDF Rendering

Content
View full analysis
{ const amount = item.quantity * item.price; itemRows += ` ${idx + 1} ${item.name} ${item.unit} ${formatCurrency(item.quantity)} ${formatCurrency(item.price)} ${formatCurrency(amount)} `; }); const html = template .replace(/{{myCompanyName}}/g, myInfo.companyName || '') .replace(/{{myBusinessNumber}}/g, myInfo.businessNumber || '') .replace(/{{myCEO}}/g, myInfo.ceo || '') .replace(/{{myAddress}}/g, myInfo.address || '') .replace(/{{myPhone}}/g, myInfo.phone || '') .replace(/{{myEmail}}/g, myInfo.email || '') .replace(/{{clientName}}/g, client.name || '') .replace(/{{clientBusinessNumber}}/g, client.businessNumber || '') .replace(/{{clientCEO}}/g, client.ceo || '') .replace(/{{clientAddress}}/g, client.address || '') .replace(/{{clientPhone}}/g, client.phone || '') .replace(/{{issueDate}}/g, issueDate) .replace(/{{validUntil}}/g, validUntil) .replace(/{{itemRows}}/g, itemRows) .replace(/{{subtotal}}/g, formatCurrency(subtotal)) .replace(/{{vat}}/g, formatCurrency(vat)) .replace(/{{total}}/g, formatCurrency(total)) .replace(/{{notes}}/g, options.notes || ''); ``` The tax-invoice path has the same issue: ```js let itemRows = ''; itemList.forEach((item, idx) => { const amount = item.quantity * item.price; itemRows += ` ${issueDate} ${item.name} ${formatCurrency(item.quantity)} ${formatCurrency(item.price)} ${formatCurrency(amount)} ${options.notes || ''} `; }); const html = template . ...[truncated 3425 chars]
Remediation
View remediation
`, ``, attribute-breaking strings, and malicious CSS to verify that generated output renders them only as text. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate.js:135
Finding

Unvalidated Date Values Permit Output Path Traversal

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/freelance-run.sh:53
Finding

Unvalidated Amount Is Interpreted as a bc Program and Injected into Event JSON

Content
View full analysis
"$EVENT_FILE" << EOF { "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "source": "invoice-gen", "invoice_num": "$INVOICE_NUM", "client": "$CLIENT", "amount": $AMOUNT, "total": $TOTAL, "file": "$FILENAME" } EOF ``` ### Technical Analysis `AMOUNT` is expected to be a monetary number but is never validated. Shell expansion places it inside a textual program that is passed to `bc`. Operators, statement separators, loops, function constructs, and other supported syntax can therefore change the intended computation or cause excessive processing. This is expression-language injection rather than direct shell command injection: shell metacharacters introduced by parameter expansion are not reparsed as shell syntax in this context. Nevertheless, the attacker can manipulate `bc` behavior, invalidate invoice totals, cause the script to fail, or consume excessive resources. The same untrusted value is inserted raw into an event JSON document. Newlines, commas, braces, or other tokens can produce invalid JSON or inject additional JSON structure. The `CLIENT` and `FILENAME` string values are also not JSON-escaped, increasing the event-integrity risk. ### Attack Path 1. An attacker or untrusted caller supplies a crafted `--amount` value containing `bc` expression syn ...[truncated 933 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

설명은 통합 견적서/세금계산서 생성기로서 한국형 견적서, 프리랜서 인보이스, 거래처/품목 DB, PDF 출력, 자동 계산을 포함한다고 주장한다. 그러나 실제 코드는 CLI 기반으로 단일 마크다운 인보이스만 생성하며, 입력된 서비스/고객/금액을 템플릿에 채우고 10% VAT를 계산하는 수준이다. 사업자등록번호 처리, 세금계산서 양식 생성, 견적서 생성, 거래처/품목 데이터베이스, PDF 변환은 구현되어 있지 않다. 또한 코드에는 설명에 없는 이벤트 디렉토리에 JSON 이벤트를 발행하는 동작이 포함된다. 자동 계산 자체는 일부 부합하지만, 핵심 기능 다수가 과장 또는 누락되어 있어 설명과 실제 동작은 materially mismatch이다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

설명과 실제 구현은 상당 부분 일치한다. 실제로 거래처/품목 JSON DB를 사용하고, 견적서와 세금계산서를 자동 계산하여 HTML 및 PDF로 생성한다. 한국형 사업자등록번호/부가세 처리도 템플릿 변수와 VAT 계산에서 반영된다. 다만 설명에 포함된 '프리랜서 인보이스(다국어, VAT)' 기능은 이 코드 조각에서 확인되지 않는다. 별도의 invoice 명령, 다국어 템플릿 선택, 언어 옵션, 해외 인보이스용 필드 처리 등이 없으므로 설명이 실제 구현 범위를 과장하고 있다. 따라서 부분적 설명 불일치로 판단된다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

설명에는 문서 생성기 전체 기능이 포함되어 있으나, 실제 코드 조각은 그중 일부인 거래처 데이터 관리만 수행한다. 거래처 DB 관리는 선언된 목적의 보조 구성요소로 볼 수 있지만, 현재 코드의 주된 역할은 CRUD형 클라이언트 관리이며 선언된 핵심 기능인 견적서/세금계산서 생성, 다국어 인보이스, PDF 출력, 자동 세금 계산은 구현되어 있지 않다. 따라서 이 코드 조각만 기준으로 보면 선언된 설명과 실제 동작 사이에 중요한 범위 차이가 있어 mismatch로 판단된다.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

제공된 코드는 품목 데이터베이스의 일부인 items.json을 관리하는 보조 CLI 도구에 해당합니다. 품목 추가, 수정, 삭제, 조회, 목록 출력 기능은 선언된 '품목 DB' 범주와 일부 일치할 수 있으나, 선언된 핵심 목적은 통합 견적서/세금계산서 생성입니다. 실제 코드에는 견적서/인보이스 문서 생성, 세금 계산, VAT/부가세 처리, 사업자등록번호 처리, 다국어 출력, PDF 생성, 거래처 정보 관리 등의 핵심 기능이 전혀 없습니다. 따라서 이 코드 청크의 실제 동작은 선언된 설명의 전체 목적에 비해 현저히 축소되어 있으며, 설명을 정확히 대표하지 못하므로 mismatch로 판단됩니다.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/generate.js quote \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-clients.js add "무펭이즘" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-clients.js add "무펭이즘" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-clients.js add "무펭이즘" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-clients.js add "무펭이즘" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-clients.js add "무펭이즘" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-clients.js add "무펭이즘" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-items.js add "포토부스 대여" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-items.js add "포토부스 대여" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-items.js add "포토부스 대여" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-items.js add "포토부스 대여" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-items.js add "포토부스 대여" \

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/manage-items.js add "포토부스 대여" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs users to store sensitive business and personal data such as business registration numbers, addresses, phone numbers, email addresses, and bank-account details in local JSON files, but it provides no security guidance on access control, encryption, redaction, retention, or safe sharing. In an invoicing context, this raises the risk of privacy leakage, financial fraud, and accidental exposure through source control, backups, generated documents, or multi-user environments.

Content

No source excerpt is available for this finding.