T09 · Insecure Skill Coding Practices
- Location
scripts/sch.py:60- Finding
Unsafe schematic mutation through unrestricted debug.exec_js helper
- Content
View full analysis
Vulnerability Details
File Location:
scripts/sch.py:60-140
Vulnerability Type: Bypass of typed design-write controls through arbitrary JavaScript execution
Risk Level: HighVulnerable Code
python def ejs(code, timeout=90): return _cli(['call', 'debug.exec_js', '--payload', json.dumps({'code': code})], timeout)python def place(lib, uuid, x, y, designator): return ejs(f"const c=await eda.sch_PrimitiveComponent.create({{libraryUuid:'{lib}',uuid:'{uuid}'}},{int(x)},{int(y)});" f"const pid=c.getState_PrimitiveId();try{{await eda.sch_PrimitiveComponent.modify(pid,{{designator:'{designator}'}});}}catch(e){{}}return pid;") def move(designator, x, y): return ejs(f"for(const c of await eda.sch_PrimitiveComponent.getAll())if(c.getState_Designator()==='{designator}')" f"{{await eda.sch_PrimitiveComponent.modify(c.getState_PrimitiveId(),{{x:{int(x)},y:{int(y)}}});return 1;}}return 0;") def delete(designators): return ejs("const D=" + json.dumps(designators) + ";const ids=[];for(const c of await eda.sch_PrimitiveComponent.getAll())" "if(D.includes(c.getState_Designator()))ids.push(c.getState_PrimitiveId());" "if(ids.length)await eda.sch_PrimitiveComponent.delete(ids);return ids.length;") def clear_wires_flags(): return ejs("const w=[];for(const x of await eda.sch_PrimitiveWire.getAll())w.push(x.getState_PrimitiveId());" "if(w.length)await eda.sch_PrimitiveWire.delete(w);const f=[];" "for(const c of await eda.sch_PrimitiveComponent.getAll()){const t=c.getState_ComponentType();" "if(t!=='part'&&t!=='sheet')f.push(c.getState_PrimitiveId());}" "if(f.length)await eda.sch_PrimitiveComponent.delete(f);return [w.length,f.length];")Technical Analysis
The helper exposes
ejs()as a generic bridge to the EasyEDA daemon's `debug.exec_j ...[truncated 2603 chars]- Remediation
View remediation
Remediation Suggestions
- Remove mutation through
debug.exec_jsfrom the distributed Skill. - Reimplement placement, movement, wiring, and deletion using typed EasyEDA actions or
easyeda apply. - Require callers to provide and verify the expected project, document UUID, and page identity before every mutation.
- Add a mandatory dry-run that returns the exact object IDs and operation plan before destructive changes.
- Require an explicit confirmation token tied to the generated plan for bulk deletion or clearing operations.
- Replace
clear_wires_flags()with a scope-limited operation that accepts an explicit allowlist of object IDs and rejects empty, wildcard, or whole-document targets by default. - Preserve a pre-mutation snapshot and perform fresh readback after each operation, failing closed if document identity or state changed.
- If the helper is needed only for legacy development, exclude it from the packaged Skill and prevent Agent workflows from invoking it.
- Remove mutation through
