Skip to content

Fix case-sensitive section/URL label matching in config_helper (#99)#104

Merged
JillRegan merged 1 commit into
1Password:mainfrom
jasondillingham:fix-case-insensitive-section-url
May 22, 2026
Merged

Fix case-sensitive section/URL label matching in config_helper (#99)#104
JillRegan merged 1 commit into
1Password:mainfrom
jasondillingham:fix-case-insensitive-section-url

Conversation

@jasondillingham

Copy link
Copy Markdown
Contributor

Fixes #99.

Per @JillRegan's comment on #99, the fix is to swap name == strings.ToLower(s.Label) for strings.EqualFold(name, s.Label) in sectionIDForName. While implementing, I noticed the same case-sensitive comparison pattern in four other sites in the same file plus one inline comparison in setValuesForTag. They're all the same bug class — user-supplied struct tag values matched case-sensitively against 1Password-stored labels — so I included them all. Happy to split into a smaller PR if you'd prefer to land just the section helpers.

Bug

In connect/config_helper.go, comparisons of struct-tag values against 1Password labels lowercase only one side, so any mixed-case label silently fails to match:

if name == strings.ToLower(s.Label) { ... }    // sections — lowercases label only
if url.Label == strings.ToLower(name) { ... }  // urls — lowercases tag only (mirror image)
if f.Label == field.Tag.Get(fieldTag) { ... }  // fields — no lowercase at all (case-sensitive)

A user with the struct:

type Config struct {
    Host string `opsection:"Details" opfield:"hostname"`
}

— and a section actually named "Details" in 1Password — gets Host = "" silently. The reporter noticed this for opsection; the same class of bug exists for opurl (mirror direction) and for opfield (no lowercasing at all).

Fix

All five comparison sites now use strings.EqualFold(tag, label):

  • Idiomatic Go for case-insensitive string comparison
  • No allocations (vs. strings.ToLower which allocates a new string on each call)
  • Correctly handles Unicode case folding (e.g. Turkish dotted/dotless I)

Tests

  • New connect/config_helper_test.go — table-driven unit tests for all five helpers (sectionIDForName, sectionLabelForName, urlPrimaryForName, urlLabelForName, urlURLForName). Covers exact-case, lowercase, uppercase, mixed-case, no-match, nil, and empty cases. 32 sub-tests total.
  • New Test_restClient_loadStructFromItem_caseInsensitiveTags in connect/client_test.go — end-to-end test exercising setValuesForTag with UPPERCASE and mixed-case tags against the existing getComplexItem fixture (which uses lowercase labels). Catches the field-label fix in setValuesForTag that the unit tests can't reach.
  • Verified each test fails against the unfixed code; 19 of the new sub-tests catch the bug. The others are lowercase-only happy paths that the bug doesn't affect.

Pre-flight checks

  • go test ./... — pass
  • go test -race ./... — pass
  • gofmt -l ./... — clean
  • go vet ./... — clean
  • Bug-demo verified: reverting any subset of the fix causes the corresponding tests to fail

@github-actions

Copy link
Copy Markdown

⚠️ This PR contains unsigned commits. To get your PR merged, please sign those commits (git rebase --exec 'git commit -S --amend --no-edit -n' @{upstream}) and force push them to this branch (git push --force-with-lease).

If you're new to commit signing, there are different ways to set it up:

Sign commits with gpg

Follow the steps below to set up commit signing with gpg:

  1. Generate a GPG key
  2. Add the GPG key to your GitHub account
  3. Configure git to use your GPG key for commit signing
Sign commits with ssh-agent

Follow the steps below to set up commit signing with ssh-agent:

  1. Generate an SSH key and add it to ssh-agent
  2. Add the SSH key to your GitHub account
  3. Configure git to use your SSH key for commit signing
Sign commits with 1Password

You can also sign commits using 1Password, which lets you sign commits with biometrics without the signing key leaving the local 1Password process.

Learn how to use 1Password to sign your commits.

Watch the demo

@jasondillingham jasondillingham force-pushed the fix-case-insensitive-section-url branch from 043be38 to 8dcd7f5 Compare May 11, 2026 16:04
…word#99)

Per @JillRegan's comment on 1Password#99: swap `name == strings.ToLower(s.Label)`
for `strings.EqualFold(name, s.Label)` in `sectionIDForName`. While
implementing, noticed the same case-sensitive comparison pattern in 4
other sites in the same file (`sectionLabelForName`, `urlPrimaryForName`,
`urlLabelForName`, `urlURLForName`) and in the field-label comparison
inside `setValuesForTag`. All five comparison sites now use
`strings.EqualFold`. Adds table-driven unit tests for all five helpers
plus an end-to-end test exercising mixed-case tags through
`setValuesForTag`.

`go test ./...`, `go test -race ./...`, `gofmt`, `go vet` all clean.

@JillRegan JillRegan 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.

Thanks for the fix on this @jasondillingham 🙌 Approved!

@JillRegan JillRegan merged commit b0e280e into 1Password:main May 22, 2026
2 of 4 checks passed
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.

Case sensitivity issue when unmarshalling struct with opsection tag

2 participants