# REPRO-2026-00255: JAIOTlink C492A-W6 Wi‑Fi IP camera firmware accepts default admin credentials (blank password) over HTTP Basic auth, enabling network‑adjacent attackers to access snapshots and privileged APIs. ## Summary Status: published Severity: critical Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00255 CVE: CVE-2026-58453 ## Package Name: jingwenyi/SmartCamera (Anyka N1 Ecosystem: firmware Affected: 4.8.30.57701411 Fixed: Unknown ## Root Cause ## Summary CVE-2026-58453 is a hard-coded/default credential vulnerability in the JAIOTlink C492A-W6 Wi-Fi IP camera HTTP service. The camera-family Anyka/N1 `anyka_ipc` HTTP service protects privileged NetSDK API endpoints with HTTP Basic authentication, but the default/factory account path provisions `admin` with an empty password. A network-adjacent attacker who can reach the camera HTTP service can send `Authorization: Basic YWRtaW46` (`admin:`) and receive protected resources such as `/NetSDK/System/deviceInfo` and snapshot endpoints. ## Impact - **Package/component affected:** JAIOTlink C492A-W6 Wi-Fi IP camera firmware, `anyka_ipc` / Anyka N1 HTTP NetSDK service. - **Affected versions:** Reported vulnerable firmware `4.8.30.57701411`; reproduced against the real Anyka N1/`anyka_ipc` HTTP service library code used by this camera family (`libNkN1API.a`, version string `1.5.7.38`) and the disclosed device behavior. - **Risk level and consequences:** Critical. A network-adjacent attacker can authenticate using predictable credentials and access protected camera APIs. The demonstrated impact is authorization bypass to protected NetSDK device information; the same authenticated surface includes snapshots, video/configuration endpoints, and factory APIs described in the disclosure. ## Impact Parity - **Disclosed/claimed maximum impact:** Authorization bypass/default credential access to snapshots, video streams, configuration, and factory APIs via HTTP Basic auth using `admin` with an empty password. - **Reproduced impact from this run:** Runtime API access through a real TCP HTTP boundary into the original Anyka N1/`anyka_ipc` NetSDK service code. The vulnerable service returned HTTP `200 OK` and protected `/NetSDK/System/deviceInfo` JSON for `admin:` while no-auth and `admin:wrong` returned HTTP `401 Unauthorized`. A fixed/remediated comparison using a non-empty `admin` password rejected `admin:` and accepted only the configured non-empty password. - **Parity:** `full` for the claimed API authentication bypass behavior on the NetSDK HTTP surface. - **Not demonstrated:** This run did not use a physical JAIOTlink C492A-W6 camera or stream real camera video. Snapshot path reachability was exercised through the same service boundary with a minimal callback-provided JPEG, while the primary protected-resource oracle is `/NetSDK/System/deviceInfo` from the real NetSDK HTTP handler. ## Root Cause The vulnerable account is created by the original Anyka N1 user-loading path. In `source/anyka_ipc/cloud/n1/src/n1_init.c`, `n1_usr_load()` opens `N1_USR_FILE_PATH` (`/etc/jffs2/usr.conf`). If the user file cannot be opened, which is the factory/default-user case, it calls: ```c NK_N1Device_AddUser("admin", "", 0); ``` The same fallback is also used if allocation fails while loading the user file. The NetSDK HTTP handler in `libNkN1API.a` contains the Basic-auth and NetSDK route code (`Authorization`, `Basic realm="nkHTTP"`, `/NetSDK/System/deviceInfo`, `/snapshot.jpg`, `N1_Device_HandleNetSDKHTTP`, `N1_Device_HandleNetSDK`). The handler decodes the Basic credential, checks the username with `NK_N1Device_HasUser()`, then compares the supplied password to the stored password. Because the stored default password is the empty string, the Basic credential `admin:` is accepted and protected routes are served. No upstream fix commit is known from the ticket. The reproduction includes a negative control representing the expected fixed behavior: provision `admin` with a non-empty password. In that remediated configuration, `admin:` fails with HTTP `401 Unauthorized`, while `admin:fixed-secret` succeeds. ## Reproduction Steps 1. Run `bundle/repro/reproduction_steps.sh`. 2. The script: - Reuses/clones the disclosure repository at the durable cache path. - Reuses/clones the Anyka SmartCamera source at commit `a5bece938ff0dc019ead3d62fa6adefbc8c497fe`. - Builds an ARM launcher that links directly against the original `libNkN1API.a`, `libNkUtils.a`, and `libbase.a` Anyka N1 service libraries. - Runs the ARM service under `qemu-arm`, exposing a localhost TCP HTTP listener. - Performs two vulnerable attempts where the real service is provisioned with `admin` and an empty password. - Performs two fixed/negative-control attempts where the service is provisioned with `admin` and a non-empty password. 3. Expected evidence: - Vulnerable attempts: no-auth and `admin:wrong` get `401`, but `admin:` gets `200` and protected NetSDK JSON. - Fixed attempts: no-auth, `admin:wrong`, and `admin:` get `401`; `admin:fixed-secret` gets `200`. ## Evidence Primary logs and artifacts: - `bundle/logs/reproduction_steps.log` — full build/run/test transcript. - `bundle/repro/runtime_manifest.json` — runtime evidence manifest showing `entrypoint_kind="api_remote"`, `service_started=true`, `healthcheck_passed=true`, and `target_path_reached=true`. - `bundle/repro/source_identity.txt` — source and library identity, including the `n1_usr_load()` fallback and `libNkN1API.a` NetSDK/auth strings. - `bundle/logs/vulnerable_attempt1_admin_empty_netsdk.headers.txt` — vulnerable `admin:` response headers: - `HTTP/1.1 200 OK` - `Server: nkHTTP / 1.4` - `Content-Type: text/json` - `bundle/logs/vulnerable_attempt1_admin_empty_netsdk.body` — protected NetSDK JSON returned to `admin:`: - `"sdkVersion":"1.5.7.38"` - `"firmwareVersion":"1.5.7.38"` - `"macAddress":"00:00:00:00:00:00"` - `bundle/logs/fixed_attempt1_admin_empty_netsdk.body` — fixed comparison rejects `admin:`: - `"statusMessage":"Unauthorized"` - `bundle/logs/fixed_attempt1_configured_password_netsdk.body` — fixed comparison remains healthy and returns protected NetSDK JSON only with the configured non-empty password. Key excerpt from the successful second verification run: ```text vulnerable attempt 1 status summary: noauth=401 wrong=401 admin_empty=200 expected_admin_empty=200 vulnerable attempt 2 status summary: noauth=401 wrong=401 admin_empty=200 expected_admin_empty=200 fixed attempt 1 status summary: noauth=401 wrong=401 admin_empty=401 expected_admin_empty=401 fixed attempt 1 configured-password status=200 fixed attempt 2 status summary: noauth=401 wrong=401 admin_empty=401 expected_admin_empty=401 fixed attempt 2 configured-password status=200 ``` Environment details captured: - HTTP entrypoint: localhost TCP listener started by the ARM Anyka N1 service under `qemu-arm`. - Service library: `libNkN1API.a` SHA-256 `ecf4d713a16633e87d76cd178e509c70695d37bc6eb2947be8b3df5a21795aea`. - Anyka source commit: `a5bece938ff0dc019ead3d62fa6adefbc8c497fe`. - Disclosure repository commit: `2554725f808a34e23a938b09b0f6db86c2adc01d`. ## Recommendations / Next Steps - Do not ship a blank or universal default administrator password. - Require a per-device random credential or setup-time password before exposing HTTP APIs. - Remove reusable default credentials from companion apps. - If a fallback account must exist for manufacturing, disable it in production firmware or gate it behind a physical setup process. - Add regression tests that start the HTTP NetSDK service and assert that `Authorization: Basic YWRtaW46` is rejected unless a user explicitly configured an empty password (which should itself be prohibited). - Restrict sensitive factory APIs from normal production mode and segment network access to camera management services. ## Additional Notes The reproduction script was run twice consecutively and passed both times. It uses a faithful runtime execution of the real Anyka N1/`anyka_ipc` HTTP/NetSDK service code rather than a reimplemented handler. The limitation is that no physical JAIOTlink C492A-W6 device was attached in the sandbox; therefore the proof uses the original service library path and a controlled launcher to exercise the real authentication and NetSDK route logic over TCP. ## Reproduction Details Reproduced: 2026-07-06T09:05:25.373Z Duration: 1782 seconds Tool calls: 287 Turns: Unknown Handoffs: 3 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00255 pruva-verify CVE-2026-58453 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00255&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00255/artifacts/bundle/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-58453 - Source: https://nvd.nist.gov/vuln/detail/CVE-2026-58453 ## Artifacts - bundle/repro/reproduction_steps.sh (reproduction_script, 15509 bytes) - bundle/repro/rca_report.md (analysis, 7903 bytes) - bundle/vuln_variant/reproduction_steps.sh (reproduction_script, 17142 bytes) - bundle/vuln_variant/rca_report.md (analysis, 10593 bytes) - bundle/artifact_promotion_manifest.json (other, 29830 bytes) - bundle/vuln_variant/root_cause_equivalence.json (other, 1852 bytes) - bundle/repro/app_default_credentials.txt (other, 460 bytes) - bundle/repro/runtime_manifest.json (other, 4008 bytes) - bundle/logs/reproduction_steps.log (log, 5170 bytes) - bundle/repro/validation_verdict.json (other, 730 bytes) - bundle/repro/source_identity.txt (other, 2807 bytes) - bundle/repro/02-default-http-credentials.md (documentation, 3867 bytes) - bundle/repro/harness_sha256.txt (other, 177 bytes) - bundle/logs/vulnerable_service_attempt1.log (log, 1929 bytes) - bundle/logs/vulnerable_attempt1_health.headers.txt (other, 181 bytes) - bundle/logs/vulnerable_attempt1_health.body (other, 130 bytes) - bundle/logs/vulnerable_attempt1_health.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt1_noauth_netsdk.headers.txt (other, 181 bytes) - bundle/logs/vulnerable_attempt1_noauth_netsdk.body (other, 130 bytes) - bundle/logs/vulnerable_attempt1_noauth_netsdk.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt1_wrong_netsdk.headers.txt (other, 181 bytes) - bundle/logs/vulnerable_attempt1_wrong_netsdk.body (other, 130 bytes) - bundle/logs/vulnerable_attempt1_wrong_netsdk.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt1_admin_empty_netsdk.headers.txt (other, 131 bytes) - bundle/logs/vulnerable_attempt1_admin_empty_netsdk.body (other, 251 bytes) - bundle/logs/vulnerable_attempt1_admin_empty_netsdk.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt1_admin_empty_snapshot.headers.txt (other, 119 bytes) - bundle/logs/vulnerable_attempt1_admin_empty_snapshot.body (other, 22 bytes) - bundle/logs/vulnerable_attempt1_admin_empty_snapshot.curl.log (log, 0 bytes) - bundle/logs/vulnerable_service_attempt2.log (log, 1929 bytes) - bundle/logs/vulnerable_attempt2_health.headers.txt (other, 181 bytes) - bundle/logs/vulnerable_attempt2_health.body (other, 130 bytes) - bundle/logs/vulnerable_attempt2_health.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt2_noauth_netsdk.headers.txt (other, 181 bytes) - bundle/logs/vulnerable_attempt2_noauth_netsdk.body (other, 130 bytes) - bundle/logs/vulnerable_attempt2_noauth_netsdk.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt2_wrong_netsdk.headers.txt (other, 181 bytes) - bundle/logs/vulnerable_attempt2_wrong_netsdk.body (other, 130 bytes) - bundle/logs/vulnerable_attempt2_wrong_netsdk.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt2_admin_empty_netsdk.headers.txt (other, 131 bytes) - bundle/logs/vulnerable_attempt2_admin_empty_netsdk.body (other, 251 bytes) - bundle/logs/vulnerable_attempt2_admin_empty_netsdk.curl.log (log, 0 bytes) - bundle/logs/vulnerable_attempt2_admin_empty_snapshot.headers.txt (other, 119 bytes) - bundle/logs/vulnerable_attempt2_admin_empty_snapshot.body (other, 22 bytes) - bundle/logs/vulnerable_attempt2_admin_empty_snapshot.curl.log (log, 0 bytes) - bundle/logs/fixed_service_attempt1.log (log, 1932 bytes) - bundle/logs/fixed_attempt1_health.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt1_health.body (other, 130 bytes) - bundle/logs/fixed_attempt1_health.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt1_noauth_netsdk.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt1_noauth_netsdk.body (other, 130 bytes) - bundle/logs/fixed_attempt1_noauth_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt1_wrong_netsdk.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt1_wrong_netsdk.body (other, 130 bytes) - bundle/logs/fixed_attempt1_wrong_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt1_admin_empty_netsdk.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt1_admin_empty_netsdk.body (other, 130 bytes) - bundle/logs/fixed_attempt1_admin_empty_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt1_configured_password_netsdk.headers.txt (other, 131 bytes) - bundle/logs/fixed_attempt1_configured_password_netsdk.body (other, 251 bytes) - bundle/logs/fixed_attempt1_configured_password_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_service_attempt2.log (log, 1932 bytes) - bundle/logs/fixed_attempt2_health.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt2_health.body (other, 130 bytes) - bundle/logs/fixed_attempt2_health.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt2_noauth_netsdk.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt2_noauth_netsdk.body (other, 130 bytes) - bundle/logs/fixed_attempt2_noauth_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt2_wrong_netsdk.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt2_wrong_netsdk.body (other, 130 bytes) - bundle/logs/fixed_attempt2_wrong_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt2_admin_empty_netsdk.headers.txt (other, 181 bytes) - bundle/logs/fixed_attempt2_admin_empty_netsdk.body (other, 130 bytes) - bundle/logs/fixed_attempt2_admin_empty_netsdk.curl.log (log, 0 bytes) - bundle/logs/fixed_attempt2_configured_password_netsdk.headers.txt (other, 131 bytes) - bundle/logs/fixed_attempt2_configured_password_netsdk.body (other, 251 bytes) - bundle/logs/fixed_attempt2_configured_password_netsdk.curl.log (log, 0 bytes) - bundle/logs/vuln_variant/reproduction_steps.log (log, 2769 bytes) - bundle/vuln_variant/candidate_results.jsonl (other, 5836 bytes) - bundle/vuln_variant/validation_verdict.json (other, 3195 bytes) - bundle/vuln_variant/variant_manifest.json (other, 3797 bytes) - bundle/vuln_variant/patch_analysis.md (documentation, 7170 bytes) - bundle/vuln_variant/source_identity.json (other, 1465 bytes) - bundle/vuln_variant/runtime_manifest.json (other, 7316 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00255 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00255/artifacts/bundle/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00255 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev