Your extension is looking pretty cool. And your model suggests people are going to have to up their robot modeling game⦠big time!
I thought Iād send a scan of your extension from another extension Iām working on that tries to prepare them for EW review. The focus is in finding security issues, common reasons for rejection, and some basic code quality review. The results may point to some things that are low priority/false positives. But there are a few items that you might want to address. I hope you find it useful.
Extension Preflight Report
# Extension Preflight Report
Target: C:/Users/
Target type: folder
Signature metadata: detected (arcticulation_tool/arcticulation_tool.susig)
Package root: C:/Users/
Selection type: extension_folder
Detected extension name: ARCticulation Tool
Root loader: arcticulation_tool.rb
Extension folder: arcticulation_tool
Extension version: 0.8.4.4
Extension creator: Arcwalde
Extension description: Mechanical articulation tools for SketchUp: Smart Motion, Joint Limits, Pose Presets, Export Hub, and Origin Manager.
Extension copyright: Copyright (c) 2026 Arcwalde
Generated: 2026-07-04T17:22:12Z
Readiness: Needs attention
Scope note: Static preflight results are review candidates, not Extension Warehouse approval.
## Summary
- Files seen: 72
- Files scanned: 58
- Files skipped: 14
- Findings total: 19
## Findings
- [P2/medium] Interpolated execute_script call detected
Location: arcticulation_tool/tools/core/diagnostics_panel.rb:91
Rule: HTML002 (HtmlDialog Safety)
Evidence: dialog.execute_script(āwindow.#{js_function} && window.#{js_function}(#{json_for_script(line.to_s)});ā)
Why it matters: Interpolating Ruby values into JavaScript can create injection bugs.
Conservative fix: Serialize dynamic values with JSON.generate or to_json and keep receiver names fixed.
- [P2/medium] Destructive file operation needs review
Location: arcticulation_tool/tools/export_hub.rb:968
Rule: DATA004 (Data Loss)
Evidence: File.delete(tmp) if tmp && File.exist?(tmp)
Why it matters: Deleting, truncating, or recursively removing files can destroy user data when paths are broad, user-controlled, or not constrained.
Conservative fix: Constrain destructive file operations to extension-owned temp/cache paths, confirm user intent, and canonicalize paths before deletion.
- [P2/medium] Model#delete_attribute may rely on a monkey-patched API
Location: arcticulation_tool/tools/pose_presets/storage.rb:125
Rule: COMPAT002 (SketchUp API Compatibility)
Evidence: model.delete_attribute(DICTIONARY, ROUTES_KEY) rescue nil
Why it matters: Sketchup::Model#delete_attribute is not part of the official SketchUp API in RuboCop-SketchUp guidance and may only exist when another extension monkey-patches it.
Conservative fix: Avoid relying on Model#delete_attribute, or guard it and provide a fallback such as writing nil or rebuilding extension-owned model attributes safely.
- [P2/medium] Model#delete_attribute may rely on a monkey-patched API
Location: arcticulation_tool/tools/pose_presets/storage.rb:266
Rule: COMPAT002 (SketchUp API Compatibility)
Evidence: model.delete_attribute(DICTIONARY, CURRENT_POSE_KEY) rescue nil
Why it matters: Sketchup::Model#delete_attribute is not part of the official SketchUp API in RuboCop-SketchUp guidance and may only exist when another extension monkey-patches it.
Conservative fix: Avoid relying on Model#delete_attribute, or guard it and provide a fallback such as writing nil or rebuilding extension-owned model attributes safely.
- [P3/medium] Path construction uses _dir_ or _FILE_ directly
Location: arcticulation_tool/main.rb:8
Rule: LOAD007 (Loader)
Evidence: ROOT_DIR = File.expand_path(_dir_) unless const_defined?(:ROOT_DIR, false)
Why it matters: SketchUp Ruby has had path-encoding edge cases around _FILE_ and _dir_; RuboCop-SketchUp recommends duplicating and forcing encoding before path operations.
Conservative fix: Use a small path helper that duplicates _dir_ or _FILE_ and forces UTF-8 before File.expand_path, File.dirname, or File.join path construction.
- [P3/low] Helper model mutation should be verified inside an operation
Location: arcticulation_tool/tools/core/joint_limits/config.rb:28
Rule: UNDO001 (Operations)
Evidence: attribute mutation: source.set_attribute(DICTIONARY, keyer.call(āallowedā), allowed ? true : false)
Why it matters: This file mutates SketchUp model entities without a local operation wrapper, but another scanned file has visible start, commit, and abort operation handling. Static review cannot prove the call path.
Conservative fix: Verify user-facing commands reach this helper inside one reliable SketchUp operation. Keep operation ownership at the command/workflow layer rather than adding nested operations in low-level geometry helpers.
- [P3/medium] Model root entities access needs review
Location: arcticulation_tool/tools/export_hub.rb:442
Rule: SEL003 (Selection And Entity Assumptions)
Evidence: scan_portable_entities(model.entities, [], [], root_world, entries, 0, definition_cache) if model && model.respond_to?(:entities)
Why it matters: Using model.entities targets the model root, not the active editing context. Commands usually should respect the user context with model.active_entities.
Conservative fix: Prefer model.active_entities unless the command intentionally works at the model root and documents that behavior.
- [P3/medium] Model root entities access needs review
Location: arcticulation_tool/tools/pose_presets/context_resolution.rb:97
Rule: SEL003 (Selection And Entity Assumptions)
Evidence: scan_entities_for_pid(model.entities, target_pid, identity_transform, [], matches, 0, []) if model && model.respond_to?(:entities)
Why it matters: Using model.entities targets the model root, not the active editing context. Commands usually should respect the user context with model.active_entities.
Conservative fix: Prefer model.active_entities unless the command intentionally works at the model root and documents that behavior.
- [P3/medium] Model root entities access needs review
Location: arcticulation_tool/tools/pose_presets/context_resolution.rb:110
Rule: SEL003 (Selection And Entity Assumptions)
Evidence: scan_entities_for_context_index(model.entities, identity_transform, [], index, 0, [])
Why it matters: Using model.entities targets the model root, not the active editing context. Commands usually should respect the user context with model.active_entities.
Conservative fix: Prefer model.active_entities unless the command intentionally works at the model root and documents that behavior.
- [P3/low] Helper model mutation should be verified inside an operation
Location: arcticulation_tool/tools/pose_presets/placement_frame.rb:704
Rule: UNDO001 (Operations)
Evidence: attribute mutation: model.set_attribute(DICTIONARY, PLACEMENT_STATE_KEY, JSON.generate(state.is_a?(Hash) ? state : {}))
Why it matters: This file mutates SketchUp model entities without a local operation wrapper, but another scanned file has visible start, commit, and abort operation handling. Static review cannot prove the call path.
Conservative fix: Verify user-facing commands reach this helper inside one reliable SketchUp operation. Keep operation ownership at the command/workflow layer rather than adding nested operations in low-level geometry helpers.
- [P3/low] Drawing tool should invalidate the view when deactivated or suspended
Location: arcticulation_tool/tools/smart_motion_tool.rb
Rule: TOOL001 (Tools And View Drawing)
Evidence: Missing or incomplete: deactivate(view), suspend(view)
Why it matters: Tools that draw temporary viewport graphics should clear stale drawing when SketchUp deactivates or suspends the tool.
Conservative fix: Implement deactivate(view) and suspend(view), and call view.invalidate from those lifecycle methods.
- [P3/medium] Tool accepts VCB input without enableVCB?
Location: arcticulation_tool/tools/smart_motion_tool.rb
Rule: TOOL003 (Tools And View Drawing)
Why it matters: Tools that implement onUserText should also opt in to the value control box so typed input is available consistently.
Conservative fix: Define enableVCB? and return true for tools that accept onUserText input.
- [Info/high] Long undo operation names detected
Location: project
Rule: UNDO006 (Operations)
Evidence: 9 occurrences; examples: arcticulation_tool/tools/core/joint_limits/dialog.rb:517 model.start_operation(āARCticulation Clear Instance Joint Settingsā, true); arcticulation_tool/tools/core/joint_limits/dialog.rb:539 model.start_operation(āARCticulation Clear Default Joint Settingsā, true); arcticulatā¦
Why it matters: Operation names appear in SketchUp undo UI and should be concise enough for users to scan.
Review note: Use short, user-facing operation names while keeping detailed context in code comments or logs.
- [Info/high] SketchUp extension signature metadata detected
Location: arcticulation_tool/arcticulation_tool.susig
Rule: SIG001 (Archive Packaging)
Evidence: .susig file present
Why it matters: A .susig file is signature metadata for a SketchUp extension package. This is useful package context, but Preflight does not validate the signature.
Review note: For code review coverage, scan the development source package before signing or encrypting.
- [Info/low] Serialized execute_script payloads need review
Location: arcticulation_tool/tools/core/diagnostics_panel.rb
Rule: HTML002 (HtmlDialog Safety)
Evidence: 6 occurrences; examples: arcticulation_tool/tools/core/diagnostics_panel.rb:128 dialog.execute_script(āarcDiagPanelEchoReply(#{json_for_script({ kind: āecho_replyā, received: data, ruby_time: Time.now.strftime(ā%H:%M:%Sā) })});ā); arcticulation_tool/tools/core/diagnostics_panel.rb:135 dialog.executeā¦
Why it matters: This file has execute_script calls with values that appear to be JSON-serialized into fixed JavaScript calls. This is lower risk than raw interpolation, but static review cannot prove every helper escapes safely.
Review note: Keep JavaScript receiver names fixed and extension-owned, and route every dynamic value through JSON.generate, to_json, or a reviewed JSON helper.
- [Info/low] Serialized execute_script payloads need review
Location: arcticulation_tool/tools/core/joint_limits/dialog.rb
Rule: HTML002 (HtmlDialog Safety)
Evidence: 1 occurrence; examples: arcticulation_tool/tools/core/joint_limits/dialog.rb:562 @dialog.execute_script(āarcSetRows(#{json(payload)});ā)
Why it matters: This file has execute_script calls with values that appear to be JSON-serialized into fixed JavaScript calls. This is lower risk than raw interpolation, but static review cannot prove every helper escapes safely.
Review note: Keep JavaScript receiver names fixed and extension-owned, and route every dynamic value through JSON.generate, to_json, or a reviewed JSON helper.
- [Info/low] Serialized execute_script payloads need review
Location: arcticulation_tool/tools/export_hub.rb
Rule: HTML002 (HtmlDialog Safety)
Evidence: 3 occurrences; examples: arcticulation_tool/tools/export_hub.rb:312 dialog.execute_script(āarcReceiveLibrary(#{JSON.generate(library_payload(model))});ā); arcticulation_tool/tools/export_hub.rb:318 dialog.execute_script(āarcStatus(#{JSON.generate(text.to_s)});ā); arcticulation_tool/tools/export_hubā¦
Why it matters: This file has execute_script calls with values that appear to be JSON-serialized into fixed JavaScript calls. This is lower risk than raw interpolation, but static review cannot prove every helper escapes safely.
Review note: Keep JavaScript receiver names fixed and extension-owned, and route every dynamic value through JSON.generate, to_json, or a reviewed JSON helper.
- [Info/low] Serialized execute_script payloads need review
Location: arcticulation_tool/tools/pose_presets/pose_crud.rb
Rule: HTML002 (HtmlDialog Safety)
Evidence: 1 occurrence; examples: arcticulation_tool/tools/pose_presets/pose_crud.rb:39 @dialog.execute_script(āwindow.arcPoseReceiveState && window.arcPoseReceiveState(#{js_json(payload)});ā)
Why it matters: This file has execute_script calls with values that appear to be JSON-serialized into fixed JavaScript calls. This is lower risk than raw interpolation, but static review cannot prove every helper escapes safely.
Review note: Keep JavaScript receiver names fixed and extension-owned, and route every dynamic value through JSON.generate, to_json, or a reviewed JSON helper.
- [Info/low] Serialized execute_script payloads need review
Location: arcticulation_tool/tools/pose_presets/quick_save.rb
Rule: HTML002 (HtmlDialog Safety)
Evidence: 1 occurrence; examples: arcticulation_tool/tools/pose_presets/quick_save.rb:38 dialog.execute_script(āwindow.arcQuickPoseStatus && window.arcQuickPoseStatus(#{js_json(status)});ā) rescue nil
Why it matters: This file has execute_script calls with values that appear to be JSON-serialized into fixed JavaScript calls. This is lower risk than raw interpolation, but static review cannot prove every helper escapes safely.
Review note: Keep JavaScript receiver names fixed and extension-owned, and route every dynamic value through JSON.generate, to_json, or a reviewed JSON helper.
## Checks Run
- Package structure and root loader discovery
- Selected extension folder paired with sibling root loader
- Root loader metadata and SketchupExtension registration
- Built-in static text, path, security, platform, and release hygiene checks
- Platform compatibility checks scoped to Windows + Mac
- Namespace wrapper and top-level Ruby hygiene
- Required Ruby stdlib require coverage
- Mac toolbar icon compatibility
## Not Reviewed / Could Not Verify
- The reviewed extension code was not loaded or executed.
- Live SketchUp behavior was not run.
- HtmlDialog developer console behavior was not inspected.
- Mac behavior was not tested.
- Final RBZ install, enable/disable, command launch, and model workflow testing were not proven.
- Documentation, support contact, dependency instructions, and listing/support links were not verified.
- Usefulness, uniqueness, duplicate-feature fit, and listing accuracy are manual submission self-checks and are not scored.
- Archive packaging was not scanned because an unpacked folder was selected.
- SketchUp signature metadata (.susig) was detected; this scanner does not validate the signature.
- External Ruby, Node, RuboCop, and RuboCop-SketchUp checks are not run in this first scaffold.
## Skipped Files
- arcticulation_tool/arcticulation_tool.susig: SketchUp signature metadata file skipped
- arcticulation_tool/icons/articulation_rotate_icon.png: unsupported file type
- arcticulation_tool/icons/axis_limits_icon.png: unsupported file type
- arcticulation_tool/icons/cursor_pick.pdf: unsupported file type
- arcticulation_tool/icons/cursor_pick.png: unsupported file type
- arcticulation_tool/icons/cursor_pick.svg: unsupported file type
- arcticulation_tool/icons/cursor_rotate.pdf: unsupported file type
- arcticulation_tool/icons/cursor_rotate.png: unsupported file type
- arcticulation_tool/icons/cursor_rotate.svg: unsupported file type
- arcticulation_tool/icons/cursor_slide.pdf: unsupported file type
- arcticulation_tool/icons/cursor_slide.png: unsupported file type
- arcticulation_tool/icons/cursor_slide.svg: unsupported file type
- arcticulation_tool/icons/export_hub_icon.png: unsupported file type
- arcticulation_tool/icons/pose_presets_lab_icon.png: unsupported file type