Skip to content

Confirm EXECUTE_USER_CMD execution; retarget exec_cmd to the OEM-default name - #6

Merged
widgetii merged 2 commits into
masterfrom
exec-confirmed
Sep 22, 2026
Merged

widgetii merged 2 commits into
masterfrom
exec-confirmed

Conversation

@widgetii

Copy link
Copy Markdown
Member

Closes the one open question from #5: what makes an uploaded EXECUTE_USER_CMD actually execute.

How it was resolved

  • Captured AjDevTools' file-upload (previous PR), then read the device's own binaries: comm_server saves the upload to /tmp/upfile_*.dat and routes it by the FilePath basename; mainctrl's get_user_cmd_from_xml runs EXECUTE_USER_CMD only for OEM-default config names (defaultconfig.xml, config.default.xml, default_2_priority.xml) copied into /mnt/nand/cust/. An arbitrary basename is only stored — which is exactly why the earlier uploads didn't run.
  • Verified live on MTF45-4G_AF: uploading <CMD DATA="killall comm_server"/> under defaultconfig.xml dropped the control connection mid-upload (the daemon was actually killed, then respawned by procman). Camera stayed healthy (ONVIF config intact), and I removed the persisted OEM-default files afterward.

Changes

  • exec_cmd(*cmds, remote_name="defaultconfig.xml", confirm=True) now targets the executing name and drops the "unverified" caveat — execution is confirmed.
  • Documents the two real side effects: the file persists as the OEM-default (re-runs on factory reset — the vendor ptzClear.xml behaviour; self-clean with a trailing rm -f /mnt/nand/cust/<name>), and a command that stops comm_server drops the connection as it runs (expected).
  • docs/devices.md updated. 57 tests green.

Note: I did this the safe way — a targeted test using the exact names the device's own code recognises (not blind file-type brute-forcing), with the self-healing killall as the observable, and cleaned up after.

…ault name

Captured AjDevTools' file-upload, then traced comm_server/mainctrl: an uploaded
file is routed by its FilePath BASENAME. OEM-default config names
(defaultconfig.xml / config.default.xml / default_2_priority.xml) are copied into
/mnt/nand/cust/ and processed by get_user_cmd_from_xml, which RUNS the embedded
<CMD DATA=...>. An arbitrary basename is only stored (why earlier uploads didn't
execute).

Verified live on MTF45-4G_AF: uploading <CMD DATA='killall comm_server'/> under
defaultconfig.xml dropped the control connection mid-upload (daemon actually
killed, procman respawned it); camera stayed healthy (ONVIF config intact), and I
cleaned up the persisted OEM-default files.

exec_cmd now defaults remote_name='defaultconfig.xml' (executes), documents the
persistence side effect and self-cleaning, and drops the 'unverified' caveat.
57 tests green. docs/devices.md updated.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Execute user commands via OEM-default config names

🐞 Bug fix ✨ Enhancement 📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Routes EXECUTE_USER_CMD uploads through a recognized OEM-default basename for confirmed execution.
• Preserves confirmation while documenting persistence, factory-reset reruns, and expected
 connection drops.
• Records live-device validation and the comm_server/mainctrl processing path.
Diagram

graph TD
  Caller["API Caller"] --> Client["exec_cmd"] --> Comm["comm_server"] --> Gate{"OEM basename?"}
  Gate -- "Yes" --> Cust[("OEM Config")] --> Main["mainctrl"] --> Shell["Shell Commands"]
  Gate -- "No" --> Stored["Stored Only"]
  subgraph Legend
    direction LR
    _component["Component"] ~~~ _decision{"Decision"} ~~~ _storage[("Storage")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Enforce an OEM-name allowlist
  • ➕ Prevents callers from silently selecting a basename that only stores the payload.
  • ➕ Makes exec_cmd's execution contract explicit and safer.
  • ➕ Rejects unexpected paths before sending hazardous content.
  • ➖ Limits experimentation with additional firmware-specific OEM names.
  • ➖ Could require an explicit escape hatch for newly discovered device variants.

Recommendation: Keep the confirmed OEM-default upload mechanism because it follows the device's verified native execution path and avoids unsafe protocol brute-forcing. Consider validating remote_name against the three recognized basenames, with an explicit advanced override if firmware research requires other names; otherwise exec_cmd may report upload success without executing anything.

Files changed (2) +48 / -34

Bug fix (1) +27 / -23
comm.pyRetarget exec_cmd to a confirmed executing basename +27/-23

Retarget exec_cmd to a confirmed executing basename

• Changes exec_cmd to upload as defaultconfig.xml with file type 0, ensuring the payload enters the verified OEM-default execution path. Renames remote_path to remote_name, removes the unverified warning, and documents persistence, factory-reset reruns, self-cleanup, and expected connection loss when comm_server stops.

anjoy/comm.py

Documentation (1) +21 / -11
devices.mdDocument verified EXECUTE_USER_CMD execution behavior +21/-11

Document verified EXECUTE_USER_CMD execution behavior

• Explains basename-based upload routing, the recognized OEM-default filenames, and the comm_server/mainctrl execution flow. Records live MTF45-4G_AF verification and warns about persistent commands and connection drops.

docs/devices.md

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 22, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Custom command uploads never execute ✓ Resolved 🐞 Bug ≡ Correctness
Description
exec_cmd forwards remote_name without checking that its basename is one of the three names the
firmware executes. When a caller supplies any other name, upload_file can return its normal
success response after merely storing the payload, so none of the requested commands run.
Code

anjoy/comm.py[310]

+        return self.upload_file(content, remote_name, file_type=0, confirm=True)
Evidence
The method promises to run commands but passes the caller-controlled name directly to the upload
transport. Both the method documentation and device documentation establish that only three
basenames execute and that arbitrary basenames are merely stored, while upload_file treats a
successful transfer as success regardless of later execution.

anjoy/comm.py[282-310]
anjoy/comm.py[227-260]
docs/devices.md[84-92]
tests/test_comm.py[255-266]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`exec_cmd` accepts arbitrary remote names even though only three recognized basenames cause the device to execute the payload; other names can return upload success after only storing it.
## Fix Focus Areas
- anjoy/comm.py[282-310]
- tests/test_comm.py[255-266]
## Recommended Fix
Validate `remote_name` before uploading and raise `AnjoyError` unless its basename is one of `defaultconfig.xml`, `config.default.xml`, or `default_2_priority.xml`. Add tests covering all recognized names and rejection of an arbitrary basename.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Overview calls shell support unfinished ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
README.md still says wiring EXECUTE_USER_CMD is a follow-up even though exec_cmd now executes
it. Readers relying on the project overview are told the newly confirmed capability is unavailable
and may miss the public API.
Code

anjoy/comm.py[284]

+        """Run shell *commands* on the camera via ``EXECUTE_USER_CMD``.
Evidence
The overview explicitly says integration remains a follow-up, while the changed method now claims
and implements confirmed command execution and the device documentation describes it as available.

README.md[20-25]
anjoy/comm.py[282-310]
docs/devices.md[84-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The project overview still describes `EXECUTE_USER_CMD` integration as future work, contradicting the newly confirmed implementation and detailed device documentation.
## Fix Focus Areas
- README.md[20-25]
- anjoy/comm.py[282-310]
- docs/devices.md[84-104]
## Recommended Fix
Replace the follow-up statement in the README with a concise description of `exec_cmd`, its `confirm=True` guard, and a link to the persistence and connection-loss details in `docs/devices.md`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread anjoy/comm.py
Comment thread anjoy/comm.py
- exec_cmd validates remote_name against EXEC_TRIGGER_NAMES (the OEM-default
  basenames the device actually executes); a non-executing name now raises
  ValueError instead of silently storing commands that never run.
- README: drop the stale 'EXECUTE_USER_CMD wiring is a follow-up' note — it's
  implemented and execution-confirmed.
- Test for the remote_name guard. 58 green.
@widgetii
widgetii merged commit 706b1f3 into master Sep 22, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant