Back to skill

Security audit

Hwp Batch Convert

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Hancom HWP batch converter, but its optional security-dialog auto-approval can click matching dialogs outside the intended conversion process.

Install only if you need Windows Hancom HWP batch conversion. Use plan-only first, prefer running without --auto-allow-dialogs, and enable auto-approval only in a controlled desktop session with trusted documents because it may approve a matching Hancom or spoofed dialog that is not part of the intended conversion.

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

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/hwp_batch_convert.py:338
Finding

Automatic Security-Dialog Approval Is Not Restricted to the Converter Process

Content
View full analysis

Vulnerability Details

File Location: scripts/hwp_batch_convert.py, lines 338–360
Vulnerability Type: Improper process authorization for desktop UI automation
Risk Level: Medium

Vulnerable Code

python
USER32.EnumWindows(enum_proc, 0)

for hwnd in hwnds:
    if hwnd in self._handled_hwnds or not USER32.IsWindowVisible(hwnd):
        continue
    title = USER32.GetWindowTextLengthW(hwnd)
    if title <= 0:
        continue
    window_title = ctypes.create_unicode_buffer(title + 1)
    USER32.GetWindowTextW(hwnd, window_title, title + 1)
    if window_title.value.strip() not in DIALOG_TITLE_WHITELIST:
        continue
    text_parts, allow_button_hwnd, allow_button_text = self._inspect_dialog(hwnd)
    window_text = ' '.join(part for part in text_parts if part).strip()
    reason = self._classify_candidate(
        window_title.value.strip(),
        window_text,
        allow_button_text,
    )
    if reason != 'match':
        if window_text:
            self._record_event(
                AutoDialogEvent(
                    window_title=window_title.value.strip(),
                    window_text=window_text,
                    button_text=allow_button_text,
                    clicked=False,
                    reason=reason,
                )
            )
            self._handled_hwnds.add(hwnd)
        continue
    clicked = False
    if allow_button_hwnd:
        USER32.SendMessageW(allow_button_hwnd, BM_CLICK, 0, 0)
        clicked = True

The converter records process ownership information at lines 403 and 429, but the dialog watcher does not use it:

python
self.owned_pids: set[int] = set()
python
self.owned_pids = _snapshot_hwp_pids() - before_pids

Technical Analysis

When --auto-allow-dialogs is enabled in real mode, AutoAllowDialogWatcher enumerates every top-level window on the user's interactive desktop. It approves a dialog based only on the following UI properties:

  • The top-level window tit ...[truncated 2551 chars]
Remediation
View remediation

Remediation Suggestions

  1. Restrict eligible windows by process ID

    • Pass a verified set of converter-owned process IDs into AutoAllowDialogWatcher.
    • Call GetWindowThreadProcessId for each candidate top-level window.
    • Reject the window unless its PID is in the verified ownership set.
  2. Fail closed when ownership cannot be established

    • Do not enable automatic approval if owned_pids is empty or process discovery fails.
    • Record a warning and require manual interaction instead.
  3. Validate executable identity

    • Resolve the candidate PID's executable path.
    • Confirm that the executable is an expected Hancom binary in a trusted installation location.
    • Do not rely solely on process names such as hwp.exe.
  4. Strengthen window validation

    • Validate expected top-level and child window classes.
    • Confirm that the candidate window is associated with the COM instance used for conversion where the API permits.
    • Retain the existing exact-title, body-keyword, and button-label checks as secondary controls rather than ownership proof.
  5. Minimize the approval window

    • Start the watcher immediately before the specific COM operation that may display the prompt.
    • Stop it immediately after that operation completes instead of keeping it active across the entire batch.
  6. Avoid global UI approval where possible

    • Prefer a documented Hancom API or trusted security module registration mechanism that scopes permission to the automation instance.
    • If reliable process binding is unavailable, disable automatic clicking and require explicit user confirmation.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (7)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README documents a feature that automatically clicks through Hancom security confirmation dialogs, which weakens a user-facing security control intended to warn about automation access to documents. Even though the behavior is constrained by a whitelist of window title, text, and button labels, the documentation presents it as a convenience feature without a prominent warning about the trust implications of suppressing security prompts or the risks of misidentifying dialogs in localized/UI-changed environments.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises shell, file-read, and file-write capable behavior but does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization ambiguity where an agent framework may grant broader execution than reviewers or policy layers expect, increasing the chance of unintended filesystem access or command execution during document conversion workflows.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file title and description are entirely in Korean and describe the behavior as specific to '한글(HWP)' dialogs, but it does not explicitly state that the skill is region- or product-specific as a documented locale constraint. Under the policy, forcing a specific language or locale without opt-in or clear justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/hwp_batch_convert.py (reported line 259)May include surrounding context.

python
def _snapshot_hwp_pids() -> set[int]:
    try:
        result = subprocess.run(['tasklist', '/FO', 'CSV', '/NH'], capture_output=True, text=True, encoding='utf-8', errors='ignore', check=False)
        if result.returncode != 0:
            return set()
        import csv

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/hwp_batch_convert.py (reported line 574)May include surrounding context.

python
[void]$form.ShowDialog()
""".strip()
    watcher = AutoAllowDialogWatcher(enabled=True, poll_interval=0.2)
    proc = subprocess.Popen(['powershell', '-NoProfile', '-STA', '-Command', dialog_script])
    try:
        clicked = watcher.click_once_for_test(timeout_seconds=timeout_seconds)
        proc.wait(timeout=timeout_seconds)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill includes an option to automatically click security confirmation dialogs for Hancom HWP when the dialog title/text/button match a narrow pattern. This weakens an application security boundary by programmatically approving access prompts that are intended to require human review, which is especially risky when processing untrusted HWP/HWPX documents that may trigger access attempts or sensitive actions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The natural-language content forces a specific language for all users, and there is no indication that Korean is optional or that the skill is intentionally limited to a Korean-only audience for compliance or regional reasons. This matches the policy category for language or locale constraints without user opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.