Skip to content

Validate macOS bundle identifiers#595

Open
jsdavid278-cyber wants to merge 1 commit into
profullstack:masterfrom
jsdavid278-cyber:codex/macos-bundle-id-validation
Open

Validate macOS bundle identifiers#595
jsdavid278-cyber wants to merge 1 commit into
profullstack:masterfrom
jsdavid278-cyber:codex/macos-bundle-id-validation

Conversation

@jsdavid278-cyber
Copy link
Copy Markdown
Contributor

Fixes #594.

Changes:

  • validate desktop-mac bundleId as a reverse-DNS identifier before build or ship
  • use the normalized bundleId in macOS package plans and real ship IDs
  • add regression tests for invalid bundleId values in build and ship flows

Validation:

  • vitest run packages/targets/desktop-mac/src/index.test.ts
  • tsc -p packages/targets/desktop-mac/tsconfig.json --noEmit

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 5, 2026

Greptile Summary

This PR adds reverse-DNS bundle identifier validation for the macOS target, throwing early (in both build and ship) when bundleId is missing or malformed, and ensures the normalized value flows through to the build plan JSON and the ship return ID.

  • Introduces BUNDLE_ID_PATTERN regex and requireBundleId helper; validated bundleId now replaces raw config.bundleId in the build plan and ship ID, except for one stale log call that still references config.bundleId.
  • Adds two regression tests covering invalid identifiers in both flows, using the new fakeShipContext test helper.

Confidence Score: 3/5

Safe to merge after fixing the stale log reference; the validation logic itself is sound but has a small gap.

The ship method validates and trims the bundleId correctly for the returned ID but still logs the raw config value, meaning log-based audit trails can show a different string than what was actually used. The regex also accepts labels that end with a hyphen (e.g. com.acme-.app), which is not a valid DNS label and could allow identifiers that Xcode or notarization tools ultimately reject.

packages/targets/desktop-mac/src/index.ts — the log call and the regex pattern both need a small fix.

Important Files Changed

Filename Overview
packages/targets/desktop-mac/src/index.ts Adds bundleId validation via regex and a requireBundleId helper; one stale reference to config.bundleId in the ship log line and a regex gap that allows hyphen-terminated labels.
packages/targets/desktop-mac/src/index.test.ts Adds regression tests for invalid bundleId in both build and ship flows; test coverage is straightforward and correct.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[build / ship called] --> B[requireBundleId]
    B --> C{bundleId present?}
    C -- No --> D[throw: desktop-mac requires bundleId]
    C -- Yes --> E{matches BUNDLE_ID_PATTERN?}
    E -- No --> F[throw: must be valid reverse-DNS identifier]
    E -- Yes --> G[return trimmed bundleId]
    G --> H[build: write macos-build-plan.json using validated bundleId]
    G --> I[ship: log config.bundleId ⚠️ / return id = bundleId@version]
Loading

Reviews (1): Last reviewed commit: "Validate macOS bundle identifiers" | Re-trigger Greptile

async ship(ctx, config) {
const bundleId = requireBundleId(config);
const targets = config.distribution === 'both' ? ['App Store', 'DMG host'] : [config.distribution === 'mas' ? 'App Store' : 'DMG host'];
ctx.log(`publish ${config.bundleId}@${ctx.version} → ${targets.join(', ')}`);
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.

P1 The ctx.log call logs config.bundleId (the raw, untrimmed value) instead of the validated bundleId returned by requireBundleId. If the caller passes a bundle ID with leading/trailing whitespace (e.g., " com.acme.app "), the log entry and the returned ship ID will disagree, making log-based audit trails unreliable.

Suggested change
ctx.log(`publish ${config.bundleId}@${ctx.version}${targets.join(', ')}`);
ctx.log(`publish ${bundleId}@${ctx.version}${targets.join(', ')}`);

signingIdentity?: string; // e.g. "Developer ID Application: ACME Inc (ABCDE12345)"
}

const BUNDLE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
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.

P2 The current pattern allows each label segment to end with a hyphen (e.g., com.acme-.app passes validation). Per DNS label rules, a label may not start or end with a hyphen. Tightening the character class so each label ends with an alphanumeric character prevents invalid identifiers like com.my-app-.utils from slipping through.

Suggested change
const BUNDLE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9-]*(\.[A-Za-z][A-Za-z0-9-]*)+$/;
const BUNDLE_ID_PATTERN = /^[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*(\.[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*)+$/;

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.

desktop-mac accepts invalid bundle identifiers

1 participant