Skip to content

[1.8] Security scan follow-ups, part 1: WSL signing key, decompression limit, templates, OTP seed - #2055

Merged
annejan merged 2 commits into
1.8from
security/1.8-scan-backport-a
Oct 26, 2026
Merged

annejan merged 2 commits into
1.8from
security/1.8-scan-backport-a

Conversation

@annejan

@annejan annejan commented Oct 26, 2026

Copy link
Copy Markdown
Member

Summary

Backport of #2051 to the 1.8 branch, for a 1.8.5 later (no release now). 1.8's code differs from main, so this is ported by hand.

Finding Change on 1.8
WSLENV omits PASSWORD_STORE_SIGNING_KEY (Medium) Forwarded with /u. The existing /w entries (length, character set) also become /u, and PASSWORD_STORE_GPG_OPTS/u is added.
Decompression bomb (Low, two places) --max-output 64 MiB on all four gpg decryptions: show, re-encrypt and its check, and content search. The pass backend gets it via PASSWORD_STORE_GPG_OPTS, after the user's own options (split on whitespace like pass's shell).
.default_template as a link to /dev/zero (Low) Both template files are read only if they are regular files (no link, device or FIFO), and at most 64 KiB; a UTF-8 BOM is dropped. 1.8 has no Util::openRegularFile, so the check is a QFileInfo test before the open. The bounded read covers a file that is swapped or grows afterwards.
otpauth template field shows the seed (Low) A bare otpauth:// line is never split into a field.

Not in this PR: the copy hints and autoclear for the entry view (SecretTextBrowser and SecretLineEdit from #2051 and #2053). 1.8 keeps its clipboard logic in QtPass rather than a ClipboardManager, so that comes as part 2. The store-identity limitation (#2050) has no 1.8 counterpart to change: 1.8's signed .gpg-id binds neither folder nor store.

CHANGELOG: a new [Unreleased] — 1.8.5 section with the security entries and the WSL upgrade note. WSL users with a signing key need a signed .gpg-id and the key inside WSL. No version bump.

Test plan

  • make check (Qt 6.12, offscreen): 27 suites, 981 passed, 0 failed
  • New tests:
    • everyDecryptionCapsItsOutput
    • templateFilesMustBeRegularAndSmall (link to /dev/zero, 200 KiB line, BOM)
    • gpgOptsCarryTheOutputLimitAfterTheUsersOwn (tabs and newlines)
    • parseOtpauthNotAFieldEvenWhenTheTemplateNamesIt
    • WSLENV flags
  • Prettier, markdownlint and textlint clean on the CHANGELOG; localization/ untouched
  • CI, including the Qt 5.15 job

🤖 Generated with Claude Code

https://claude.ai/code/session_01VJygpMUf461yZgfAqwMJ6d

…, OTP

Backport of #2051 for the 1.8 branch (a 1.8.5 to come; no release yet).
1.8's code differs, so this is ported by hand:

- WSL: WSLENV forwards PASSWORD_STORE_SIGNING_KEY to pass in WSL, and
  the length, character set and GPG options get /u; /w meant "from WSL
  out", so pass there never saw them, and without the signing key it
  did not check .gpg-id.sig.
- Decompression: the four gpg decryptions (show, re-encrypt and its
  check, content search) pass --max-output 64 MiB; the pass backend gets
  it through PASSWORD_STORE_GPG_OPTS after the user's own options.
- Templates: .templates and .default_template are read only when they
  are regular files (no link, device or FIFO), and at most 64 KiB, with a
  UTF-8 byte order mark dropped. 1.8 has no Util::openRegularFile, so the
  check is by QFileInfo before the open; the bounded read stops a file
  that is swapped or grows after it.
- otpauth: a bare otpauth:// line is never split into a field, also not
  when the template lists "otpauth".

The copy hints for the entry view (SecretTextBrowser, SecretLineEdit,
tracking for autoclear) follow in a second PR: 1.8 keeps its clipboard
logic in QtPass, not in a ClipboardManager.

CHANGELOG: an Unreleased 1.8.5 section with the security entries and the
WSL upgrade note. Tests for each fix; make check: 27 suites, 981 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJygpMUf461yZgfAqwMJ6d
Signed-off-by: Anne Jan Brouwer <brouwer@annejan.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI (base), Organization UI (inherited)
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 3bfcde72-2501-4526-ad1f-afa6ea3d62b1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

…cate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VJygpMUf461yZgfAqwMJ6d
Signed-off-by: Anne Jan Brouwer <brouwer@annejan.com>
@coveralls

coveralls commented Oct 26, 2026 •

Copy link
Copy Markdown

Coverage Status

coverage: 68.622% (+0.1%) from 68.518% — security/1.8-scan-backport-a into 1.8

@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.77778% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 66.89%. Comparing base (faa94d3) to head (46b135c).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/templateio.cpp 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              1.8    #2055      +/-   ##
==========================================
+ Coverage   66.73%   66.89%   +0.16%     
==========================================
  Files          58       58              
  Lines        5083     5111      +28     
==========================================
+ Hits         3392     3419      +27     
- Misses       1691     1692       +1     
Flag Coverage Δ
qtpass 66.89% <97.77%> (+0.16%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

👍 for 46b135c. The 1.8 backport of #2051's part 1 checks out against the main version.

  • WSLENV: /u, with the signing key and PASSWORD_STORE_GPG_OPTS.
  • --max-output: on all four decryptions. On 1.8 the content search lives in ImitatePass::grepMatchFile, and it is covered there too.
  • Templates: regular files only, 64 KiB at most, BOM dropped.
  • otpauth: an otpauth:// line is never split into a field.

Each has a test. The GPG_OPTS test restores the environment before its QCOMPARE, so a failure does not leak it.

Qt 5 / C++17: std::optional (src.pro has c++17), split(QRegularExpression, Qt::SkipEmptyParts) (5.14+), QTextStream(QString *), the QRegularExpression include and isOtpUri are all there on 1.8. The ubuntu-latest, 5.15 build is green, as is everything else; only CodeQL was still running.

One pedantic note, not blocking. 1.8 has no Util::openRegularFile, so this is check-then-open: QFileInfo first, QFile::open afterwards. A FIFO put in place exactly between the two would make open() block on the GUI thread, because opening a FIFO for reading waits for a writer. The bounded read covers a file that grows or is swapped for a big one, but not that. Through a synced store the timing is not realistic, so this is fine for 1.8.

Leaving the copy hints (part 2) and #2050 out, as the PR says, is right.

@annejan
annejan merged commit fa3f6f2 into 1.8 Oct 26, 2026
26 checks passed
@annejan
annejan deleted the security/1.8-scan-backport-a branch October 26, 2026 23:20
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.

3 participants