Skip to content

security(line): synthesize auth boundary hardening for webhook and replay paths#32545

Merged
Takhoffman merged 18 commits intomainfrom
task-line-auth-boundary-synthesis
Mar 3, 2026
Merged

security(line): synthesize auth boundary hardening for webhook and replay paths#32545
Takhoffman merged 18 commits intomainfrom
task-line-auth-boundary-synthesis

Conversation

@Takhoffman
Copy link
Copy Markdown
Contributor

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: LINE inbound auth boundaries were fragmented across pairing authorization, webhook verification, and replay handling, creating partial-trust behavior under overlap (DM vs group allowlists, replayed payload variants, and ack timing).
  • Why it matters: Partial coverage in security boundaries can allow unintended authorization paths or make failure/retry behavior unsafe under provider redeliveries.
  • What changed: Synthesized LINE hardening into one branch: account-scoped pairing-store checks, explicit group-vs-DM policy separation, fail-closed webhook startup secret validation, replay dedupe (webhook event + message-id/postback keyed by account), and processing-before-200 webhook semantics.
  • What did NOT change (scope boundary): No channel expansion, no new external dependencies, no changes to unrelated providers/channels, and no origin/main direct push/merge.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • LINE webhook startup now fails immediately when channelSecret is blank/whitespace.
  • LINE group authorization remains explicit to group allowlist policy and does not inherit DM pairing-store entries.
  • LINE replayed inbound payloads are deduped more strictly (message-id/postback/event-id, account-scoped).
  • LINE webhook handlers now process events before acknowledging 200, allowing provider retries on processing failure.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (Yes)
  • If any Yes, explain risk + mitigation:
    • Data access scope is tightened to account-scoped pairing authorization semantics in LINE paths; risk is behavioral regressions for misconfigured multi-account setups, mitigated via focused regression tests for DM/group boundary and replay permutations.

Repro + Verification

Environment

  • OS: macOS (worktree-based local run)
  • Runtime/container: Node 22+, pnpm workspace
  • Model/provider: n/a
  • Integration/channel (if any): LINE + gateway plugin HTTP auth path checks
  • Relevant config (redacted): LINE dmPolicy/groupPolicy variants; webhook signed/unsigned probes

Steps

  1. Apply synthesized commits from the related PR set onto one branch.
  2. Run focused regression tests for LINE handlers/webhook/gateway plugin auth path.
  3. Run full local quality gates (pnpm build, pnpm check).

Expected

  • DM/group boundaries remain strict, replay duplicates are dropped, invalid/missing signature flows fail closed (except verification probe), and all gates pass.

Actual

  • All targeted tests and local gates pass.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: DM pairing account scoping, group allowlist isolation, webhook secret fail-closed startup, signed/unsigned/probe permutations, replay dedupe by event + message id, and process-before-200 webhook behavior.
  • Edge cases checked: unsigned empty-events verification probe; redelivery with changed webhookEventId but same message id; cross-account allowlist scoping.
  • What you did not verify: live LINE cloud callbacks in external environment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert this PR or revert replay-related commits first, then policy cluster if needed.
  • Files/config to restore: src/line/bot-handlers.ts, src/line/webhook.ts, src/line/webhook-node.ts, plus related tests.
  • Known bad symptoms reviewers should watch for: unexpected duplicate LINE turns, unexpected group message admits/blocks, webhook retry storms.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: Over-aggressive dedupe suppresses legitimate redelivery variants.
    • Mitigation: account-scoped keys + focused replay tests for message-id/event-id permutations.
  • Risk: process-before-200 can increase webhook latency on heavy processing paths.
    • Mitigation: current tests verify correctness; monitor LINE webhook timeout behavior and adjust handler path if needed.

@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 3, 2026

🤖 We're reviewing this PR with Aisle

We're running a security check on the changes in this PR now. This usually takes a few minutes. ⌛
We'll post the results here as soon as they're ready.

Progress:

  • Analysis
  • Triage
  • Finalization

Latest run failed. Keeping previous successful results. Trace ID: 019cb1ff955ff36b50cadaca358f05bb.

Last updated on: 2026-03-03T04:40:54Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb20a8cfc06968cee59799cafd7e9.

Last updated on: 2026-03-03T04:52:52Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb2234d41f3f2cdf04814b957edbc.

Last updated on: 2026-03-03T05:21:25Z

Latest run failed. Keeping previous successful results. Trace ID: 019cb259ef03ba0a39c7f032b6cb15c9.

Last updated on: 2026-03-03T06:19:34Z

@openclaw-barnacle openclaw-barnacle bot added size: M maintainer Maintainer-authored PR labels Mar 3, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e0bc14f83

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR synthesizes LINE inbound auth hardening across four areas: account-scoped pairing-store lookups, explicit group-vs-DM policy separation, fail-closed webhook startup validation when channelSecret is blank, and process-before-200 semantics with in-memory replay deduplication.

Key findings:

  • Postback dedup key uses replyToken instead of webhookEventId — The most significant issue. In buildLineWebhookReplayKey, postback events are keyed by event.replyToken. LINE assigns a new, unique replyToken on every delivery attempt (including redeliveries), so the cache key from the original delivery will never match the key from a retry. Postback redeliveries therefore bypass the dedup check entirely. The stable cross-delivery identifier is webhookEventId, which the code already uses correctly in the generic fallback path (lines 113–129) but never reaches for postbacks because replyToken is virtually always present. This gap is also untested — there is no test covering postback dedup across redeliveries. Given that the companion change moves processing before the 200 response (making LINE timeouts and retries more likely), this bug meaningfully undermines the replay-hardening goal.

  • Group/DM policy separation and account-scoped pairing — The readChannelAllowFromStore change from process.env to undefined and the explicit effectiveGroupAllow derivation (excluding DM pairing-store entries) look correct and well-tested.

  • Fail-closed startLineWebhook — The channelSecret trim-and-throw guard is correctly placed; createLineWebhookMiddleware remains usable as a lower-level utility without the guard, which is an acceptable layered design.

  • Process-before-200 error handling — Both webhook.ts and webhook-node.ts correctly propagate processing errors into the outer catch block and return 500, allowing LINE to retry. Individual per-event errors inside handleLineWebhookEvents continue to be swallowed and logged, which keeps the behaviour consistent for single-event failures within a batch.

Confidence Score: 3/5

  • Safe to merge for most paths, but the postback replay-dedup bug should be fixed before deploying to environments with active postback traffic and process-before-200 semantics.
  • The group/DM boundary hardening, account-scoped pairing, fail-closed secret validation, and process-before-200 changes are all correct and well-tested. However, the postback dedup branch uses replyToken as its cache key — a value LINE regenerates on every redelivery — so postback events will not be deduplicated across retries. Combined with the process-before-200 change that increases retry likelihood under slow processing, this creates a gap in the replay-hardening goal for postback events.
  • src/line/bot-handlers.ts — specifically the buildLineWebhookReplayKey postback branch (lines 103–111) and the absence of a postback redelivery dedup test in src/line/bot-handlers.test.ts.

Last reviewed commit: 0e0bc14

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@Takhoffman
Copy link
Copy Markdown
Contributor Author

Addressed the replay-dedupe review findings in 4739b97.

Changes made:

  • Switched postback replay dedupe to stable identifiers (webhookEventId fallback path), removing replyToken-based keys.
  • Changed replay-cache semantics to mark events as seen only after handler success (no pre-processing cache insert).
  • Added tests for:
    • postback redelivery dedupe when replyToken changes
    • retry behavior after transient processing failure (event is not cached on failure)

Verification:

  • pnpm test src/line/bot-handlers.test.ts
  • pnpm check

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4739b979cd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d2cf3a875

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@Takhoffman
Copy link
Copy Markdown
Contributor Author

Addressed the remaining webhook ACK review concern in 6520161.

What changed:

  • handleLineWebhookEvents now logs per-event errors and rethrows after the loop.
  • This lets createLineWebhookMiddleware return non-200 on real processing failures so LINE can retry, while still preserving per-event replay dedupe state for successfully processed events.
  • Updated src/line/bot-handlers.test.ts to assert failure propagation and that replay cache is not marked on failed processing.

Also included earlier in this branch:

  • Non-text/media regression guards to keep command authorization fail-closed:
    • src/media-understanding/apply.test.ts
    • src/line/bot-message-context.test.ts

@Takhoffman Takhoffman force-pushed the task-line-auth-boundary-synthesis branch from 6520161 to e84267d Compare March 3, 2026 06:10
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ee17c8217

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@Takhoffman
Copy link
Copy Markdown
Contributor Author

Addressed the new in-flight replay continuity review concern in be7ad01.

What changed:

  • Reworked replay in-flight tracking to store a per-key in-flight Promise and await it on concurrent duplicates.
  • Concurrent duplicate deliveries now mirror the first attempt outcome:
    • first attempt success -> duplicate skips and returns success
    • first attempt failure -> duplicate path observes failure and propagates non-200, preserving retry semantics
  • Kept post-success replay marking semantics (seen cache only after successful handler completion).

Regression coverage added:

  • mirrors in-flight replay failures so concurrent duplicates also fail

Verification run:

  • pnpm test src/line/bot-handlers.test.ts src/line/webhook.test.ts src/line/webhook-node.test.ts

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

Labels

maintainer Maintainer-authored PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants