Skip to content

fix(msteams): bound federated certificate file reads#109864

Open
xydt-juyaohui wants to merge 2 commits into
openclaw:mainfrom
xydt-juyaohui:fix/msteams-certificate-read-bound
Open

fix(msteams): bound federated certificate file reads#109864
xydt-juyaohui wants to merge 2 commits into
openclaw:mainfrom
xydt-juyaohui:fix/msteams-certificate-read-bound

Conversation

@xydt-juyaohui

Copy link
Copy Markdown
Contributor

What Problem This Solves

createFederatedApp (in extensions/msteams/src/sdk.ts) read the federated certificate path with an unbounded fs.readFileSync(creds.certificatePath, "utf-8"), so a misconfigured or oversized certificate file could trigger an unbounded read at credential-load time.

PR #109260 ran a credential-reader sweep that adopted tryReadSecretFileSync (with a maxBytes bound) across anthropic-vertex, google, gh-read, and mantis readers, but the MS Teams federated certificate read was missed. This applies the same helper there with a 1 MiB bound, so an oversized certificate file is rejected at the size check instead of being read whole. Missing or empty files still surface as the existing "Failed to read certificate file" error.

Evidence

  • The fix replaces fs.readFileSync with tryReadSecretFileSync(..., ``maxBytes: 1_048_576, rejectHardlinks: false)`, mirroring the fix: reject oversized credential files in remaining readers #109260 sweep shape (e.g. anthropic-vertex/region.ts).
  • tryReadSecretFileSync returns undefined for missing or over-limit files (its {BT}statSync().size > maxBytes{BT} guard), so the load path now throws "Failed to read certificate file ... file is empty or missing" in that case instead of proceeding with an empty/oversized key.
  • Local vitest run of extensions/msteams/src/sdk.test.ts is green: 19 passed (19).
  • New regression test mocks the helper returning undefined (the over-limit path) and asserts the load fails and tryReadSecretFileSync is called with the bound.
privateKey = tryReadSecretFileSync(creds.certificatePath, "MS Teams federated certificate", {
  maxBytes: MSTEAMS_CERTIFICATE_MAX_BYTES,
  rejectHardlinks: false,
}) ?? "";
 Test Files  1 passed (1)
      Tests  19 passed (19)

Sibling of #109260 (same tryReadSecretFileSync helper, same maxBytes-bound sweep); applies it to the MS Teams federated certificate read that the original sweep missed.

@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams size: S labels Jul 17, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 17, 2026
@clawsweeper

clawsweeper Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 19, 2026, 9:52 PM ET / July 20, 2026, 01:52 UTC.

Summary
The branch replaces the MS Teams federated-certificate fs.readFileSync call with tryReadSecretFileSync using a 1 MiB limit and updates the SDK tests.

PR surface: Source +13, Tests +30. Total +43 across 2 files.

Reproducibility: no. the source clearly shows the former unbounded synchronous read, but this review has no executed current-head filesystem reproduction or live oversized-file trace.

Review metrics: none identified.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add a temp-file regression that crosses the actual 1 MiB boundary.
  • Post redacted terminal or runtime-log proof for normal and oversized certificate files; updating the PR body should trigger a fresh review, or a maintainer can comment @clawsweeper re-review.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR supplies mocked unit-test and static-check claims, but no redacted after-fix filesystem run showing a normal certificate loads and an oversized file is rejected; please add terminal output, logs, or a reproducible transcript and redact paths, keys, tenant data, IPs, and other private details. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging introduces a 1 MiB rejection threshold for existing federated-certificate paths; an unusually large existing file would now fail credential loading, so the normal and over-limit filesystem behavior should be demonstrated before merge.
  • [P1] The current test does not exercise a real over-limit file, and the PR has no redacted runtime transcript or terminal output showing the post-fix behavior outside mocks.

Maintainer options:

  1. Prove the compatibility boundary before merge (recommended)
    Add a real filesystem regression for a normal certificate and a file exceeding 1 MiB, then post redacted after-fix runtime output showing the expected outcomes.
  2. Accept the new size policy explicitly
    Merge with the 1 MiB limit as an intentional compatibility change only after confirming that the deployment population cannot require larger federated certificate files.

Next step before merge

  • [P1] The remaining merge gate is contributor-supplied real behavior proof, which ClawSweeper cannot manufacture from the contributor's certificate-loading environment; the patch also needs the explicitly requested real-file boundary regression.

Security
Cleared: The two-file diff hardens an existing credential-file boundary using a repository helper and adds no dependency, workflow, secret, or supply-chain surface.

Review findings

  • [P2] Exercise the actual oversized-file boundary — extensions/msteams/src/sdk.test.ts:107-123
Review details

Best possible solution:

Keep the shared bounded-reader approach, add an actual filesystem regression that proves both a normal PEM and a file over the 1 MiB limit, and attach redacted after-fix terminal or log evidence before merge.

Do we have a high-confidence way to reproduce the issue?

No; the source clearly shows the former unbounded synchronous read, but this review has no executed current-head filesystem reproduction or live oversized-file trace.

Is this the best way to solve the issue?

Yes, reusing the shared bounded secret-file reader is the narrowest maintainable fix; it needs actual boundary coverage and redacted real behavior proof rather than another mocked-only assertion.

Full review comments:

  • [P2] Exercise the actual oversized-file boundary — extensions/msteams/src/sdk.test.ts:107-123
    The new test still configures tryReadSecretFileSync to return undefined, so it verifies caller handling rather than the real size check. Add a temp-file case larger than 1 MiB (and retain a normal-file case) so this MS Teams path proves that the bound is actually enforced. This remains from the prior review cycle.
    Confidence: 0.91

Overall correctness: patch is incorrect
Overall confidence: 0.87

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 27f05c8993fb.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • remove rating: 🧂 unranked krab: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.

Label justifications:

  • P2: This is a bounded hardening fix with limited blast radius, but it needs concrete runtime proof before merge.
  • merge-risk: 🚨 compatibility: The new 1 MiB limit changes credential-loading behavior for any existing MS Teams deployment configured with a larger certificate file.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR supplies mocked unit-test and static-check claims, but no redacted after-fix filesystem run showing a normal certificate loads and an oversized file is rejected; please add terminal output, logs, or a reproducible transcript and redact paths, keys, tenant data, IPs, and other private details. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +13, Tests +30. Total +43 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 15 2 +13
Tests 1 35 5 +30
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 50 7 +43

What I checked:

  • Current patch surface: The proposed change replaces the federated certificate's direct synchronous read with the existing plugin-SDK bounded secret-file reader and retains rejectHardlinks: false, avoiding a new hardlink policy change for this credential path. (extensions/msteams/src/sdk.ts:323, 099144bcb0ab)
  • Remaining boundary gap: The added oversized-file test makes the mocked helper return undefined; it verifies the caller's error mapping and requested options, but not that a real file over 1 MiB reaches the helper's size rejection path. (extensions/msteams/src/sdk.test.ts:107, 099144bcb0ab)
  • Existing shared-pattern provenance: The merged credential-reader sweep introduced the shared bounded-reader pattern for other owner-specific credential files, but its listed touched surfaces did not include the MS Teams federated certificate path. (src/plugin-sdk/secret-file-runtime.ts, 04c31f453cfc)
  • Prior review continuity: Three completed ClawSweeper cycles requested an actual oversized-file boundary exercise and contributor-supplied real behavior proof; the current PR body and comments still provide only unit-test/static-check claims and mocked helper evidence. (extensions/msteams/src/sdk.test.ts:107, b77f3dc73d36)
  • Current status: The supplied current-main base SHA is newer than the branch's functional commit, while the PR remains open, mergeable, and does not have a merged replacement that implements this exact MS Teams read path. (extensions/msteams/src/sdk.ts:323, 27f05c8993fb)

Likely related people:

  • steipete: Authored and merged the prior bounded credential-reader sweep that established the tryReadSecretFileSync adoption pattern used by this PR. (role: shared credential-reader pattern author; confidence: medium; commits: 04c31f453cfc; files: src/plugin-sdk/secret-file-runtime.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-17T09:24:15.294Z sha 3d8c3f4 :: needs real behavior proof before merge. :: [P2] Test the actual oversized-file exception
  • reviewed 2026-07-17T09:42:27.898Z sha 78fd737 :: needs real behavior proof before merge. :: [P2] Exercise the real oversized-file boundary
  • reviewed 2026-07-17T09:58:35.516Z sha b77f3dc :: needs real behavior proof before merge. :: [P2] Exercise the actual oversized-file path

@xydt-juyaohui
xydt-juyaohui force-pushed the fix/msteams-certificate-read-bound branch from 3d8c3f4 to 78fd737 Compare July 17, 2026 09:35
@xydt-juyaohui

Copy link
Copy Markdown
Contributor Author

CI status note

This change only touches extensions/msteams/src/sdk.ts (swap an unbounded fs.readFileSync for the tryReadSecretFileSync helper with a 1 MiB bound) plus its tests. The local checks are green: vitest 19/19, oxlint clean, and tsgo typecheck clean on the extensions-test shard (the sdk.test.ts mock type is correctly string | undefined).

check-test-types passes on this revision - the two earlier sdk.test.ts undefined-assignment errors were a mock return-type issue I fixed (the helper legitimately returns undefined for missing/over-limit files, so the mock's return type is string | undefined).

The remaining CI failures are main-wide and unrelated to this change:

1. check-lint - oxlint max-lines ratchet fails on a main file that this PR does not touch (same pre-existing condition as on main HEAD). msteams/sdk.ts is not in the lint output.

2. build-artifacts - Check CLI startup memory - gateway status --json measured 428.4 MB vs the 425 MB limit (samples 428.4 / 428.4 / 426.2, a ~0.8% marginal overage). The msteams SDK module is not on the gateway status startup import graph, so this change cannot move that figure.

3. checks-node-changed-2 - a node-changed lane failure unrelated to the certificate-read change in this PR.

Happy to rebase once main's lint/memory baseline settles. The sibling sweep this builds on is #109260 (which itself introduced the anthropic-vertex/stream-runtime.ts TS2352 currently visible on main - worth a separate fix).

createFederatedApp read the certificate path with an unbounded
fs.readFileSync, so a misconfigured or oversized certificate file could
trigger an unbounded read at credential-load time.

Adopt tryReadSecretFileSync (the same helper the credential-reader sweep
in openclaw#109260 applied to anthropic-vertex / google / gh-read / mantis) with a
1 MiB maxBytes bound so oversized certificate files are rejected at the
size check rather than read whole. Missing or empty files surface as the
existing "Failed to read certificate file" error.

Update the sdk tests to mock tryReadSecretFileSync and add a regression
case asserting an oversized file (helper returns undefined) fails the
load with the bound applied.
@xydt-juyaohui
xydt-juyaohui force-pushed the fix/msteams-certificate-read-bound branch from 78fd737 to b77f3dc Compare July 17, 2026 09:52
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label Jul 17, 2026
@xydt-juyaohui

Copy link
Copy Markdown
Contributor Author

Update after rebasing onto main (e0478e2)

Rebased to include #109826 (test/script typecheck repair), #109845 (web push migration lint), and #109863 (CLI startup metadata cache reuse).

  • check-test-types now passes (the sdk.test.ts mock return type is string | undefined, correctly handling the helper's missing/over-limit return).
  • check-lint passes after the web-push lint fix in fix: restore lint after Web Push migration #109845.
  • build-artifacts fails on gateway status --json startup memory (persistent main-wide marginal threshold, ~429 MB vs 425 MB limit, unrelated to this change).
  • checks-node-changed-2 fails - unrelated to the certificate-read change here.

Leaving this for maintainer review - the change itself is green locally (vitest 19/19, oxlint, tsgo) and the remaining failures are main-wide baseline issues.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant