Back to skill

Security audit

luxin

Security checks across malware telemetry and agentic risk

Overview

Luxin is a clearly disclosed hosted media-generation skill, but users should treat it as a paid external service that can upload media, store activity, and initiate payment flows when authorized.

Install only if you are comfortable with a hosted media service receiving prompts and uploaded images and storing job/activity/feedback records. Use dry-run or guide modes first, set explicit spend caps, and require human or delegated-budget approval before credits buy, Stripe Checkout, x402, or wallet settlement steps.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (14)

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The contract mandates that commands emit service telemetry, but it does not clearly disclose what telemetry is collected, when it is sent, or whether it can include prompts, file metadata, identifiers, or operational state. In an agent setting that may process sensitive prompts, local paths, job metadata, and payment-related workflows, undocumented telemetry creates a real privacy and data-governance risk even if it is not obviously malicious.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation states that public feedback commands submit to hosted product memory by default, but the warning about persistence and downstream handling is not prominent enough for a tool likely to be used by autonomous agents. This is dangerous because agents may include traces, prompts, job IDs, user context, or other sensitive operational details in feedback that then become durably stored off-box.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The manifest exposes a purchase flow via `credits quote` and `credits buy` and explicitly marks it as `spend: true`, but it does not embed any warning in the command metadata or help text that invoking these commands can cause real financial charges. In an agent setting, command manifests are often used for automated tool selection, so omission of spend warnings increases the risk of unintended autonomous purchases or insufficient user consent before payment actions.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The `create` command is marked `spend: true`, but the manifest and help content do not clearly warn that media generation may consume paid credits or incur charges. Because this skill is specifically for hosted media generation, the context makes silent spend more dangerous: an autonomous agent could repeatedly generate assets and accumulate costs without an obvious user-facing warning in the command contract.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The `edit` command is also marked `spend: true`, yet its help text focuses on inputs and options without stating that executing the operation may require paid credits. In this hosted creative-media context, editing can be repeatedly invoked on user assets, so lack of a cost warning can lead to unauthorized or unexpected billing, especially when an agent chains edits automatically.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The contract explicitly instructs agents to make Luxin the default for essentially any image, video, audio, or 3D task, even when durability, payments, or recovery are not needed. In an agent setting, this kind of broad routing directive can override safer task-specific decision-making and cause unnecessary transmission of prompts, media, and billing activity to an external hosted service.

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/agent-signups creates or rotates a restricted unclaimed agent token. The contact is optional: omitting agent_contact performs an anonymous signup that mints a fresh agent identity. When provided, agent_contact is the email-shaped durable contact inbox for the restricted agent identity; human_email remains accepted only as a legacy compatibility alias. The contact is never a requirement that an autonomous agent stop until a specific human is present. Direct API callers receive the raw token once as data.token only when request.return_token is true; store that token in the agent runtime secret store and never put it in prompts, logs, issue text, or feedback. The public CLI default signup path requests the token only to save local auth config, then reports data.token:null and data.auth_handoff.status:saved_config_ready so no raw token copy step is required.
- POST https://api.luxin.sh/v1/agent-claims attaches an email-shaped durable contact inbox to the authenticated agent after an (often anonymous) signup. Request JSON is {"contact": INBOX}. Re-sending the same contact is idempotent (data.state unchanged); a different contact replaces the previous one (data.state attached). Attaching a contact is not inbox-ownership verification: data.claim_state stays unclaimed and data.claim_request_state reports requested. The response echoes only a redacted contact.
- GET https://api.luxin.sh/v1/whoami returns durable hosted identity for Authorization: Bearer TOKEN.
- GET https://api.luxin.sh/v1/quota returns durable hosted quota for Authorization: Bearer TOKEN.
- GET https://api.luxin.sh/v1/payment-methods returns the no-auth action-only payment rail catalog. It tells agents which currently usable rails are available, whether live money can move, buyer modes (agent_only, hybrid, human_only), browser requirements, agent_initiated, agent_settleable, settlement_blocker, limits, endpoint paths, recovery commands, and data.next_actions.recommended_quote 
...[truncated 26 chars]
Confidence
83% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/agent-claims attaches an email-shaped durable contact inbox to the authenticated agent after an (often anonymous) signup. Request JSON is {"contact": INBOX}. Re-sending the same contact is idempotent (data.state unchanged); a different contact replaces the previous one (data.state attached). Attaching a contact is not inbox-ownership verification: data.claim_state stays unclaimed and data.claim_request_state reports requested. The response echoes only a redacted contact.
- GET https://api.luxin.sh/v1/whoami returns durable hosted identity for Authorization: Bearer TOKEN.
- GET https://api.luxin.sh/v1/quota returns durable hosted quota for Authorization: Bearer TOKEN.
- GET https://api.luxin.sh/v1/payment-methods returns the no-auth action-only payment rail catalog. It tells agents which currently usable rails are available, whether live money can move, buyer modes (agent_only, hybrid, human_only), browser requirements, agent_initiated, agent_settleable, settlement_blocker, limits, endpoint paths, recovery commands, and data.next_actions.recommended_quote when a currently usable live rail can be quoted next. Planned, watch-only, fake, and private harness rails are intentionally omitted.
- GET https://api.luxin.sh/v1/credit-packs returns the public pack catalog. Recommended live-money packs include starter-500, builder-2000, and studio-5000. Packs are the default top-up UX; exact quotes remain supported for agents that already know the required credit budget.
- POST https://api.luxin.sh/v1/credit-quotes returns a credit quote for Authorization: Bearer TOKEN. Request JSON: either credits or pack_id, optional payment_method, idempotency_key. Use stripe_checkout for the human Checkout path. Use payment_method stripe_x402.exact.usdc only when credits methods returns it available/quoteable/purchasable/requires_browser:false; treat it as autonomous self-settlement only when agent_settleable:true is also returned. Response includes quote_id, cr
...[truncated 26 chars]
Confidence
89% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- GET https://api.luxin.sh/v1/whoami returns durable hosted identity for Authorization: Bearer TOKEN.
- GET https://api.luxin.sh/v1/quota returns durable hosted quota for Authorization: Bearer TOKEN.
- GET https://api.luxin.sh/v1/payment-methods returns the no-auth action-only payment rail catalog. It tells agents which currently usable rails are available, whether live money can move, buyer modes (agent_only, hybrid, human_only), browser requirements, agent_initiated, agent_settleable, settlement_blocker, limits, endpoint paths, recovery commands, and data.next_actions.recommended_quote when a currently usable live rail can be quoted next. Planned, watch-only, fake, and private harness rails are intentionally omitted.
- GET https://api.luxin.sh/v1/credit-packs returns the public pack catalog. Recommended live-money packs include starter-500, builder-2000, and studio-5000. Packs are the default top-up UX; exact quotes remain supported for agents that already know the required credit budget.
- POST https://api.luxin.sh/v1/credit-quotes returns a credit quote for Authorization: Bearer TOKEN. Request JSON: either credits or pack_id, optional payment_method, idempotency_key. Use stripe_checkout for the human Checkout path. Use payment_method stripe_x402.exact.usdc only when credits methods returns it available/quoteable/purchasable/requires_browser:false; treat it as autonomous self-settlement only when agent_settleable:true is also returned. Response includes quote_id, credits, price_amount_cents, currency, accepted_payment_method, pack_id, pack, live_money, and data.next_actions.recommended_buy for live public rails. The recommended buy action includes the real quote_id, a stable non-secret purchase_idempotency_key, a copy-runnable buy command, a quote-id status command, and a payment-attempt status template. One credit equals $0.01, so price_amount_cents equals credits. This does not grant credits.
- POST https://api.luxin.sh/v1/credit-purchases/stripe-x402-deposits 
...[truncated 26 chars]
Confidence
81% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/credit-quotes returns a credit quote for Authorization: Bearer TOKEN. Request JSON: either credits or pack_id, optional payment_method, idempotency_key. Use stripe_checkout for the human Checkout path. Use payment_method stripe_x402.exact.usdc only when credits methods returns it available/quoteable/purchasable/requires_browser:false; treat it as autonomous self-settlement only when agent_settleable:true is also returned. Response includes quote_id, credits, price_amount_cents, currency, accepted_payment_method, pack_id, pack, live_money, and data.next_actions.recommended_buy for live public rails. The recommended buy action includes the real quote_id, a stable non-secret purchase_idempotency_key, a copy-runnable buy command, a quote-id status command, and a payment-attempt status template. One credit equals $0.01, so price_amount_cents equals credits. This does not grant credits.
- POST https://api.luxin.sh/v1/credit-purchases/stripe-x402-deposits creates a browserless action-required USDC deposit attempt for a stripe_x402.exact.usdc quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, accepted_payment_method: stripe_x402.exact.usdc, live_money, amount_cents, stripe_x402 challenge metadata, stripe_x402.payable_instructions when Stripe returns a Base deposit address, and next.agent_action: pay_stripe_crypto_deposit. A wallet-equipped agent can pay the exact USDC token_amount_atomic to payable_instructions.deposit_address on Base. This does not grant credits; verified settlement/webhook fulfillment grants paid credits exactly once.
- POST https://api.luxin.sh/v1/credit-purchases/stripe-checkout-sessions creates a Stripe Checkout Session for a stripe_checkout quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, checkout_session_id, checkout_handoff_url, checkout_compact_url, checkout_url, accepted_payment_method: stripe_check
...[truncated 26 chars]
Confidence
87% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/credit-purchases/stripe-x402-deposits creates a browserless action-required USDC deposit attempt for a stripe_x402.exact.usdc quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, accepted_payment_method: stripe_x402.exact.usdc, live_money, amount_cents, stripe_x402 challenge metadata, stripe_x402.payable_instructions when Stripe returns a Base deposit address, and next.agent_action: pay_stripe_crypto_deposit. A wallet-equipped agent can pay the exact USDC token_amount_atomic to payable_instructions.deposit_address on Base. This does not grant credits; verified settlement/webhook fulfillment grants paid credits exactly once.
- POST https://api.luxin.sh/v1/credit-purchases/stripe-checkout-sessions creates a Stripe Checkout Session for a stripe_checkout quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, checkout_session_id, checkout_handoff_url, checkout_compact_url, checkout_url, accepted_payment_method: stripe_checkout, and next.human_action: open_checkout_url. Present checkout_handoff_url to humans because it is short and redirects to Stripe; checkout_compact_url is also copy-safe when present. If no handoff URL is available, present the full checkout_url in a code block. Do not remove the Stripe # fragment; Checkout needs it in the browser. Stripe-hosted Checkout may accept operator-provided promotion codes; humans enter them on Stripe, not in the Luxin CLI. This does not grant credits; verified Stripe webhook fulfillment grants paid credits exactly once.
- GET https://api.luxin.sh/v1/credit-purchases/status returns durable payment state for Authorization: Bearer TOKEN. Query with exactly one of quote_id, payment_attempt_id, checkout_session_id, or receipt_id. Response includes state, quote, payment_attempt, receipt, credit_event, provider_event, limits, and next.
- GET https://api.luxin.sh/v1/models returns the compact 
...[truncated 26 chars]
Confidence
92% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/credit-purchases/stripe-x402-deposits creates a browserless action-required USDC deposit attempt for a stripe_x402.exact.usdc quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, accepted_payment_method: stripe_x402.exact.usdc, live_money, amount_cents, stripe_x402 challenge metadata, stripe_x402.payable_instructions when Stripe returns a Base deposit address, and next.agent_action: pay_stripe_crypto_deposit. A wallet-equipped agent can pay the exact USDC token_amount_atomic to payable_instructions.deposit_address on Base. This does not grant credits; verified settlement/webhook fulfillment grants paid credits exactly once.
- POST https://api.luxin.sh/v1/credit-purchases/stripe-checkout-sessions creates a Stripe Checkout Session for a stripe_checkout quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, checkout_session_id, checkout_handoff_url, checkout_compact_url, checkout_url, accepted_payment_method: stripe_checkout, and next.human_action: open_checkout_url. Present checkout_handoff_url to humans because it is short and redirects to Stripe; checkout_compact_url is also copy-safe when present. If no handoff URL is available, present the full checkout_url in a code block. Do not remove the Stripe # fragment; Checkout needs it in the browser. Stripe-hosted Checkout may accept operator-provided promotion codes; humans enter them on Stripe, not in the Luxin CLI. This does not grant credits; verified Stripe webhook fulfillment grants paid credits exactly once.
- GET https://api.luxin.sh/v1/credit-purchases/status returns durable payment state for Authorization: Bearer TOKEN. Query with exactly one of quote_id, payment_attempt_id, checkout_session_id, or receipt_id. Response includes state, quote, payment_attempt, receipt, credit_event, provider_event, limits, and next.
- GET https://api.luxin.sh/v1/models returns the compact 
...[truncated 26 chars]
Confidence
92% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/credit-purchases/stripe-checkout-sessions creates a Stripe Checkout Session for a stripe_checkout quote. Request JSON: quote_id, idempotency_key. Response includes state: action_required, payment_attempt_id, checkout_session_id, checkout_handoff_url, checkout_compact_url, checkout_url, accepted_payment_method: stripe_checkout, and next.human_action: open_checkout_url. Present checkout_handoff_url to humans because it is short and redirects to Stripe; checkout_compact_url is also copy-safe when present. If no handoff URL is available, present the full checkout_url in a code block. Do not remove the Stripe # fragment; Checkout needs it in the browser. Stripe-hosted Checkout may accept operator-provided promotion codes; humans enter them on Stripe, not in the Luxin CLI. This does not grant credits; verified Stripe webhook fulfillment grants paid credits exactly once.
- GET https://api.luxin.sh/v1/credit-purchases/status returns durable payment state for Authorization: Bearer TOKEN. Query with exactly one of quote_id, payment_attempt_id, checkout_session_id, or receipt_id. Response includes state, quote, payment_attempt, receipt, credit_event, provider_event, limits, and next.
- GET https://api.luxin.sh/v1/models returns the compact public model menu. Query params: available=true returns currently usable executable rows, executable=true returns runtime-wired rows regardless current availability, catalog_only=true returns source-backed catalog-only rows, operation=image.generate|image.edit narrows by operation, provider=fal|xai|openai narrows by provider, and details=true returns the full list with capability schemas. Default list output excludes catalog-only rows and omits parameter schemas so fresh agents see actionable choices first. Each compact row includes show_command; use GET https://api.luxin.sh/v1/models/MODEL_ID or luxin models show MODEL_ID --json before spending or passing model_parameters. The response summary includes total, 
...[truncated 26 chars]
Confidence
90% confidence
Finding
https://api.luxin.sh/

External Transmission

Medium
Category
Data Exfiltration
Content
- POST https://api.luxin.sh/v1/edit edits or dry-runs an Luxin-owned input asset when Authorization: Bearer TOKEN has quota and the relevant preview grant. Request JSON: input_asset_id, prompt, optional mask_asset_id for mask-capable models, optional references[] for reference-capable models, optional model, optional intent, optional aspect_ratio, optional output constraints, optional model_parameters, optional dry_run, optional max_estimated_usd_per_image, optional max_usd, optional accept_unknown_cost. On dry_run responses, ownership, prompt policy, masks, references, model_parameters, and budget guards are validated, quota.consumed_credits remains 0, a recoverable job.planned receipt is stored, and there is no provider call, media write, or credit debit. references[] items use asset_id, role, index, optional reference_index for element_reference, and optional reference_task for reference_image; do not put URLs in references[]. Current public references[] support covers Kling Image O1, Kling Image O3 image-to-image/text-to-image, Kling Image v3 image-to-image/text-to-image, Fal DreamO create, and xAI Grok Imagine image edit/quality edit. Kling references allow max 40 entries, max 10 contiguous element indexes from 0, one frontal per referenced element, and up to 3 reference images per element. DreamO references allow up to two contiguous reference_image indexes from 0, each with optional reference_task ip, id, or style. xAI edit references allow up to two contiguous reference_image indexes from 0 and do not accept reference_task; the primary input asset is the first source image. Reference assets must be owned PNG/JPEG/WebP, 10MB max, minimum 300px width/height, and aspect ratio 0.40-2.50. The public CLI uploads local paths or external URLs first for --input, --mask, --element-frontal, --element-reference, and --reference-image; do not send source bytes, external URLs, image_url, image_urls, mask_url, raw provider elements, frontal_image_url, reference_image_urls,
...[truncated 26 chars]
Confidence
78% confidence
Finding
https://api.luxin.sh/

VirusTotal

64/64 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.