Back to skill

Security audit

ai-news-pipeline-new

Security checks for vulnerabilities and agentic risk

Overview

This news-reporting skill mostly matches its purpose, but it has review-worthy risks around external API credentials, untrusted RSS content, and generated spreadsheets.

Install only in a dedicated workspace, use trusted HTTPS RSS sources, avoid feed credentials on plaintext URLs, set ARK_API_BASE only to a trusted model provider, consider using --disable-ai for sensitive content, and treat generated XLSX files as untrusted until formula escaping is added.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (8)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_company_report.py:497
Finding

Domestic report permits spreadsheet formula injection from RSS content

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_company_report.py:497-500
Vulnerability Type: Spreadsheet formula injection
Risk Level: High

Vulnerable Code

python
for row in merged_rows:
    worksheet.append([row.get(header, "") for header in headers])

Technical Analysis

The report writer inserts externally sourced RSS fields directly into XLSX cells. These fields include the title, article content, source, timestamp, and link. No neutralization is applied when a value begins with a spreadsheet formula marker such as =, +, -, or @.

Spreadsheet software may interpret such values as formulas rather than text. Depending on the software and its security settings, a formula can initiate external network requests, expose report data through attacker-controlled URLs, present deceptive hyperlinks, or invoke dangerous legacy spreadsheet functionality.

Attack Path

  1. An attacker publishes an RSS item containing a formula payload in its title, content, source, or link.
  2. The configured feed collector stores the malicious value in a JSONL data file.
  3. generate_company_report.py matches the item to a monitored company.
  4. The value is passed unchanged to worksheet.append.
  5. A user opens reports/company_mentions.xlsx.
  6. The spreadsheet application evaluates or presents the injected formula according to its security configuration.

Impact Assessment

Exploitation does not directly grant Python-process privileges. It targets the user opening the generated workbook and can compromise report integrity, cause unintended outbound requests, disclose information included in formula arguments, or potentially trigger spreadsheet-specific code-execution features in vulnerable or permissively configured clients.

Remediation
View remediation

Remediation Suggestions

  • Treat every feed-derived value as untrusted before writing it to XLSX.
  • Prefix values beginning with =, +, -, or @ with a single quote.
  • Explicitly assign sanitized values as string cells rather than relying on automatic type detection.
  • Apply the same sanitization to existing workbook rows before rewriting cumulative reports.
  • Add tests covering formula-prefixed titles, content, links, source names, and AI-generated fields.

Example hardening:

python
def safe_excel_text(value: object) -> str:
    text = str(value or "")
    if text.startswith(("=", "+", "-", "@")):
        return "'" + text
    return text

for row in merged_rows:
    worksheet.append([safe_excel_text(row.get(header, "")) for header in headers])

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate_international_report.py:490
Finding

International report permits spreadsheet formula injection from RSS content

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_international_report.py:490-493
Vulnerability Type: Spreadsheet formula injection
Risk Level: High

Vulnerable Code

python
for row in merged_rows:
    worksheet.append([row.get(header, "") for header in headers])

Technical Analysis

International RSS fields are written directly into spreadsheet cells without protection against formula interpretation. Attacker-controlled values beginning with spreadsheet control characters can therefore be stored as formulas in international_company_mentions.xlsx.

The cumulative merge does not eliminate the issue: both new feed values and values loaded from an existing workbook are written back without sanitization.

Attack Path

  1. An attacker places a formula-prefixed value in an international RSS item.
  2. The item passes the international relevance filter and is stored in JSONL.
  3. The report generator converts the record into a report row.
  4. The row is appended to the workbook without escaping.
  5. A report recipient opens the generated workbook.
  6. The spreadsheet application processes the attacker-controlled formula.

Impact Assessment

The principal impact is against the report recipient rather than the Skill process. It includes report manipulation, unintended network callbacks, possible disclosure of data encoded into formula requests, deceptive content, and exposure to client-specific spreadsheet execution behavior.

Remediation
View remediation

Remediation Suggestions

  • Sanitize every untrusted value before writing it to a cell.
  • Escape values beginning with =, +, -, or @.
  • Apply sanitization to RSS fields, model output, and rows loaded from previous reports.
  • Where possible, set the cell data type explicitly to text.
  • Add regression tests that inspect generated XLSX cell types and values.

Example:

python
def safe_excel_text(value: object) -> str:
    text = str(value or "")
    return "'" + text if text.startswith(("=", "+", "-", "@")) else text

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_company_report.py:271
Finding

Domestic RSS content is embedded directly into model instructions

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_company_report.py:271-277
Vulnerability Type: Indirect prompt injection
Risk Level: Medium

Vulnerable Code

python
"\n\n"
f"Enterprise name: {row['Enterprise name']}\n"
f"Original title: {row['News title']}\n"
f"News content: {row['News content']}\n"
f"News source: {row['News source']}\n"
f"News time: {row['News time']}\n"
f"News link: {row['News link']}\n"

The actual source uses Chinese field labels, but the security-relevant operation is the direct interpolation of the corresponding row fields shown above.

Technical Analysis

Untrusted feed content is concatenated into the same prompt string as the model’s operational instructions. The prompt does not clearly delimit the article as inert data or instruct the model to disregard commands contained in the article.

A malicious publisher can include text such as instructions to ignore the requested JSON policy, fabricate a summary, promote a particular entity, or misrepresent the article. JSON parsing constrains the response format but does not ensure that the generated values faithfully summarize the source.

Attack Path

  1. An attacker publishes an RSS article containing model-directed instructions.
  2. The collector stores the text without removing instruction-like content.
  3. The article matches a company alias and is selected for AI enrichment.
  4. The malicious article text is inserted directly into the model prompt.
  5. The model follows some or all embedded instructions.
  6. Manipulated titles or summaries are written into the XLSX and DOCX reports.

Impact Assessment

This issue affects report integrity and trustworthiness. It can cause false, biased, promotional, or misleading summaries to enter business reports. The model call has no tool or local-file access, so the demonstrated path does not provide operating-system privileges or arbitrary local code executio ...[truncated 2 chars]

Remediation
View remediation

Remediation Suggestions

  • Put untrusted article fields in a clearly delimited data section.
  • Add an explicit instruction that commands appearing inside source content are untrusted and must never modify the summarization task.
  • Use separate system and user message roles if the model API supports them.
  • Prefer a structured input object over free-form prompt concatenation.
  • Validate whether generated claims are supported by the original article.
  • Flag anomalous output rather than silently inserting it into final reports.
  • Add adversarial tests containing common prompt-injection phrases.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_international_report.py:221
Finding

International RSS content can manipulate summaries and impact rankings through prompt injection

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_international_report.py:221-227
Vulnerability Type: Indirect prompt injection
Risk Level: Medium

Vulnerable Code

python
f"{retry_hint}\n"
f"Original title: {row['News title']}\n"
f"News content: {row['News content']}\n"
f"News source: {row['News source']}\n"
f"News time: {row['News time']}\n"
f"News link: {row['News link']}\n"

The actual source uses Chinese field labels, but the security-relevant operation is the direct interpolation of these untrusted row values.

Technical Analysis

International feed data is placed directly into the model prompt alongside instructions for generating a title, summary, and impact_score. There is no robust trust-boundary marker between application instructions and article content.

This is especially significant because the generated impact score controls sorting and determines which five international items appear in the Word brief. An attacker can attempt to instruct the model to assign an artificially high score or produce promotional text. The retry mechanism repeats the same attacker-controlled content up to three times and does not address the trust-boundary problem.

Attack Path

  1. An attacker publishes an AI-related RSS item containing prompt-injection instructions.
  2. The item satisfies the topic and event filters.
  3. Its title and content are embedded in the AI request.
  4. The model returns attacker-influenced JSON, including a high impact_score.
  5. The score is accepted as long as it parses as an integer and is then clamped to the range 0–100.
  6. Sorting prioritizes the manipulated item, potentially placing it in the top-five international section of the Word brief.

Impact Assessment

An attacker can influence report content, prioritization, and editorial conclusions. This can displace legitimate stories from the brief or insert misleading claims. The issue does not d ...[truncated 126 chars]

Remediation
View remediation

Remediation Suggestions

  • Clearly label feed fields as untrusted quoted data.
  • Explicitly instruct the model not to follow instructions found in article content.
  • Separate model instructions from source data using structured roles or API-native structured input.
  • Calculate ranking from deterministic metadata where possible instead of relying exclusively on model output.
  • Validate unusually high scores through independent rules or a second verification step.
  • Detect instruction-like phrases in source material and flag affected records for review.
  • Ensure retries do not repeat untrusted input without additional defensive framing.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/collect_feeds.py:218
Finding

RSS Basic Authentication credentials may be transmitted without transport protection

Content
View full analysis

Vulnerability Details

File Location: scripts/collect_feeds.py:218-230
Vulnerability Type: Insecure credential transport
Risk Level: Medium

Vulnerable Code

python
def build_request(source: SourceConfig) -> Request:
    headers = {"User-Agent": USER_AGENT}
    if source.headers:
        headers.update(source.headers)

    if source.username and source.password:
        basic_token = base64.b64encode(
            f"{source.username}:{source.password}".encode("utf-8")
        ).decode("ascii")
        headers["Authorization"] = f"Basic {basic_token}"

    return Request(source.url, headers=headers)


def fetch_feed(source: SourceConfig) -> bytes:
    request = build_request(source)
    with urlopen(request, timeout=30) as response:
        return response.read()

Technical Analysis

Base64 encoding is the normal representation for HTTP Basic Authentication, but it does not encrypt credentials. The code accepts arbitrary source URLs and does not require HTTPS when a username and password are configured.

Consequently, an authenticated feed configured with an http:// URL transmits recoverable credentials over plaintext transport. Redirect destinations are also not explicitly restricted by application logic, so authenticated redirect behavior should be hardened rather than delegated entirely to default URL handling.

The encoded token is not printed or written to local output. The issue is network transport, not stdout exfiltration.

Attack Path

  1. A feed is configured with username, password, and an HTTP URL, whether through mistake or malicious configuration.
  2. The collector Base64-encodes username:password.
  3. It places the result in the Authorization header.
  4. urlopen sends the request over an unencrypted connection.
  5. A network-positioned attacker captures the header and decodes the credentials.

Impact Assessment

The exposed privileges are th ...[truncated 218 chars]

Remediation
View remediation

Remediation Suggestions

  • Reject authenticated feed URLs unless their scheme is HTTPS.
  • Parse and validate URLs before constructing the request.
  • Reject redirects from HTTPS to HTTP.
  • Strip authorization headers on cross-origin redirects.
  • Consider restricting redirects entirely for authenticated feeds.
  • Avoid accepting an Authorization value through arbitrary user-supplied headers when dedicated credential fields are used.
  • Document that Basic Authentication is safe only when protected by TLS.

Example validation:

python
from urllib.parse import urlparse

parsed = urlparse(source.url)
if source.username or source.password:
    if parsed.scheme.lower() != "https":
        raise ValueError("Authenticated RSS sources must use HTTPS")

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_company_report.py:343
Finding

Domestic model API key can be disclosed to an unrestricted endpoint override

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_company_report.py:343-352
Vulnerability Type: Configurable credential exfiltration destination
Risk Level: Medium

Vulnerable Code

python
request = Request(
    f"{ARK_API_BASE.rstrip('/')}/responses",
    data=body,
    headers={
        "Content-Type": "application/json; charset=utf-8",
        "Authorization": f"Bearer {ARK_API_KEY}",
    },
    method="POST",
)

with urlopen(request, timeout=ARK_TIMEOUT_SECONDS) as response:
    response_payload = json.loads(response.read().decode("utf-8"))

The destination is initialized from an unrestricted environment variable:

python
ARK_API_BASE = os.getenv(
    "ARK_API_BASE",
    "https://ark.cn-beijing.volces.com/api/v3",
)

Technical Analysis

The default endpoint is consistent with the declared Volcengine integration. However, ARK_API_BASE can be set to any URL, and the application then sends both the Bearer API key and complete feed-derived prompt to that destination.

The code does not enforce HTTPS or verify that the hostname belongs to the intended provider. This creates a credential-disclosure path in environments where deployment variables, task configuration, wrapper scripts, or inherited environment settings can be manipulated.

Attack Path

  1. An attacker or unsafe deployment configuration sets ARK_API_BASE to an attacker-controlled URL.
  2. A report run starts with a valid ARK_API_KEY.
  3. The application constructs a POST request to the attacker URL.
  4. The request includes the API key in the Authorization header.
  5. The request body also contains company names and collected news content.
  6. The attacker records the key and submitted report data.

Impact Assessment

The attacker obtains the privileges and quota associated with ARK_API_KEY and receives all article data submitted for domestic report generation. No arbitrary wo ...[truncated 40 chars]

Remediation
View remediation

Remediation Suggestions

  • Require the endpoint scheme to be HTTPS.
  • Allowlist the expected Volcengine hostname or a documented set of trusted endpoints.
  • Fail closed when the endpoint cannot be validated.
  • If custom providers are necessary, require a separate provider-specific credential rather than automatically forwarding ARK_API_KEY.
  • Avoid following cross-origin redirects with the Bearer header.
  • Log only the validated hostname, never the API key.
  • Document the exact data fields sent to the model provider.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_international_report.py:285
Finding

International model API key can be disclosed to an unrestricted endpoint override

Content
View full analysis

Vulnerability Details

File Location: scripts/generate_international_report.py:285-294
Vulnerability Type: Configurable credential exfiltration destination
Risk Level: Medium

Vulnerable Code

python
request = Request(
    f"{ARK_API_BASE.rstrip('/')}/responses",
    data=body,
    headers={
        "Content-Type": "application/json; charset=utf-8",
        "Authorization": f"Bearer {ARK_API_KEY}",
    },
    method="POST",
)

with urlopen(request, timeout=ARK_TIMEOUT_SECONDS) as response:
    response_payload = json.loads(response.read().decode("utf-8"))

The destination is controlled by:

python
ARK_API_BASE = os.getenv(
    "ARK_API_BASE",
    "https://ark.cn-beijing.volces.com/api/v3",
)

Technical Analysis

Any environment-provided API base receives the Volcengine Bearer key and international article data. No application-level scheme or hostname restriction ensures that the destination is the intended provider.

Although using a configurable compatible endpoint may be operationally useful, automatically pairing that endpoint with the same secret exceeds a safe least-privilege design unless the destination is explicitly trusted.

Attack Path

  1. ARK_API_BASE is changed to a malicious or unintended endpoint.
  2. International report generation starts with ARK_API_KEY configured.
  3. For each selected article, the code posts the prompt to that endpoint.
  4. The malicious server captures the Bearer key, article title, article content, source, time, and link.
  5. Retries can transmit the same data multiple times.

Impact Assessment

The attacker can misuse the model API credential within its assigned permissions and quota. The attacker also obtains international report input. The implementation does not use this route to upload arbitrary files from the workspace.

Remediation
View remediation

Remediation Suggestions

  • Enforce HTTPS and validate the destination hostname.
  • Allowlist the intended model provider.
  • Disable cross-origin redirects for authenticated requests.
  • Use separate credentials for separately configured providers.
  • Require an explicit opt-in for custom endpoints.
  • Provide a --disable-ai default in untrusted deployment environments until endpoint validation succeeds.

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Third-party dependencies are installed without version or integrity constraints

Content
View full analysis

Vulnerability Details

File Location: scripts/requirements.txt:1-2
Vulnerability Type: Unpinned dependency supply-chain risk
Risk Level: Medium

Vulnerable Code

text
openpyxl
python-docx

Technical Analysis

Both dependencies are specified without exact versions or package hashes. Each installation therefore resolves whatever versions the configured package index currently serves.

This makes deployments non-reproducible and prevents integrity verification. A compromised package release, compromised package index, or unsafe index configuration could cause malicious code to execute during installation or when the package is imported.

No evidence was found that the named dependencies are themselves malicious; the vulnerability is the absence of version and integrity controls.

Attack Path

  1. A dependency release or configured Python package index is compromised.
  2. A user follows the documented pip install -r scripts/requirements.txt command.
  3. Pip resolves the unrestricted dependency to the compromised distribution.
  4. Malicious package code executes during installation or subsequent import.
  5. The code runs with the privileges of the user operating the Skill.

Impact Assessment

Successful supply-chain compromise can obtain all permissions available to the installing or executing user, including access to the workspace, environment variables such as ARK_API_KEY, generated reports, and network connectivity.

Remediation
View remediation

Remediation Suggestions

  • Pin every direct dependency to a reviewed exact version.
  • Generate and verify cryptographic hashes using a lockfile or --require-hashes.
  • Review and pin transitive dependencies as well.
  • Install packages only from a trusted package index.
  • Use automated dependency scanning and controlled update review.
  • Build in an isolated environment with minimal privileges.

Example structure:

text
openpyxl==REVIEWED_VERSION --hash=sha256:REVIEWED_HASH
python-docx==REVIEWED_VERSION --hash=sha256:REVIEWED_HASH
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (26)

Tainted flow: 'request' from os.getenv (line 342, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The HTTP destination is derived from ARK_API_BASE in the environment and used directly for an authenticated outbound request carrying the Bearer token and article content. If an attacker can influence environment variables in the agent/workspace runtime, they can redirect requests to a malicious endpoint, exfiltrating the API key and potentially sensitive news content; in this skill context, automatic report generation makes such silent exfiltration more plausible.

Content

Scanner excerpt · scripts/generate_company_report.py (reported line 352)May include surrounding context.

python
method="POST",
    )

    with urlopen(request, timeout=ARK_TIMEOUT_SECONDS) as response:
        response_payload = json.loads(response.read().decode("utf-8"))

    text = extract_text_from_response(response_payload)

Tainted flow: 'request' from os.getenv (line 284, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The script constructs an outbound HTTP request using ARK_API_BASE and ARK_API_KEY from environment variables and sends full news content to that endpoint. Because the base URL is externally configurable, a compromised workspace or wrapper could redirect requests and exfiltrate data and bearer credentials to an attacker-controlled server; in this skill's 'self-contained workspace' context, the hidden external call makes the risk more significant.

Content

Scanner excerpt · scripts/generate_international_report.py (reported line 294)May include surrounding context.

python
method="POST",
    )

    with urlopen(request, timeout=ARK_TIMEOUT_SECONDS) as response:
        response_payload = json.loads(response.read().decode("utf-8"))

    text = extract_text_from_response(response_payload)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description promises a self-contained AI news workflow covering Chinese and international news, including optional high-frequency RSS capture, scheduled report delivery, cumulative Excel outputs, and a merged Word brief. The supplied code chunk is much narrower: it loads rows from existing Excel files, filters them by date/time window, selects top international items, and writes a formatted .docx brief. It does not fetch RSS feeds, schedule jobs, deliver reports, or create/update Excel outputs. The Word brief functionality is consistent with part of the description, but the actual code does not represent the broader declared workflow and instead implements only one downstream report-writing component.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code clearly supports part of the description: it is self-contained in the current workspace, reads domestic/international source configs, collects RSS/Atom items, and stores cumulative local outputs with deduplication and logging. However, the declared purpose promises a broader workflow including scheduled report delivery, cumulative Excel outputs, and a merged Word brief. None of those capabilities appear in this code chunk. The actual behavior is limited to network feed retrieval, filtering, state tracking, and JSONL persistence. Because major declared outputs and delivery/reporting functions are absent, the description does not accurately represent what this supplied code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code chunk is a report-generation component, not a full end-to-end news workflow. It reads existing local JSONL data files, filters/matches articles against companies.txt, optionally enriches matches via an external ARK model API, writes a cumulative Excel workbook, and creates a Word brief with imported international rows. The declared description promises a self-contained Chinese/international AI news workflow with modes for RSS capture-only or scheduled report delivery-only, but this script contains neither RSS ingestion nor scheduling/delivery logic. The external ARK API dependency also conflicts with the 'self-contained' characterization. While cumulative Excel output and a merged Word brief are partially consistent, the overall declared purpose materially overstates and mischaracterizes what this code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description covers a fairly broad self-contained AI news workflow with multiple operating modes and report-generation outputs. The supplied code chunk is a narrow wrapper script for capture-only execution: it accepts a workspace path, sets an environment variable, and delegates to collect_feeds.main(). That aligns with only one slice of the declared behavior (RSS capture only), but not the full described workflow including scheduled delivery and document outputs. Because the description presents capabilities materially broader than what this code chunk actually performs, this is a description-behavior mismatch for the provided code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code in run_full_workflow.py is an orchestrator that always performs both steps: feed collection and report building. The description says the skill should be used when the user wants either high-frequency RSS capture only or scheduled report delivery only, which implies selective single-mode operation; this script does not provide such branching and instead always runs the full workflow. It does align with using the current workspace and not an external repository path, and the optional time-window/disable-AI arguments are consistent with report generation support. However, the primary purpose as implemented is a full end-to-end runner, not the narrower 'capture only or report only' behavior described. Also, while downstream scripts may create Excel or Word outputs, that is not established by this supplied code chunk itself.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description covers a broader end-to-end AI news workflow with two possible operating modes: RSS capture only or scheduled report delivery only, plus cumulative Excel outputs and a merged Word brief. The supplied code chunk is specifically a 'report only' runner. It sets the workspace, derives a time window, and calls two report-generation modules for China and international reports. There is no RSS capture logic in this chunk, and the primary purpose is narrower than the declared description. While the script is consistent with the self-contained/current-workspace and merged Word brief aspects, the missing capture-only mode and narrower scope make the description inaccurate for this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description describes a complete AI news workflow with capture, reporting, and document generation. The supplied code chunk does not implement that workflow; it is a narrow helper module for time-window parsing/formatting and simple file-path lookup. While such utilities could support a reporting workflow, the actual code’s primary purpose is materially different and far more limited than the declared skill behavior.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill advertises executable scripts that read environment variables, access the filesystem, write reports/state, and perform network requests, but it does not declare any explicit tool scope such as permissions or allowed-tools. This weakens reviewability and policy enforcement because an agent may invoke capabilities broader than what the manifest makes obvious to users or security controls.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This file embeds a fixed Chinese locale in its generated document format, including Chinese font families and later Chinese section titles/content strings, with no opt-in or alternate locale path. That can violate language/locale policy when a skill forces a specific language experience rather than allowing user choice or clearly documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The prompt text explicitly instructs the model in Chinese and requires Chinese-character length limits and Chinese punctuation, which forces a specific language/locale behavior. The file does not offer a user opt-in or language selection, and no region-specific justification is documented here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The prompt explicitly instructs the model to generate the title and summary in Chinese and to translate ordinary English terms into Chinese. Because this is a code file, these natural-language strings are in scope for policy review, and there is no visible user choice or opt-in for language/locale behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code sends report data to an external AI service despite the skill description emphasizing a self-contained workflow in the current workspace. The main danger is undisclosed data egress: titles, content, source, time, and links are transmitted off-box, which may violate user expectations, policy boundaries, or handling requirements for sensitive inputs.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file documents outputs including multiple JSONL, Excel, and Word files, which means the skill modifies user workspace contents. Under SQP-2 for markdown files, descriptions should warn when behavior can affect user data or system state, but no warning or disclosure is provided near these instructions or output descriptions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The markdown indicates that AI fields depend on ARK_API_KEY and model/API connectivity, implying data may be sent to external AI services during report generation. The skill description does not include a user-facing privacy or network-use warning, which is expected for markdown files when behavior may affect privacy or transmit data externally.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The stated purpose is an AI news capture/report workflow with local cumulative outputs, but the script depends on externally supplied environment-based credentials and endpoint configuration. Reading ARK_API_KEY and related endpoint settings introduces a credential/configuration capability that is not reflected in the manifest's purpose description.

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/collect_feeds.py (reported line 126)May include surrounding context.

python
def configure_output_encoding() -> None:
    for stream_name in ("stdout", "stderr"):
        stream = getattr(sys, stream_name, None)
        reconfigure = getattr(stream, "reconfigure", None)
        if callable(reconfigure):
            reconfigure(encoding="utf-8", errors="replace")

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/generate_company_report.py (reported line 73)May include surrounding context.

python
def configure_output_encoding() -> None:
    for stream_name in ("stdout", "stderr"):
        stream = getattr(sys, stream_name, None)
        reconfigure = getattr(stream, "reconfigure", None)
        if callable(reconfigure):
            reconfigure(encoding="utf-8", errors="replace")

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/generate_international_report.py (reported line 69)May include surrounding context.

python
def configure_output_encoding() -> None:
    for stream_name in ("stdout", "stderr"):
        stream = getattr(sys, stream_name, None)
        reconfigure = getattr(stream, "reconfigure", None)
        if callable(reconfigure):
            reconfigure(encoding="utf-8", errors="replace")

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
88% confidence
Finding

The dependency openpyxl is unpinned, which reduces build reproducibility and can result in unexpected installation of a vulnerable or breaking version in the future. Because this skill generates cumulative Excel outputs, the package is part of the main processing path and should be version-controlled for safety and stability.

Content

Scanner excerpt · scripts/requirements.txt (reported line 1)May include surrounding context.

text
openpyxl
python-docx

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency python-docx is unpinned, so installs may resolve to different versions over time, including vulnerable or incompatible releases. This is more concerning here because the skill processes document files, and python-docx has known historical security advisories involving XML parsing behavior.

Content

Scanner excerpt · scripts/requirements.txt (reported line 2)May include surrounding context.

text
openpyxl
python-docx

Unverifiable Dependency: python-docx has 2 known advisory(ies) (CVE-2016-5851 (Improper Restriction of XML External Entity Reference in python-docx); CVE-2016-5851 (python-docx before 0.8.6 allows context-dependent attackers to conduct XML Exter)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The manifest does not pin python-docx, and that package has known advisories affecting some historical versions, including XML external entity handling. Since the installed version cannot be verified from this file, the environment could resolve to an affected release, which matters more in a workflow that creates or potentially handles Office documents.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This code sets the AI_NEWS_WORKSPACE environment variable, which modifies process environment state and may influence downstream behavior, but there is no explicit user disclosure about this action. The existing step logs describe feed collection and report building, not the environment mutation itself.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.