Skip to content

Fix/security and algo hardening - #576

Merged
ginccc merged 5 commits into
mainfrom
fix/security-and-algo-hardening
Jun 30, 2026
Merged

Fix/security and algo hardening#576
ginccc merged 5 commits into
mainfrom
fix/security-and-algo-hardening

Conversation

@ginccc

@ginccc ginccc commented Jun 29, 2026

Copy link
Copy Markdown
Member

Summary

This pull request introduces a comprehensive set of security hardening and algorithm bug fixes across several core modules, with a focus on SSRF/file-read protections, cron scheduling correctness, retry/backoff logic, and resource usage guards. Most changes are behavior-preserving for valid input, with two intentional behavior corrections in cron parsing and retry backoff. New SSRF protections are opt-in and off by default to ensure backward compatibility.

Security and SSRF Protections:

  • OpenAPI Spec Discovery: Now validates that remote spec locations are strictly http(s) URLs, preventing local-file reads and non-http SSRF vectors (e.g., file://, classpath:). Inline content detection is improved with a new looksLikeInlineSpec() method. [1] [2] [3]
  • Opt-in SSRF Protection for Outbound Calls: Introduces a new eddi.security.ssrf-protection.enabled flag (default off). When enabled, all agent-driven outbound URLs are validated to block private/loopback/link-local/CGNAT/cloud-metadata and non-http targets. Redirect following can be disabled per request via the new setFollowRedirects method in IRequest, now supported in Vert.x. [1] [2]

Algorithm and Logic Corrections:

  • CronParser Fixes:
    • Accepts day-of-week 7 as Sunday and normalizes it to 0, matching standard cron semantics. [1] [2]
    • Corrects day-of-month/day-of-week logic to use OR (not AND) when both fields are restricted, as per Vixie cron. [1] [2] [3] [4]
    • Improves error handling for malformed fields: step and range expressions now throw clear IllegalArgumentExceptions if invalid or reversed. [1] [2]

Resource Usage Guards:

  • Dead-letter Queue Bound: The InMemoryConversationCoordinator now caps the dead-letter queue length via a configurable property (eddi.coordinator.max-dead-letters, default 1000, -1 disables). Oldest entries are evicted first to prevent unbounded memory growth. [1] [2]

Other Notable Changes:

  • Extensive new and updated tests for all new validation, SSRF, cron, and resource-guarding logic.
  • Documentation updated to reflect new configuration options and security behaviors.

These changes significantly improve the security posture and correctness of the system, while preserving expected behavior for valid, existing configurations.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 📝 Documentation update
  • ♻️ Refactoring (no functional changes)
  • 🔧 Chore (dependency updates, CI changes, etc.)

Checklist

  • My code follows the project's code style
  • I have added tests that prove my fix/feature works
  • Existing tests pass locally (./mvnw clean verify -DskipITs)
  • I have updated documentation if needed
  • My commit messages follow conventional commits
  • I have not committed any secrets, API keys, or tokens
  • This PR has a clear, focused scope (one concern per PR)

Summary by CodeRabbit

  • New Features
    • Added an opt-in security toggle to validate outbound targets and disable redirect following for protected calls, including agent card and API execution.
    • Improved OpenAPI spec loading by distinguishing inline content from remote locations and rejecting unsupported spec locations.
  • Bug Fixes
    • Fixed cron scheduling for Sunday/DOW=7 and corrected day-of-month vs day-of-week matching semantics; hardened parsing for malformed step/range.
    • Corrected retry backoff to be exponential with a capped maximum.
    • Added configurable limits for in-memory dead-letter retention.
  • Documentation
    • Updated the changelog with security and hardening notes.
  • Tests
    • Expanded tests for protection, cron behavior, retry timing, and calculator robustness (expression length/stack exhaustion).

ginccc added 2 commits June 29, 2026 22:33
…rden cron/calculator/coordinator algorithms

Easy-to-fix findings from a security & algorithm review:

- McpApiToolBuilder.parseSpec: require an http(s) URL for remote spec
  locations (UrlValidationUtils.isValidHttpUrl) before readLocation(),
  blocking file:// local-file reads, classpath:/jar:/other non-http
  schemes (reachable via /apicalls/discover-endpoints and
  create_api_agent). Scheme-only by design: private/internal hosts stay
  allowed so internal OpenAPI discovery keeps working (endpoint is
  eddi-admin/eddi-editor gated).
- CronParser: accept day-of-week 7 as Sunday (standard cron); reject
  malformed steps (*/) and reversed ranges (5-1) with clean errors
  instead of AIOOBE / silent never-fire.
- CalculatorTool: cap expression length + catch StackOverflowError to
  prevent recursive-descent stack exhaustion from LLM-supplied input.
- InMemoryConversationCoordinator: cap the dead-letter deque (1000,
  oldest-first eviction) so a failure storm can't grow heap unbounded.

Reported but intentionally unchanged (behavior change needs its own
decision): cron dom/dow AND-vs-OR semantics; ApiCallExecutor linear
'exponential' backoff. See docs/changelog.md.

Tests: +12 across McpApiToolBuilderTest, CronParserTest, CalculatorToolTest;
affected suites green, mvnw compile clean.
… semantics + exponential backoff

Tackles the remaining fixable review items (the rest are architectural):

- Opt-in SSRF protection (eddi.security.ssrf-protection.enabled, default
  off). When on: ApiCallExecutor validates the resolved httpcall URL and
  disables redirect-following (new IRequest.setFollowRedirects, honoured
  by the Vert.x wrapper); A2AToolProviderManager validates peer
  card-fetch + tasks/send URLs. RemoteApiResourceSource is intentionally
  out of scope (admin-initiated, internal imports legitimate, JDK client
  is Redirect.NEVER).
- CronParser: standard-cron dom/dow OR semantics when both fields are
  restricted (was AND); single-restricted still reduces to AND so
  existing schedules are unaffected.
- ApiCallExecutor: retry backoff is now truly exponential
  (base * 2^(attempt-1), overflow-safe, 5-min ceiling) instead of linear.

Tests: +14 (ApiCallExecutor SSRF + backoff curve, CronParser OR cases);
8 constructor-call sites updated. Mock-based suites green; A2A/embedded-
server suites compile but are unrunnable in this sandbox (JDK HttpClient
selector) - covered by CI. mvnw compile + test-compile clean.
@ginccc
ginccc requested a review from Copilot June 29, 2026 20:38
@ginccc
ginccc requested a review from rolandpickl as a code owner June 29, 2026 20:38
@github-actions

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds opt-in SSRF protection across outbound HTTP flows, hardens cron parsing and validation, caps dead-letter retention, and adds calculator input guards. It also updates related tests, config defaults, and the changelog.

Changes

Security & Algorithm Hardening

Layer / File(s) Summary
IRequest redirect control
src/main/java/ai/labs/eddi/engine/httpclient/IRequest.java, src/main/java/ai/labs/eddi/engine/httpclient/impl/HttpClientWrapper.java
Adds setFollowRedirects(boolean) to IRequest and forwards it in the Vert.x request wrapper.
OpenAPI spec location validation
src/main/java/ai/labs/eddi/engine/mcp/McpApiToolBuilder.java, src/test/java/ai/labs/eddi/engine/mcp/McpApiToolBuilderTest.java
Detects inline OpenAPI content, rejects non-http(s) remote spec locations, and adds tests for file-read and inline-spec handling.
ApiCallExecutor SSRF and backoff
src/main/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutor.java, src/main/resources/application.properties, src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutor*Test.java
Injects SSRF protection config, validates outbound targets, disables redirects when enabled, and changes retry delay calculation to capped exponential backoff with matching tests.
A2AToolProviderManager SSRF checks
src/main/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManager.java, src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManager*Test.java
Injects SSRF protection config and validates agent card and task URLs before outbound A2A requests, with updated test constructors.
CronParser semantics and validation
src/main/java/ai/labs/eddi/engine/runtime/internal/CronParser.java, src/test/java/ai/labs/eddi/engine/runtime/internal/CronParserTest.java
Accepts day-of-week 7, normalizes Sunday matching, applies DOM/DOW OR semantics, and rejects malformed step and range expressions; tests cover the updated behavior.
Dead-letter retention cap
src/main/java/ai/labs/eddi/engine/runtime/internal/InMemoryConversationCoordinator.java, src/main/resources/application.properties, src/test/java/ai/labs/eddi/engine/runtime/internal/*ConversationCoordinator*Test.java
Adds a configurable maximum for retained dead-letter entries and evicts oldest entries after routing failures, with updated tests and config.
CalculatorTool input guards
src/main/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorTool.java, src/test/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorToolTest.java
Adds a maximum expression length check and catches StackOverflowError for deeply nested expressions, with tests for both conditions.
Changelog entry
docs/changelog.md
Adds a new top-of-file changelog section for the 2026-06-29 hardening changes.

Sequence Diagram(s)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • labsai/EDDI#423: Shares the UrlValidationUtils-based SSRF hardening pattern and redirect-related outbound request behavior.

Suggested reviewers

  • rolandpickl

Poem

🐇 I hop through code with a careful grin,
The bad URLs can’t sneak back in.
Seven means Sunday, the cron now sings,
And backoff grows on exponential wings.
Dead letters capped, the calculator stays bright,
A tidy little burrow, safe and light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.66% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the PR’s main themes: security fixes and algorithm hardening.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/security-and-algo-hardening

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.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens several core modules against SSRF / file-read vectors, corrects cron parsing semantics to align with standard cron behavior, and adds resource-exhaustion guards—while keeping the new SSRF protections opt-in (disabled by default via configuration).

Changes:

  • Hardened outbound URL handling (OpenAPI spec discovery scheme-gate; optional SSRF validation + redirect disabling for agent-driven HTTP calls and A2A peer calls).
  • Fixed cron parsing bugs (DOW 7 support; dom/dow OR semantics; clearer malformed-field handling).
  • Added DoS/resource guards (calculator expression length/stack defense; dead-letter queue cap) and expanded test coverage.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/main/java/ai/labs/eddi/engine/mcp/McpApiToolBuilder.java Blocks non-http(s) spec locations; adds inline-vs-location heuristic to prevent file reads via swagger-parser.
src/main/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutor.java Adds opt-in SSRF validation + disables redirects per request; fixes exponential backoff algorithm with a ceiling.
src/main/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManager.java Adds opt-in SSRF validation for agent card fetch and task execution URLs.
src/main/java/ai/labs/eddi/engine/httpclient/IRequest.java Adds per-request redirect control API (default no-op).
src/main/java/ai/labs/eddi/engine/httpclient/impl/HttpClientWrapper.java Implements per-request redirect control for the Vert.x-backed client wrapper.
src/main/java/ai/labs/eddi/engine/runtime/internal/CronParser.java Corrects DOW range and dom/dow semantics; adds malformed step/range validation.
src/main/java/ai/labs/eddi/engine/runtime/internal/InMemoryConversationCoordinator.java Caps dead-letter retention to prevent unbounded growth under failure storms.
src/main/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorTool.java Adds expression length cap and StackOverflowError handling for deeply nested inputs.
src/main/resources/application.properties Documents and introduces eddi.security.ssrf-protection.enabled (default false).
src/test/java/ai/labs/eddi/engine/mcp/McpApiToolBuilderTest.java Adds tests for scheme-gating and inline spec handling.
src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutorTest.java Adds tests for opt-in SSRF behavior, redirect disabling, and exponential backoff curve/cap.
src/test/java/ai/labs/eddi/engine/runtime/internal/CronParserTest.java Adds tests for DOW 7 handling, dom/dow OR semantics, and malformed-field rejection.
src/test/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorToolTest.java Adds robustness tests for length cap and deep nesting behavior.
src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutorExtendedTest.java Updates constructor usage to include new SSRF flag parameter.
src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutorBranchCoverageTest.java Updates constructor usage to include new SSRF flag parameter.
src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerTest.java Updates constructor usage to include new SSRF flag parameter.
src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerExtendedTest.java Updates constructor usage to include new SSRF flag parameter.
src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerBranchTest.java Updates constructor usage to include new SSRF flag parameter.
src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerDeepBranchTest.java Updates constructor usage to include new SSRF flag parameter.
src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerUncoveredBranchTest.java Updates constructor usage to include new SSRF flag parameter.
docs/changelog.md Adds a detailed changelog entry describing the security and algorithm changes and associated tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main/java/ai/labs/eddi/engine/runtime/internal/CronParser.java Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/ai/labs/eddi/engine/httpclient/IRequest.java`:
- Around line 25-35: The default setFollowRedirects(boolean) in IRequest is
currently a silent no-op, which can let unsupported request implementations
bypass SSRF protections without notice. Change IRequest so redirect control
cannot be ignored: either make setFollowRedirects(boolean) abstract or have the
default implementation fail fast by throwing, and ensure any concrete
implementation like the Vert.x-backed request class explicitly overrides it to
handle redirect behavior.

In `@src/main/java/ai/labs/eddi/engine/mcp/McpApiToolBuilder.java`:
- Around line 168-183: The OpenAPI parsing path in McpApiToolBuilder still
allows nested external $ref fetches because ParseOptions is configured with
resolve enabled for both readContents and readLocation. Update the parsing flow
to prevent automatic resolution here, or ensure that any external reference
fetching is routed through the same http(s)-only policy enforced by
looksLikeInlineSpec, UrlValidationUtils.isValidHttpUrl, and the OpenAPIV3Parser
calls so untrusted specs cannot trigger unrestricted fetches.

In `@src/main/java/ai/labs/eddi/engine/runtime/internal/CronParser.java`:
- Around line 83-87: The day-field star detection in CronParser is too strict
because it only treats exact "*" as starred, so expressions like "*/2" are
misclassified. Update the logic around bothDayFieldsRestricted in CronParser to
use Vixie-style star semantics for the day-of-month and day-of-week fields, and
rely on that check when deciding the AND vs OR path so leading "*/" patterns are
handled as starred fields.

In `@src/main/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorTool.java`:
- Around line 44-50: Move the expression length guard in CalculatorTool before
any logging or eager string concatenation of the user input. The current
validation in the expression evaluation flow happens after the full expression
has already been built for logs, so update the relevant method in CalculatorTool
to check MAX_EXPRESSION_LENGTH first and return the error immediately, then only
log/process the expression if it passes the guard.

In `@src/test/java/ai/labs/eddi/engine/runtime/internal/CronParserTest.java`:
- Around line 194-197: The malformed-step test in CronParserTest is too broad
because assertThrows(IllegalArgumentException.class, ...) also accepts
NumberFormatException, so tighten it to verify the domain-specific failure from
CronParser.parseField("*/", 0, 59) by asserting on the exception message or
explicitly checking the thrown type/message to ensure a cron-validation error is
raised instead of a low-level parse error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0fd5a9fa-cb61-41d4-898a-095d07ca56a4

📥 Commits

Reviewing files that changed from the base of the PR and between dbff7d7 and 5957b0c.

📒 Files selected for processing (21)
  • docs/changelog.md
  • src/main/java/ai/labs/eddi/engine/httpclient/IRequest.java
  • src/main/java/ai/labs/eddi/engine/httpclient/impl/HttpClientWrapper.java
  • src/main/java/ai/labs/eddi/engine/mcp/McpApiToolBuilder.java
  • src/main/java/ai/labs/eddi/engine/runtime/internal/CronParser.java
  • src/main/java/ai/labs/eddi/engine/runtime/internal/InMemoryConversationCoordinator.java
  • src/main/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutor.java
  • src/main/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManager.java
  • src/main/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorTool.java
  • src/main/resources/application.properties
  • src/test/java/ai/labs/eddi/engine/mcp/McpApiToolBuilderTest.java
  • src/test/java/ai/labs/eddi/engine/runtime/internal/CronParserTest.java
  • src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutorBranchCoverageTest.java
  • src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutorExtendedTest.java
  • src/test/java/ai/labs/eddi/modules/apicalls/impl/ApiCallExecutorTest.java
  • src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerBranchTest.java
  • src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerDeepBranchTest.java
  • src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerExtendedTest.java
  • src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerTest.java
  • src/test/java/ai/labs/eddi/modules/llm/impl/A2AToolProviderManagerUncoveredBranchTest.java
  • src/test/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorToolTest.java

Comment thread src/main/java/ai/labs/eddi/engine/httpclient/IRequest.java Outdated
Comment thread src/main/java/ai/labs/eddi/engine/mcp/McpApiToolBuilder.java
Comment thread src/main/java/ai/labs/eddi/engine/runtime/internal/CronParser.java Outdated
Comment thread src/main/java/ai/labs/eddi/modules/llm/tools/impl/CalculatorTool.java Outdated
The dead-letter retention limit was hardcoded at 1000. Expose it as
eddi.coordinator.max-dead-letters (default 1000, -1 = unbounded,
0 = retain none), matching the existing eddi.coordinator.
max-active-conversations property and EDDI's config-driven design.

Tests: +2 (cap evicts oldest; -1 disables). Coordinator suites green.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/ai/labs/eddi/engine/runtime/internal/InMemoryConversationCoordinator.java`:
- Around line 199-207: Serialize the dead-letter enqueue and trim logic in
routeToDeadLetter() so concurrent callers cannot interleave addLast() with the
maxDeadLetters eviction loop. Add a small lock around the deadLetters update
block in InMemoryConversationCoordinator to make the cap enforcement
deterministic and prevent over-eviction under concurrent failures.
- Around line 89-96: Reject invalid dead-letter limits in
InMemoryConversationCoordinator at startup by validating the maxDeadLetters
constructor argument. Keep -1 as the only allowed unbounded sentinel, allow 0
and positive values, and throw an initialization error for any value less than
-1 so typos cannot silently disable trimming. Make the check in the
InMemoryConversationCoordinator constructor right after the injected config
values are assigned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9911ef11-3194-4281-854c-2700ce949d2c

📥 Commits

Reviewing files that changed from the base of the PR and between 5957b0c and 41e5ced.

📒 Files selected for processing (5)
  • docs/changelog.md
  • src/main/java/ai/labs/eddi/engine/runtime/internal/InMemoryConversationCoordinator.java
  • src/main/resources/application.properties
  • src/test/java/ai/labs/eddi/engine/runtime/internal/ConversationCoordinatorTest.java
  • src/test/java/ai/labs/eddi/engine/runtime/internal/InMemoryConversationCoordinatorTest.java
✅ Files skipped from review due to trivial changes (1)
  • docs/changelog.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/resources/application.properties

ginccc added 2 commits June 29, 2026 23:23
…iction, Vixie star, field-aware cron errors)

From Copilot + CodeRabbit review of the branch:

- IRequest.setFollowRedirects is now abstract (not a no-op default), so a
  new IRequest impl cannot silently re-enable the SSRF redirect bypass.
- InMemoryConversationCoordinator dead-letter eviction computes the excess
  once and evicts that many (was size()-per-iteration -> potential O(n^2)).
- CronParser: a day field is "starred" when it begins with '*' (so */2
  takes the standard AND path, not OR) - matches Vixie DOM_STAR/DOW_STAR.
- CronParser: parseIntField wraps NumberFormatException into a field-aware
  IllegalArgumentException (e.g. */abc) instead of a vague parse message.
- CalculatorTool: length guard runs before the eager debug-log
  concatenation, so oversized input isn't built/logged.

Not changed: OpenAPI external $ref resolution stays on - disabling it
breaks legitimate in-document #/components refs; documented as an accepted,
role-gated residual in docs/changelog.md.

Tests: CronParserTest +2 (non-numeric step, */2 AND path); affected suites
green (CronParser 30, ApiCallExecutor 38, coordinator 18/6, Calculator 79).
… add/trim

Addresses CodeRabbit review of the dead-letter cap:

- Reject eddi.coordinator.max-dead-letters < -1 at startup. Only -1
  (unbounded), 0 (retain none) and positive values are valid; a typo
  like -2 would otherwise silently disable trimming.
- Serialize the dead-letter add+trim under a dedicated lock so concurrent
  failures enforce the cap deterministically. (pollFirst already evicts
  oldest-first, so the newest failures were never dropped; the lock just
  removes transient under-retention below the cap.)

Tests: +2 (reject -2; accept -1 and 0). Coordinator suites green (20/6).
@ginccc
ginccc merged commit fc0003c into main Jun 30, 2026
23 checks passed
@ginccc
ginccc deleted the fix/security-and-algo-hardening branch June 30, 2026 10:27
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