Skip to content

feat: scanner protocol-less urls#1498

Open
rufusutt wants to merge 3 commits into
sysadminsmedia:mainfrom
rufusutt:feat/scanner-protocol-less-urls
Open

feat: scanner protocol-less urls#1498
rufusutt wants to merge 3 commits into
sysadminsmedia:mainfrom
rufusutt:feat/scanner-protocol-less-urls

Conversation

@rufusutt

Copy link
Copy Markdown

What type of PR is this?

  • feature

What this PR does / why we need it:

Lets the scanner read protocol-less URLs like example.com/a/1.
Dropping https:// and using uppercase characters fits more data into the smallest Data Matrix / QR codes (C40 mode), so users can pre-print tiny asset stickers.

parseScanResult (new, in composables/utils.ts):

  • If the input has an explicit scheme://, accept only http(s) with a host. Reject file://, mailto:, data:, javascript:, etc.
  • Otherwise, treat as a host+path payload and parse against the current page's protocol. Reject inputs without a / so plain EAN/UPC barcode digits still fall through to the existing product-lookup path.

Used by both ScannerModal.vue and parseHomeboxUrl in the AR scanner. The AR scanner's path regexes also got the i flag so uppercase paths resolve to the right entity type (vue-router already routes static path segments case-insensitively, but the AR scanner classifies the entity via its own regex).

Which issue(s) this PR fixes:

None

Testing

20 unit tests in composables/utils.test.ts covering: full http(s) URLs, mixed-case URLs, protocol-less host+path payloads (with and without port, with and without uppercase), current-page protocol fallback, bare paths and numeric barcodes, protocol-relative URLs, and non-http schemes file://, mailto:, javascript:, data:.

@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

A new parseScanResult utility strictly validates barcode-scanned payloads as HTTP(S) URLs, rejecting non-URL-shaped inputs and disallowed schemes. ScannerModal and barcode detector components are updated to use this parser, and route extraction now employs case-insensitive matching to resolve uppercase-encoded entity IDs.

Changes

Barcode scan URL parsing and validation

Layer / File(s) Summary
Scan result parser implementation and validation
frontend/composables/utils.ts, frontend/composables/utils.test.ts
New parseScanResult function handles explicit scheme:// URLs and protocol-less host/path payloads, normalizing protocols/hosts and rejecting non-HTTP(S) schemes, malformed URLs, and non-URL-shaped inputs. Comprehensive test suite validates all parsing paths and rejection cases including origin matching and special localhost handling.
Scanner modal integration
frontend/components/App/ScannerModal.vue
ScannerModal now routes decoded scan text through parseScanResult instead of direct URL construction, validating the parsed result and its pathname before proceeding with navigation logic.
Barcode detector route parsing and case-insensitive matching
frontend/composables/use-barcode-detector.ts
parseHomeboxUrl branches on pathname (/ prefix) versus scanned URL (parsed via parseScanResult), validates origin matching, and applies case-insensitive regex matching for asset/item/location route extraction to handle uppercase-encoded segments.

Security Recommendations

🔒 Verification of URL origin validation:

  • Confirm that parseHomeboxUrl correctly validates globalThis.location?.origin to prevent barcode payloads from arbitrary origins from being processed.
  • Verify that the HTTP(S)-only scheme restriction in parseScanResult adequately blocks javascript:, data:, file:, and mailto: payloads, as tested in the suite.

🔒 Case-insensitive route matching:

  • The case-insensitive regex flag (/i) on entity ID extraction is appropriate for flexibility, but confirm that this does not inadvertently match unintended patterns or create security bypass opportunities in route resolution.

🔒 Null handling in integration points:

  • Ensure ScannerModal and barcode detector gracefully handle null returns from parseScanResult and do not fall through to unsafe fallback logic.

🎯 3 (Moderate) | ⏱️ ~20 minutes


⬆️ enhancement


  • katosdev
  • tonyaellie

A scanner wakes up, decays URLs with grace,
HTTP(S) only—the secure embrace,
Case-insensitive, routes align,
Barcodes parsed with logic fine,
No malicious schemes shall trace. 📱✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description includes all required sections: PR type (feature), detailed explanation of what the PR does and why (protocol-less URL support, C40 mode optimization), issue reference (None), and comprehensive testing details (20 unit tests).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'feat: scanner protocol-less urls' clearly and concisely describes the main feature addition, matching the PR's primary objective of enabling scanner support for URLs without explicit protocols.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot requested review from katosdev and tonyaellie May 16, 2026 12:34
@rufusutt rufusutt changed the title Feat/scanner protocol less urls feat: scanner protocol less urls May 16, 2026
@coderabbitai coderabbitai Bot added the ⬆️ enhancement New feature or request label May 16, 2026
@rufusutt rufusutt changed the title feat: scanner protocol less urls feat: scanner protocol-less urls May 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/composables/use-barcode-detector.ts`:
- Around line 89-96: The regex character class used to sanitize and extract IDs
(the patterns applied to sanitized and in the assetMatch/itemMatch/locationMatch
tests) incorrectly places the hyphen between 9 and _, creating an unintended
range; update those regexes (the sanitization regex and the three extraction
regexes in useBarcodeDetector/composable where sanitized.match is used) to
either escape the hyphen or move it to the end of the class (e.g., change
[a-zA-Z0-9-_] to [A-Za-z0-9_-] or [A-Za-z0-9_\-]) so IDs only match letters,
digits, underscore and hyphen.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1116ca53-7d0a-4c59-bb58-536ea224090b

📥 Commits

Reviewing files that changed from the base of the PR and between e8af2e3 and 3a80039.

📒 Files selected for processing (4)
  • frontend/components/App/ScannerModal.vue
  • frontend/composables/use-barcode-detector.ts
  • frontend/composables/utils.test.ts
  • frontend/composables/utils.ts

Comment on lines +89 to 96
const assetMatch = sanitized.match(/^\/a\/([a-zA-Z0-9-_]+)/i);
if (assetMatch) return { entityType: "asset", id: assetMatch[1]! };

const itemMatch = sanitized.match(/^\/item\/([a-zA-Z0-9-_]+)/);
const itemMatch = sanitized.match(/^\/item\/([a-zA-Z0-9-_]+)/i);
if (itemMatch) return { entityType: "item", id: itemMatch[1]! };

const locationMatch = sanitized.match(/^\/location\/([a-zA-Z0-9-_]+)/);
const locationMatch = sanitized.match(/^\/location\/([a-zA-Z0-9-_]+)/i);
if (locationMatch) return { entityType: "location", id: locationMatch[1]! };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In JavaScript RegExp character classes, does [a-zA-Z0-9-]match characters beyond letters/digits/underscore/hyphen? What is the safest equivalent for exactly alnum ++-?

💡 Result:

In JavaScript regular expressions, the character class [a-zA-Z0-9-] does not match characters beyond letters, digits, underscores, and hyphens, provided the hyphen is placed correctly [1][2][3]. However, if the hyphen is placed between two characters (e.g., [a-z0-9-]), it may be interpreted as a range operator depending on the surrounding characters, which can lead to unexpected behavior [4][5]. The hyphen (-) is a special character inside character classes used to define ranges (e.g., a-z) [6][7]. If it is not placed at the very beginning or the very end of the class, or if it is not escaped with a backslash (-), the regex engine may attempt to create a range between the characters immediately preceding and following it [1][2][8]. For example, in [a-z0-9-], the hyphen is between 9 and , which is generally safe because the ASCII value of 9 is less than the ASCII value of , but it is best practice to avoid ambiguity [6][5]. The safest and most readable equivalent for exactly alphanumeric characters (a-z, A-Z, 0-9), underscores (), and hyphens (-) is: /[\w-]/ In JavaScript, the \w shorthand character class is equivalent to [A-Za-z0-9] [1][2][3]. By placing the hyphen at the end of the class ([\w-]), you ensure it is treated as a literal hyphen without needing to escape it [1][2][8]. If you prefer to be explicit or want to avoid the \w shorthand, the safest explicit pattern is: /[a-zA-Z0-9-]/ In this version, the hyphen is escaped (-), which explicitly tells the regex engine to treat it as a literal character regardless of its position [4][8].

Citations:


🏁 Script executed:

# Check if the file exists and read the relevant lines
if [ -f "frontend/composables/use-barcode-detector.ts" ]; then
  echo "File exists. Reading lines 85-100:"
  sed -n '85,100p' "frontend/composables/use-barcode-detector.ts"
else
  echo "File not found. Searching for it..."
  find . -name "use-barcode-detector.ts" -type f
fi

Repository: sysadminsmedia/homebox

Length of output: 731


Fix regex character class escaping on lines 84 and 89–96 to prevent matching unintended punctuation.

The character class [a-zA-Z0-9-_] treats the hyphen (between 9 and _) as a range operator, matching ASCII 57–95, which includes unwanted punctuation like :;<=>?@[\]^. This affects both the sanitization regex on line 84 and the ID extraction patterns on lines 89–96.

Move the hyphen to the end of the character class or escape it: [A-Za-z0-9_-] or [A-Za-z0-9_\-].

Suggested patch
-    const sanitized = pathname.replace(/[^a-zA-Z0-9-_/]/g, "");
+    const sanitized = pathname.replace(/[^A-Za-z0-9_-/]/g, "");
 
     // Case-insensitive so uppercase-encoded codes resolve to the right entity.
-    const assetMatch = sanitized.match(/^\/a\/([a-zA-Z0-9-_]+)/i);
+    const assetMatch = sanitized.match(/^\/a\/([A-Za-z0-9_-]+)/i);
 
-    const itemMatch = sanitized.match(/^\/item\/([a-zA-Z0-9-_]+)/i);
+    const itemMatch = sanitized.match(/^\/item\/([A-Za-z0-9_-]+)/i);
 
-    const locationMatch = sanitized.match(/^\/location\/([a-zA-Z0-9-_]+)/i);
+    const locationMatch = sanitized.match(/^\/location\/([A-Za-z0-9_-]+)/i);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/composables/use-barcode-detector.ts` around lines 89 - 96, The regex
character class used to sanitize and extract IDs (the patterns applied to
sanitized and in the assetMatch/itemMatch/locationMatch tests) incorrectly
places the hyphen between 9 and _, creating an unintended range; update those
regexes (the sanitization regex and the three extraction regexes in
useBarcodeDetector/composable where sanitized.match is used) to either escape
the hyphen or move it to the end of the class (e.g., change [a-zA-Z0-9-_] to
[A-Za-z0-9_-] or [A-Za-z0-9_\-]) so IDs only match letters, digits, underscore
and hyphen.

@rufusutt

Copy link
Copy Markdown
Author

Regarding CodeRabbit feedback

  • Origin validation: already in place in use-barcode-detector.ts.
  • HTTP(S)-only scheme restriction: enforced in parseScanResult and covered by the tests in utils.test.ts.
  • Null handling: in ScannerModal the null falls through to the existing EAN/UPC product-lookup path. In the AR scanner it's just dropped, since AR mode doesn't have a product-lookup flow.
  • The regex-class hyphen suggestion would have broken the regex (_ > / creates an out-of-order range). Original is correct in ECMAScript without the v flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⬆️ enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant