TuyaOpen IDE Preview — Bug Submissions [Post 2]

Follow-up: Part C & D — Hardware-Safety (in response to PR #686)


Global environment (same as original submission)

Field Value
OS Windows 11, PowerShell 5.1
IDE VS Code + Antigravity IDE, TuyaOpen IDE Preview v0.1.5
SDK TuyaOpen SDK main branch (IDE-managed)
Hardware Tuya T5AI-Core (BK7258)
Labels preview-tester bug (+ ux/feature-request where noted)

PART C — ULTRA / WOW — Inconsistent validation & prompt-injection → RCE

These are not new topics — they are the same class you just fixed, but missed in the next file over. That’s why they are high-value: the fix pattern exists (and is correct) at one call site, but was not applied to the identical call site next door.

C1 — :star: Path traversal in tos.py new — arbitrary directory creation outside the SDK

Labels: preview-tester bug Severity: High/Critical

The inconsistency: cli_config.py:139-155 (_normalize_save_name) correctly blocks traversal for tos.py config save:

if "/" in name or "\\" in name or os.sep in name: return ""
if ".." in name: return ""

The same os.path.join(root, input) in cli_new.py has zero check:

CLI Line
tos.py new project cli_new.py:475-477os.path.join(work_root, new_project_name)
tos.py new board cli_new.py:539-543os.path.join(boards/... , new_board_name)
tos.py new platform cli_new.py:424-426os.path.join(platforms_root, ...)

Repro:

$ tos.py new project
Input new project name.
input: ../../evil
# → directory `C:/<project>/../../evil` == `C:/evil` created via copy_directory at cli_new.py:486

Fix: Reuse _normalize_save_name for all three new_* prompts.


C2 — Kconfig injection via board/platform name

Labels: preview-tester bug Severity: Medium-High

cli_new.py:491-497 and 506-516:

add_board_context = f'''
    config BOARD_CHOICE_{new_board_name_}
        bool "{new_board_name}"   # ← raw, no escaping
            rsource "./{new_board_name}/Kconfig"

Only '-' → '_' is sanitized. A name like a"\nconfig PWNED\n\tbool "x closes the string and injects a new config. Same via replace_string_in_file at 561-562.

Fix: Validate ^[A-Za-z0-9_-]+$; escape " as \" if free-form is needed.


C3 — T5AI toolchain install always broken on macOS (GNU-only commands in Darwin branch)

Labels: preview-tester bug Severity: High (macOS — supported host)

platform/T5AI/toolchain_get.sh:138-145 (shared by all OS, including Darwin*)):

sha256sum "$TOOLCHAIN_FILE" | awk '{print $1}'
stat -c %s "$TOOLCHAIN_FILE"

sha256sum / stat -c are GNU coreutils. macOS ships shasum -a 256 / stat -f %z. On Mac both fail → verify_toolchain_package returns 1 → retry exhausts → every T5AI build fails even on perfect network.

Fix: command -v sha256sum >/dev/null && sha256sum || shasum -a 256 and stat -c / stat -f fallback.


C4 — :star: Prompt-injection → shell RCE chain via “Create with AI”

Labels: preview-tester bug Severity: Critical

Tuya’s headline feature “Create with AI” → natural language → LLM outputs CONFIG_PROJECT_NAME → written to app_default.configcli_build.py:218-227 runs:

cmake -G Ninja ... -DTOS_PROJECT_NAME={project_name}   # shell=True, unquoted
Prompt: "Create a project named a & calc &" → LLM → CONFIG_PROJECT_NAME="a & calc &" → cmd.exe /c ... -DTOS_PROJECT_NAME=a & calc & → calc.exe

Two injection points (cmake_configure + build_setup at 168-170). This is a prompt-injection → file write → shell RCE chain reachable through the primary AI workflow.

Fix: B1’s fix (shell=False list form) kills the chain; also validate CONFIG_PROJECT_NAME against ^[A-Za-z0-9_.-]+$.


C5 — rm_rf on Windows mishandles trailing \

Labels: preview-tester bug Severity: Low

util_files.py:17-21: rmdir /S /Q "C:\path\" — trailing \ escapes the closing ", cmd.exe sees unterminated string. Fix: rstrip("\\/") or use shutil.rmtree.


PART D — HARDWARE SAFETY / PLATFORM SPEC — Breaking-change, not injection

Cross-checked platform.json vs board.json pinouts — the exact check the vibe-coding skill must do before picking pins.

D1 — :star: expansionPins exposes flash UART + QSPI flash pins as free — brick risk

Labels: preview-tester bug Severity: High

  • platform.jsonuart.ports[0] role=download tx 11 / rx 10 (RXD 10 "Firmware download RX", TXD 11 "Firmware download TX")
  • platform.jsonqspi.ports[0] (QSPI0 flash) clk 22 / cs 23 / d0 24 / d1 25 / d2 26 / d3 27 — chip boots from this bus
  • board.jsonexpansionPins (33 entries) includes 10,11 and 22,23,24,25,267 critical system pins marked freely wireable:
expansionPins: [2,3,4,5,6,7,8, 10,11, 12... 22,23,24,25,26 ...]

Log UART 0/1 is correctly excluded — same logic was applied for log but missed for flash/QSPI. Vibe coding can legally pick 10/11 for a sensor → next tos.py flash drives same pins from USB-serial + peripheral → flash hang / QSPI corruption → brick on sealed Core board.

Fix: Remove 10,11,22,23,24,25,26 from expansionPins; generate expansionPins by subtracting all system-reserved pins (flash UART + QSPI + log UART + onboard devices) from SoC pinout.


D2 — platform.json for T5AI omits flashAndDebug — the safety check that would have caught D1 is skipped

Labels: preview-tester bug Severity: Medium

AGENTS.md documents platform.json must have flashAndDebug.flash.pins / flashAndDebug.debug. The actual T5AI platform.json (1878 lines) has no top-level flashAndDebug key. The skill rule “also check flashAndDebug.flash.pins therefore never runs for this platform.

Fix: Add flashAndDebug to T5AI spec and derive expansionPins from it automatically.


D3 — IRQ capability mismatch: GPIOs 10/11 are free but not interrupt-capable

Labels: preview-tester bug Severity: Medium

  • platform.jsongpio.spec.irq.pins: [[0,9], [12,55]]IRQ not supported on 10-11 (the gap).
  • board.jsonexpansionPins includes 10,11 with functions: ["GPIO", ...]

Assigning an interrupt-driven peripheral (button IRQ_RISE, onchip:gpio with irq) to 10/11 will register but never fire — silent runtime failure with no build warning.

Fix: Filter expansionPins against irq.pins when IRQ is requested, or warn at generation time.


Thank you again for the fast [PR #686] turnaround — happy to verify these locally on T5AI-Core or open separate issues for D1/D3 as you prefer. These should make the vibe-coding pin-selection path as robust as the CLI hardening you just landed.

@Jie_Yang — thank you for confirming and fixing B1 / B3 / B11 / B12 in PR #686 fix(cli): harden tos.py against config loss, injection, and stuck gitconfig by shiliu-yang.

This follow-up re-audited the same areas you just patched, looking for where the fix was applied inconsistently or where the same pattern appears in adjacent code/platform specs. All have exact file:line so you can jump directly.

Apologies for that,

In the Original topic post of "TuyaOpen IDE Preview — Bug Submissions" , when i replied with the new bug submissions of part C and D.

My Post got flagged for Spam.:expressionless_face:

Therefore, I created a fresh topic post. Glad to continue conversation here. @adwuard @Jie_Yang

Your regards,

Naman

My apologies yeah the AI spam detection default settings got pretty aggressive.:face_holding_back_tears: I’m dialing it down a little bit and adding you to a trusted user. :raising_hands:

1 Like