[GH-ISSUE #7534] [Bug] Package inspection reports a digit prefix as the exact version for an attached-letter token #4479

Open
opened 2026-10-31 00:50:09 +00:00 by bsakaguchi · 0 comments
Owner

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

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

With a fixture adb returning versionCode=45abc minSdk=24 targetSdk=34, this command returned version_code: "45" and coverage: "complete", with no numeric issues:

node scripts/rea.mjs inspect-adb-package fixture-device com.example.app --json

The reported version is the digit prefix of the supplied token. A valid versionCode=45 minSdk=24 targetSdk=34 response produced the same three result fields. All calls exited 0 with empty stderr. These are production CLI observations using a local executable selected by REA_ADB_PATH; no Android device or adb server was used.

Reproduction

  1. From the already built baseline checkout, put Node 24.22.1 on PATH. Run this inline probe. It creates an isolated home and XDG directories, supplies its own adb executable, repeats the attached-letter case twice, then runs a valid-token control. The temporary files are removed on completion.
python3 - <<'PY'
import json, os, pathlib, shutil, subprocess, tempfile
node = shutil.which('node')
with tempfile.TemporaryDirectory() as work:
    root = pathlib.Path(work)
    adb = root / 'adb'
    adb.write_text("""#!/bin/sh
if [ "$#" = 1 ] && [ "$1" = version ]; then
  printf 'Android Debug Bridge version 1.0.41\\nVersion 34.0.5-fixture\\n'
  exit 0
fi
if [ "$#" = 6 ] && [ "$1" = -s ] && [ "$2" = fixture-device ] && [ "$3" = shell ] && [ "$4" = dumpsys ] && [ "$5" = package ] && [ "$6" = com.example.app ]; then
  cat "$ADB_FIXTURE"
  exit 0
fi
exit 91
""")
    adb.chmod(0o755)
    env = {'PATH':str(pathlib.Path(node).parent)+os.pathsep+os.defpath,
           'REA_ADB_PATH':str(adb), 'ADB_FIXTURE':str(root/'package.txt')}
    for key in ['HOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME', 'XDG_STATE_HOME']:
        directory = root / key.lower()
        directory.mkdir()
        env[key] = str(directory)
    for value in ['45abc', '45abc', '45']:
        text = ('Packages:\n  Package [com.example.app] (abcdef):\n'
                '    userId=10123\n    pkg=Package{abcdef com.example.app}\n'
                '    versionCode='+value+' minSdk=24 targetSdk=34\n'
                '    versionName=1.0\n    requested permissions:\n'
                '      android.permission.INTERNET\n')
        (root/'package.txt').write_text(text)
        run = subprocess.run([node, 'scripts/rea.mjs', 'inspect-adb-package',
                              'fixture-device', 'com.example.app', '--json'],
                             env=env, capture_output=True, text=True)
        assert run.returncode == 0 and not run.stderr, (run.returncode, run.stdout, run.stderr)
        result = json.loads(run.stdout)['normalized_result']
        raw = subprocess.check_output([str(adb), '-s', 'fixture-device', 'shell',
                                       'dumpsys', 'package', 'com.example.app'], env=env, text=True)
        assert raw == text
        print(json.dumps({'input':value, 'exit':run.returncode,
                          **{key:result[key] for key in ['version_code', 'numeric_issues', 'coverage']}}))
PY
  1. Observe these exact relevant results:
{"input": "45abc", "exit": 0, "version_code": "45", "numeric_issues": {"sample": [], "total": 0}, "coverage": "complete"}
{"input": "45abc", "exit": 0, "version_code": "45", "numeric_issues": {"sample": [], "total": 0}, "coverage": "complete"}
{"input": "45", "exit": 0, "version_code": "45", "numeric_issues": {"sample": [], "total": 0}, "coverage": "complete"}

The attached-letter case failed twice in this reduced replay and twice in an earlier independent probe: four of four calls. The raw-output assertion succeeded for every call, confirming that the supplied token contained the attached letters.

Expected behavior

The package-inspection documentation and output schema promise the exact version code reported by dumpsys. An attached-letter token cannot establish the decimal version 45. The response should preserve uncertainty rather than promote its leading digits to an exact, completely observed version. For the current nullable decimal-string result, returning an unknown version with partial coverage would avoid the false observation; the particular diagnostic representation is a design choice.

Whitespace-separated properties following a valid decimal token remain valid. Signed values and values above JavaScript's safe-integer range must also retain their exact spelling.

Impact and scope

The demonstrated consequence is a wrong normalized version with a completeness claim. The malformed token and valid 45 token are indistinguishable in the returned version, diagnostics and coverage fields. This can mislead a caller relying on those fields; downstream version comparisons or acquisition decisions were not exercised.

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The public CLI produces a bounded incorrect version observation for synthetic malformed package output. No device mutation or wider failure was observed, and real-device prevalence is unknown.
  • Workaround status: available
  • Workaround basis: Read and retain the raw package response independently before relying on the normalized version. The probe performs that read through its selected fixture adb and verifies exact retention of the malformed token. Real-device use of the workaround was not tested.

REA version

Exact stdout from node scripts/rea.mjs --version:

6.8.0

Source baseline: 65f1c447344a423fa2785847dbcea1e9a9e2454a, confirmed with git rev-parse HEAD. The npm registry version query also returned 6.8.0; a separately installed release runtime was not executed.

Runtime and platform

Node.js v24.22.1; macOS 27.0.1 arm64. The fixture executable identifies itself as Android Debug Bridge 1.0.41, build 34.0.5-fixture. No installed platform-tools binary was invoked.

Target and artifact context

Synthetic package output for com.example.app with a loaded package, valid user ID, version name and one requested permission. The malformed token was supplied deliberately to test REA's observation boundary. No real device is known from this verification to emit that shape.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

The three JSON lines above came from the reduced production CLI replay. Its raw-output assertions establish the input text independently of REA's normalization. Additional executed controls retained 9007199254740993 and -4294967296 exactly as strings, with complete coverage and no numeric issues. Those controls distinguish this failure from the older large-number precision defect.

Source checks at the baseline:

  • Expected contract: docs/adb-device-analysis.md:139-146 says the version remains exact source text. src/domain/adb/adbDeviceAnalysis.ts:629-634 constrains it to a nullable signed-decimal string and describes exact dumpsys spelling. AGENTS.md, Architecture and Cleanup, requires source values and uncertainty to survive normalization.
  • Reachability: src/cli/adbCommands.ts:133-141 routes the executed command to the package-inspection operation.
  • Failure boundary: src/adb/AdbShellOutput.ts:412-414 admits a leading signed digit run without requiring the version token to end. The built runtime contains the same logic at dist/adb/AdbShellOutput.js:311-314.
  • Projection: src/adb/AdbProvider.ts:1575-1596 returns that admitted value and can mark coverage complete when the package and version-name information are present.
  • Diagnostic scope: src/domain/adb/adbDeviceAnalysis.ts:548-558 currently limits package numeric issues to user_id. The empty diagnostic output is observed context; this report does not assume an existing version-code diagnostic shape.

Analysis or suspected cause

Source-derived explanation: the version parser removes attached nondecimal text before the decimal-string result schema sees the value. The resulting prefix satisfies the schema, so the projection cannot distinguish it from a fully reported version. A token-boundary check would distinguish attached letters from whitespace-separated properties; handling uncertainty after rejection must also preserve the ordinary, large and negative controls.

Additional context

The open and closed issue and PR searches found related work with different restoration checks:

  • Issue #7409 and open PR #7470 concern attached text in userId/appId. The inspected PR diff changes only that ID branch and its tests, leaving the version-code admission unchanged.
  • Closed issue #3368 and merged PR #3485 concern numeric precision and negative version codes. Both corresponding controls passed here; this report does not claim their original failure has regressed.
  • Closed issue #4654, #5426 and #6584 concern permission availability, the appId spelling and permission counting respectively.

Searches used both issue-list and issue-search APIs, plus all-state PR searches, with terms including versionCode, version_code, malformed, prefix, attached and package numeric declarations. MCP delivery, real-device prevalence and a last-known-good version for attached version text remain untested.

Originally created by @coygeek on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7534 ### 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 With a fixture adb returning `versionCode=45abc minSdk=24 targetSdk=34`, this command returned `version_code: "45"` and `coverage: "complete"`, with no numeric issues: ```sh node scripts/rea.mjs inspect-adb-package fixture-device com.example.app --json ``` The reported version is the digit prefix of the supplied token. A valid `versionCode=45 minSdk=24 targetSdk=34` response produced the same three result fields. All calls exited 0 with empty stderr. These are production CLI observations using a local executable selected by `REA_ADB_PATH`; no Android device or adb server was used. ### Reproduction 1. From the already built baseline checkout, put Node 24.22.1 on PATH. Run this inline probe. It creates an isolated home and XDG directories, supplies its own adb executable, repeats the attached-letter case twice, then runs a valid-token control. The temporary files are removed on completion. ```sh python3 - <<'PY' import json, os, pathlib, shutil, subprocess, tempfile node = shutil.which('node') with tempfile.TemporaryDirectory() as work: root = pathlib.Path(work) adb = root / 'adb' adb.write_text("""#!/bin/sh if [ "$#" = 1 ] && [ "$1" = version ]; then printf 'Android Debug Bridge version 1.0.41\\nVersion 34.0.5-fixture\\n' exit 0 fi if [ "$#" = 6 ] && [ "$1" = -s ] && [ "$2" = fixture-device ] && [ "$3" = shell ] && [ "$4" = dumpsys ] && [ "$5" = package ] && [ "$6" = com.example.app ]; then cat "$ADB_FIXTURE" exit 0 fi exit 91 """) adb.chmod(0o755) env = {'PATH':str(pathlib.Path(node).parent)+os.pathsep+os.defpath, 'REA_ADB_PATH':str(adb), 'ADB_FIXTURE':str(root/'package.txt')} for key in ['HOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME', 'XDG_STATE_HOME']: directory = root / key.lower() directory.mkdir() env[key] = str(directory) for value in ['45abc', '45abc', '45']: text = ('Packages:\n Package [com.example.app] (abcdef):\n' ' userId=10123\n pkg=Package{abcdef com.example.app}\n' ' versionCode='+value+' minSdk=24 targetSdk=34\n' ' versionName=1.0\n requested permissions:\n' ' android.permission.INTERNET\n') (root/'package.txt').write_text(text) run = subprocess.run([node, 'scripts/rea.mjs', 'inspect-adb-package', 'fixture-device', 'com.example.app', '--json'], env=env, capture_output=True, text=True) assert run.returncode == 0 and not run.stderr, (run.returncode, run.stdout, run.stderr) result = json.loads(run.stdout)['normalized_result'] raw = subprocess.check_output([str(adb), '-s', 'fixture-device', 'shell', 'dumpsys', 'package', 'com.example.app'], env=env, text=True) assert raw == text print(json.dumps({'input':value, 'exit':run.returncode, **{key:result[key] for key in ['version_code', 'numeric_issues', 'coverage']}})) PY ``` 2. Observe these exact relevant results: ```json {"input": "45abc", "exit": 0, "version_code": "45", "numeric_issues": {"sample": [], "total": 0}, "coverage": "complete"} {"input": "45abc", "exit": 0, "version_code": "45", "numeric_issues": {"sample": [], "total": 0}, "coverage": "complete"} {"input": "45", "exit": 0, "version_code": "45", "numeric_issues": {"sample": [], "total": 0}, "coverage": "complete"} ``` The attached-letter case failed twice in this reduced replay and twice in an earlier independent probe: four of four calls. The raw-output assertion succeeded for every call, confirming that the supplied token contained the attached letters. ### Expected behavior The package-inspection documentation and output schema promise the exact version code reported by dumpsys. An attached-letter token cannot establish the decimal version `45`. The response should preserve uncertainty rather than promote its leading digits to an exact, completely observed version. For the current nullable decimal-string result, returning an unknown version with partial coverage would avoid the false observation; the particular diagnostic representation is a design choice. Whitespace-separated properties following a valid decimal token remain valid. Signed values and values above JavaScript's safe-integer range must also retain their exact spelling. ### Impact and scope The demonstrated consequence is a wrong normalized version with a completeness claim. The malformed token and valid `45` token are indistinguishable in the returned version, diagnostics and coverage fields. This can mislead a caller relying on those fields; downstream version comparisons or acquisition decisions were not exercised. - Impact level: P2 - Assessment status: supported - Impact basis: The public CLI produces a bounded incorrect version observation for synthetic malformed package output. No device mutation or wider failure was observed, and real-device prevalence is unknown. - Workaround status: available - Workaround basis: Read and retain the raw package response independently before relying on the normalized version. The probe performs that read through its selected fixture adb and verifies exact retention of the malformed token. Real-device use of the workaround was not tested. ### REA version Exact stdout from `node scripts/rea.mjs --version`: ```text 6.8.0 ``` Source baseline: `65f1c447344a423fa2785847dbcea1e9a9e2454a`, confirmed with `git rev-parse HEAD`. The npm registry version query also returned 6.8.0; a separately installed release runtime was not executed. ### Runtime and platform Node.js v24.22.1; macOS 27.0.1 arm64. The fixture executable identifies itself as Android Debug Bridge 1.0.41, build 34.0.5-fixture. No installed platform-tools binary was invoked. ### Target and artifact context Synthetic package output for `com.example.app` with a loaded package, valid user ID, version name and one requested permission. The malformed token was supplied deliberately to test REA's observation boundary. No real device is known from this verification to emit that shape. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence The three JSON lines above came from the reduced production CLI replay. Its raw-output assertions establish the input text independently of REA's normalization. Additional executed controls retained `9007199254740993` and `-4294967296` exactly as strings, with complete coverage and no numeric issues. Those controls distinguish this failure from the older large-number precision defect. Source checks at the baseline: - Expected contract: `docs/adb-device-analysis.md:139-146` says the version remains exact source text. `src/domain/adb/adbDeviceAnalysis.ts:629-634` constrains it to a nullable signed-decimal string and describes exact dumpsys spelling. `AGENTS.md`, Architecture and Cleanup, requires source values and uncertainty to survive normalization. - Reachability: `src/cli/adbCommands.ts:133-141` routes the executed command to the package-inspection operation. - Failure boundary: `src/adb/AdbShellOutput.ts:412-414` admits a leading signed digit run without requiring the version token to end. The built runtime contains the same logic at `dist/adb/AdbShellOutput.js:311-314`. - Projection: `src/adb/AdbProvider.ts:1575-1596` returns that admitted value and can mark coverage complete when the package and version-name information are present. - Diagnostic scope: `src/domain/adb/adbDeviceAnalysis.ts:548-558` currently limits package numeric issues to `user_id`. The empty diagnostic output is observed context; this report does not assume an existing version-code diagnostic shape. ### Analysis or suspected cause Source-derived explanation: the version parser removes attached nondecimal text before the decimal-string result schema sees the value. The resulting prefix satisfies the schema, so the projection cannot distinguish it from a fully reported version. A token-boundary check would distinguish attached letters from whitespace-separated properties; handling uncertainty after rejection must also preserve the ordinary, large and negative controls. ### Additional context The open and closed issue and PR searches found related work with different restoration checks: - [Issue #7409](https://github.com/morluto/rea/issues/7409) and [open PR #7470](https://github.com/morluto/rea/pull/7470) concern attached text in `userId`/`appId`. The inspected PR diff changes only that ID branch and its tests, leaving the version-code admission unchanged. - [Closed issue #3368](https://github.com/morluto/rea/issues/3368) and [merged PR #3485](https://github.com/morluto/rea/pull/3485) concern numeric precision and negative version codes. Both corresponding controls passed here; this report does not claim their original failure has regressed. - [Closed issue #4654](https://github.com/morluto/rea/issues/4654), [#5426](https://github.com/morluto/rea/issues/5426) and [#6584](https://github.com/morluto/rea/issues/6584) concern permission availability, the appId spelling and permission counting respectively. Searches used both issue-list and issue-search APIs, plus all-state PR searches, with terms including versionCode, version_code, malformed, prefix, attached and package numeric declarations. MCP delivery, real-device prevalence and a last-known-good version for attached version text remain untested.
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#4479
No description provided.