[GH-ISSUE #6584] [Bug] ADB package inspection stops counting permissions at a valid Unicode name #3973

Closed
opened 2026-10-31 00:45:43 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6584

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Process capture or runtime observation

Observed behavior

On current main, AdbProvider.execute({operation: "inspect_adb_package", input: {serial: "fixture-device", package: "com.example"}}) returned requested_permissions_count: 0 and coverage: "complete" when a fake adb supplied two requested permissions beginning with com.example.permission.ÉCRIRE. With one ASCII permission before that name and another after it, the provider returned 1 instead of 3, again with complete coverage. The all-ASCII control returned the correct count of 2.

These were executed source-provider probes with a local fake adb, not a real Android device, CLI invocation, or MCP session. Android format applicability is source-derived below.

Reproduction

From a source checkout with locked dependencies, run this minimal parser probe (executed with Node 24.22.1):

./node_modules/.bin/tsx --eval 'import {parseDumpsysPackageOutput} from "./src/adb/AdbShellOutput.ts"; const dump = "Packages:\n  Package [com.example] (abcdef):\n    pkg=Package{abcdef com.example}\n    versionCode=7 minSdk=24 targetSdk=34\n    versionName=1.0\n    requested permissions:\n      com.example.permission.ÉCRIRE\n      android.permission.CAMERA\n    install permissions:\n      android.permission.CAMERA: granted=true\n"; console.log(JSON.stringify({expected:2,actual:parseDumpsysPackageOutput(dump).requestedPermissions}));'

Observed:

{"expected":2,"actual":0}

A separate probe supplied the same dump through an executable fake adb, then called the real AdbProvider.execute operation above. Its version branch printed Android Debug Bridge version 1.0.41 and Version 36.0.0-fixture; its -s fixture-device shell dumpsys package com.example branch printed the fixture. It reproduced the wrong count and complete coverage. Each provider case ran once; no real client configuration was modified.

Expected behavior

Count every requested-permission row in the section, including valid non-ASCII names, and continue counting subsequent ASCII rows. If a row cannot be interpreted, keep the count uncertain or disclose partial coverage instead of reporting a complete count of zero or a prefix count.

The documented package projection includes permission count. Android 14's uses-permission parser reads a non-resource string, checks its length and applicability, and retains it without an ASCII identifier restriction. Its dumpsys producer prints each requested permission verbatim. This establishes the fixture format from source; an APK with this declaration was not installed.

Impact and scope

A requested permission outside REA's ASCII alphabet makes the normalized count omit that permission and every later row in the same section. The provider still reports complete coverage and emits no limitation identifying those omitted rows. This is an incorrect inventory count, not a claim about permission grants or a security finding.

Observed scope is the Linux source parser and real REA provider with simulated adb output. Real-device occurrence and frequency, CLI/MCP delivery, and other host platforms were not executed. A raw adb -s DEVICE shell dumpsys package PACKAGE inspection is a possible workaround; that workaround was not exercised against a device.

REA version

Executed current main 46111dd091f2ae01baab9eb119b53b9bd309a05b, whose package version is 6.7.0. This is not identified as a main-only defect: the latest published rea-agents-6.7.0 revision 27dc42d10249f0410904a75c0997842eb03b931c contains the same restrictive ASCII parsing mechanism. Release applicability is source-derived; the published package runtime was not run.

Runtime and platform

Node.js v24.22.1, locked checkout dependencies, Linux x86_64. Local fake adb only; no Android device, emulator, Apktool, JADX, or JEB process was used.

Target and artifact context

Reduced dumpsys package com.example text with a loaded parsed package, version metadata, and a requested-permissions section. All package and permission names are synthetic.

Interface

Other

Earliest failure stage

Transport or result projection

Relevant output or evidence

Executed real-provider results:

{"case":"ascii-control","expected":2,"actual":2,"coverage":"complete"}
{"case":"unicode-first","expected":2,"actual":0,"coverage":"complete"}
{"case":"unicode-middle","expected":3,"actual":1,"coverage":"complete"}

The provider limitations describe a fixed projection and unknown inventories when pkg=null, but do not disclose this truncation of an existing section.

The main parser accepts only [A-Za-z0-9._$-]+ permission names, then sets inPermissions = false on a nonmatching row. The provider projection uses the resulting numeric count and reports complete coverage when version metadata is present. The published-release parser uses an even narrower ASCII alphabet and has the same section-ending behavior.

  • Evidence provenance: observed source-parser and production-provider results with simulated tool output; Android input validity and released-code applicability are source-derived.
  • Local verification: reproduced before drafting.
  • Reproduction completeness: complete for the reduced provider boundary; real-device and public-adapter reproduction unavailable.

Typed outcome or recovery expected

For the two-row fixture, return requested_permissions_count: 2. If normalization cannot establish the count, report an unknown/partial inventory rather than a complete zero. Preserve later valid rows instead of ending the section on the first unsupported name.

Analysis or suspected cause

Source-derived: row recognition conflates the end of the indented requested-permissions section with failure of an ASCII name whitelist. A valid Unicode permission fails the whitelist, permanently clears inPermissions, and prevents subsequent rows from contributing to the count. The result carries a non-null count, so the provider's coverage condition does not detect the omission.

Additional context

Open and closed issue searches included "dumpsys" "unicode", "permission" "non-ASCII", "requested" "permissions" "count", "dumpsys" "permission", "permissions" "truncated", and permission-count/name title searches. No matching report was found. #4654 concerns an unavailable parsed package and an absent section; this report has a loaded parsed package and an existing section whose rows are lost. #5426 concerns the separate appId/userId field spelling.

NOT_ENOUGH_INFO: no real APK/device reproduction or last-known-good version was established. No provider runtime beyond the local fake-adb boundary was tested.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The executed provider returns a consequential but bounded wrong inventory count with complete coverage for an Android-source-compatible requested-permission name. One such row also erases later ASCII rows; no mutation or broader impact was observed.
  • Workaround status: unverified
  • Workaround basis: Inspecting the raw dumpsys section would avoid this parser, but no real-device workaround was executed. The reduced fixture retains all names; that does not establish a deployed-device workflow.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6584 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Process capture or runtime observation ### Observed behavior On current main, `AdbProvider.execute({operation: "inspect_adb_package", input: {serial: "fixture-device", package: "com.example"}})` returned `requested_permissions_count: 0` and `coverage: "complete"` when a fake adb supplied two requested permissions beginning with `com.example.permission.ÉCRIRE`. With one ASCII permission before that name and another after it, the provider returned 1 instead of 3, again with complete coverage. The all-ASCII control returned the correct count of 2. These were executed source-provider probes with a local fake adb, not a real Android device, CLI invocation, or MCP session. Android format applicability is source-derived below. ### Reproduction From a source checkout with locked dependencies, run this minimal parser probe (executed with Node 24.22.1): ```sh ./node_modules/.bin/tsx --eval 'import {parseDumpsysPackageOutput} from "./src/adb/AdbShellOutput.ts"; const dump = "Packages:\n Package [com.example] (abcdef):\n pkg=Package{abcdef com.example}\n versionCode=7 minSdk=24 targetSdk=34\n versionName=1.0\n requested permissions:\n com.example.permission.ÉCRIRE\n android.permission.CAMERA\n install permissions:\n android.permission.CAMERA: granted=true\n"; console.log(JSON.stringify({expected:2,actual:parseDumpsysPackageOutput(dump).requestedPermissions}));' ``` Observed: ```json {"expected":2,"actual":0} ``` A separate probe supplied the same dump through an executable fake adb, then called the real `AdbProvider.execute` operation above. Its version branch printed `Android Debug Bridge version 1.0.41` and `Version 36.0.0-fixture`; its `-s fixture-device shell dumpsys package com.example` branch printed the fixture. It reproduced the wrong count and complete coverage. Each provider case ran once; no real client configuration was modified. ### Expected behavior Count every requested-permission row in the section, including valid non-ASCII names, and continue counting subsequent ASCII rows. If a row cannot be interpreted, keep the count uncertain or disclose partial coverage instead of reporting a complete count of zero or a prefix count. The [documented package projection](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/docs/adb-device-analysis.md#L93) includes permission count. Android 14's [uses-permission parser](https://github.com/aosp-mirror/platform_frameworks_base/blob/android-14.0.0_r1/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java#L1258-L1394) reads a non-resource string, checks its length and applicability, and retains it without an ASCII identifier restriction. Its [dumpsys producer](https://github.com/aosp-mirror/platform_frameworks_base/blob/android-14.0.0_r1/services/core/java/com/android/server/pm/Settings.java#L4993-L5005) prints each requested permission verbatim. This establishes the fixture format from source; an APK with this declaration was not installed. ### Impact and scope A requested permission outside REA's ASCII alphabet makes the normalized count omit that permission and every later row in the same section. The provider still reports complete coverage and emits no limitation identifying those omitted rows. This is an incorrect inventory count, not a claim about permission grants or a security finding. Observed scope is the Linux source parser and real REA provider with simulated adb output. Real-device occurrence and frequency, CLI/MCP delivery, and other host platforms were not executed. A raw `adb -s DEVICE shell dumpsys package PACKAGE` inspection is a possible workaround; that workaround was not exercised against a device. ### REA version Executed current main `46111dd091f2ae01baab9eb119b53b9bd309a05b`, whose package version is 6.7.0. This is not identified as a main-only defect: the latest published `rea-agents-6.7.0` revision `27dc42d10249f0410904a75c0997842eb03b931c` contains the same restrictive ASCII parsing mechanism. Release applicability is source-derived; the published package runtime was not run. ### Runtime and platform Node.js v24.22.1, locked checkout dependencies, Linux x86_64. Local fake adb only; no Android device, emulator, Apktool, JADX, or JEB process was used. ### Target and artifact context Reduced `dumpsys package com.example` text with a loaded parsed package, version metadata, and a requested-permissions section. All package and permission names are synthetic. ### Interface Other ### Earliest failure stage Transport or result projection ### Relevant output or evidence Executed real-provider results: ```json {"case":"ascii-control","expected":2,"actual":2,"coverage":"complete"} {"case":"unicode-first","expected":2,"actual":0,"coverage":"complete"} {"case":"unicode-middle","expected":3,"actual":1,"coverage":"complete"} ``` The provider limitations describe a fixed projection and unknown inventories when `pkg=null`, but do not disclose this truncation of an existing section. The [main parser](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/adb/AdbShellOutput.ts#L318-L335) accepts only `[A-Za-z0-9._$-]+` permission names, then sets `inPermissions = false` on a nonmatching row. The [provider projection](https://github.com/morluto/rea/blob/46111dd091f2ae01baab9eb119b53b9bd309a05b/src/adb/AdbProvider.ts#L1556-L1582) uses the resulting numeric count and reports complete coverage when version metadata is present. The [published-release parser](https://github.com/morluto/rea/blob/27dc42d10249f0410904a75c0997842eb03b931c/src/adb/AdbShellOutput.ts#L295-L318) uses an even narrower ASCII alphabet and has the same section-ending behavior. - Evidence provenance: observed source-parser and production-provider results with simulated tool output; Android input validity and released-code applicability are source-derived. - Local verification: reproduced before drafting. - Reproduction completeness: complete for the reduced provider boundary; real-device and public-adapter reproduction unavailable. ### Typed outcome or recovery expected For the two-row fixture, return `requested_permissions_count: 2`. If normalization cannot establish the count, report an unknown/partial inventory rather than a complete zero. Preserve later valid rows instead of ending the section on the first unsupported name. ### Analysis or suspected cause Source-derived: row recognition conflates the end of the indented requested-permissions section with failure of an ASCII name whitelist. A valid Unicode permission fails the whitelist, permanently clears `inPermissions`, and prevents subsequent rows from contributing to the count. The result carries a non-null count, so the provider's coverage condition does not detect the omission. ### Additional context Open and closed issue searches included `"dumpsys" "unicode"`, `"permission" "non-ASCII"`, `"requested" "permissions" "count"`, `"dumpsys" "permission"`, `"permissions" "truncated"`, and permission-count/name title searches. No matching report was found. [#4654](https://github.com/morluto/rea/issues/4654) concerns an unavailable parsed package and an absent section; this report has a loaded parsed package and an existing section whose rows are lost. [#5426](https://github.com/morluto/rea/issues/5426) concerns the separate `appId`/`userId` field spelling. NOT_ENOUGH_INFO: no real APK/device reproduction or last-known-good version was established. No provider runtime beyond the local fake-adb boundary was tested. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The executed provider returns a consequential but bounded wrong inventory count with complete coverage for an Android-source-compatible requested-permission name. One such row also erases later ASCII rows; no mutation or broader impact was observed. - Workaround status: unverified - Workaround basis: Inspecting the raw dumpsys section would avoid this parser, but no real-device workaround was executed. The reduced fixture retains all names; that does not establish a deployed-device workflow.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3973
No description provided.