Skip to content

[TT-17065] Fix MinTokenLength: reject silent-accept on create + correct off-by-one operator#8154

Merged
imogenkraak merged 6 commits into
masterfrom
TT-17065/reject-short-custom-keys
Jun 8, 2026
Merged

[TT-17065] Fix MinTokenLength: reject silent-accept on create + correct off-by-one operator#8154
imogenkraak merged 6 commits into
masterfrom
TT-17065/reject-short-custom-keys

Conversation

@sedkis

@sedkis sedkis commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Two related defects in the MinTokenLength enforcement chain. They were originally surfaced together by a 2-week investigation on the Evri Apigee→Tyk migration; this PR fixes both in one go because they are coupled — the create-time guard has to mirror whatever the runtime gate does, and changing only one of them just moves the trap.

  1. Silent-accept on create. POST /tyk/keys/<customID> historically stored any custom-ID key regardless of length. If the key was unreachable at auth time, the operator got no signal at create — they got 200 OK, the session went into Redis, and then every consumer request 403'd with response_flag=AKI. This PR rejects the create with 400 Bad Request whenever len(customID) < MinTokenLength, with an error message that names both the submitted length and the configured minimum.
  2. Off-by-one operator at the runtime gate. gateway/middleware.go::CheckSessionAndIdentityForValidKey used if len(key) <= minLength, which rejects a key whose length is exactly MinTokenLength. The config field reads as a minimum accepted length, but was enforced as a strict lower bound — which is what bit Evri (32-char Apigee keys vs MinTokenLength=32). This PR changes the gate to if len(key) < minLength, so a key of length equal to MinTokenLength is accepted, matching the field's name and documentation. The create-time guard above mirrors the same < semantic.

Background — how this was found

The Evri Apigee-to-Tyk migration PoC was blocked for ~2 weeks on 403s across every imported key. Apigee default consumer keys are 32 chars; Evri had set TYK_GW_MINTOKENLENGTH=32 thinking it was the minimum accepted length. Tyk's auth middleware used len(key) <= minLength, so 32-char keys were rejected before any Redis lookup — but the create path happily accepted and stored them. The only form that worked was the eyJ… envelope (120+ chars), which external-system consumers don't have. Two weeks of investigation chased Portal/Dashboard/REGO/hash-function code paths before the length gate surfaced.

There are two distinct mistakes made by the operator+code interaction here, and fixing only one of them leaves a real trap behind:

  • If we only fix the silent-accept (1), the operator with MinTokenLength=32 still can't create a 32-char key — the field name lied to them, and they have to hunt for the off-by-one in code.
  • If we only fix the operator (2), an operator with MinTokenLength=64 can still POST a 30-char custom-ID key, get 200 OK, and silently 403 every consumer request.

So both fixes ship together.

Behavior matrix (before vs after)

Reproduced on tyk-demo with min_token_length: 32:

Request Before After
POST /tyk/keys/shortkey (custom id, len=8) 200 OK, session stored, traffic later 403s 400 Bad Request at create; no session written
POST /tyk/keys/apigeecustomkey0123456789abcdefg (custom id, len=32 — equal to limit) 200 OK, session stored, traffic later 403s 200 OK at create; traffic with raw key now 200 OK ← the case that bit Evri
POST /tyk/keys/apigeecustomkey0123456789abcdefg_lon (custom id, len=35) 200 OK 200 OK (unchanged)
POST /tyk/keys/create (autogenerate) 200 OK 200 OK (unchanged — generateToken envelope is well above any reasonable MinTokenLength)
PUT /tyk/keys/<existingShortID> (update an old pre-fix import) 200 OK 200 OK (unchanged — admin API still allows mutate/read/delete on already-stored keys)
Traffic with the eyJ… envelope of any of the above 200 OK 200 OK (unchanged)

Implementation

1. Runtime gate (gateway/middleware.go)

- if len(key) <= minLength {
+ if len(key) < minLength {
      return user.SessionState{IsInactive: true}, false
  }

Default fallback (minLength = 3 when MinTokenLength is unset) is unchanged in placement; only the comparison flips. Effect: in the default-config case, a key of length exactly 3 now authenticates instead of being rejected. There are no tests asserting the old boundary behavior.

2. Create-time guard (gateway/api.go::handleAddOrUpdate, POST branch)

minLen := gw.GetConfig().MinTokenLength
if keyName != "" && minLen > 0 && len(keyName) < minLen {
    return apiError(fmt.Sprintf(
        "custom key ID length %d is less than min_token_length (%d); "+
            "the key would be unreachable at auth time. Use an ID of at least min_token_length characters, "+
            "or lower min_token_length in the gateway configuration.",
        len(keyName), minLen,
    )), http.StatusBadRequest
}

Gated on keyName != \"\" so autogenerated creates fall through. Gated on minLen > 0 so the default-config path (where MinTokenLength is 0 / unset, and the middleware falls back to 3) is not affected by this guard — that case is handled by the runtime gate's default; this PR intentionally doesn't over-apply.

PUT/update path unchanged. Existing keys created before this fix remain returnable/mutable/deletable via the admin API — important for cleanup of pre-fix imports.

Test plan

TestKeyHandler_RejectCustomKeyBelowMinTokenLength (in gateway/api_test.go) exercises, with MinTokenLength=32:

  • Custom ID strictly below MinTokenLength (len=31) → 400 (rejected)
  • Custom ID exactly equal to MinTokenLength (len=32) → 200 (accepted — the case that bit Evri, now the canonical "works" case)
  • Custom ID above MinTokenLength (len=34) → 200 (unchanged)
  • Autogenerated create (POST /tyk/keys/create) → 200 (unchanged)
  • Broader regression: TestKeyHandler|TestCreateKey|TestHashKeyHandler|TestCheckSession|TestAuthKey suite passes locally.
go test ./gateway/ -run TestKeyHandler_RejectCustomKeyBelowMinTokenLength -v -count=1
go test ./gateway/ -run 'TestKeyHandler|TestCreateKey|TestHashKeyHandler|TestCheckSession|TestAuthKey' -count=1

Backwards compatibility

Both changes are pure relaxations or loud-failure additions — no traffic that previously authenticated will stop authenticating, and no key creation that previously produced a usable key will now fail.

  • Runtime gate (<=<): keys whose raw length equals MinTokenLength go from rejected at auth time → accepted at auth time. Anyone relying on the old <= semantics intentionally (e.g., wanting "strictly greater than 32") would have configured MinTokenLength=33 to express that, so this is not a breaking change in practice. The field name and docs both read as "minimum accepted," which is now what the code does.
  • Create-time guard: rejects only inputs that would have been silently broken under the old behavior. There is no input being rejected that previously produced a working key.
  • Default config (MinTokenLength unset): runtime gate's default is minLength = 3. The operator change means a key of length exactly 3 now authenticates instead of being rejected. Tyk-generated tokens are always far above this; the only practical effect is that hand-typed 3-char custom IDs (uncommon — and arguably should work given the field is called "min_token_length") now work.
  • Existing keys: unaffected on read / update / delete paths.

References

  • TT-17065
  • Customer-engineering journal (internal): `deployed-engineering/customers/evri/credentials/2026-04-24-apigee-keys-403-mintokenlength.md`
  • Generalised migration pattern (internal): `deployed-engineering/use-cases/migration/apigee-to-tyk/patterns/mintokenlength-and-custom-keys.md`

Follow-up (separate ticket): add the same create-time guard to the Dashboard layer (`tyk-analytics/dashboard/api_keys.go::createKey`). Not required for correctness — the Gateway 400 here bubbles up — but it's a nicer UX for Dashboard UI/API clients to fail fast without a Gateway round-trip.

🤖 Generated with Claude Code

Tyk's auth middleware short-circuits in CheckSessionAndIdentityForValidKey
(middleware.go:603-613) with `if len(key) <= minLength`, so any custom-ID
key POSTed at or below `min_token_length` is stored in Redis but silently
403s (response_flag=AKI) on every subsequent auth attempt with the raw ID.
Only the wrapped `eyJ...` envelope form authenticates — which consumers
migrating from external systems (Apigee, AWS API Gateway, Kong, etc.)
don't have.

This cost an Evri Apigee migration two weeks of debugging before the
length gate surfaced, because the import path gave no signal that every
created key was unusable.

Fix: at the POST branch of handleAddOrUpdate, reject with 400 when a
user-supplied keyName has `len(keyName) <= MinTokenLength`. The error
names both the submitted length and the configured minimum so the
operator can act on it immediately. Autogenerated creates (empty
keyName) are unaffected because generateToken produces an envelope
that is always well above any reasonable MinTokenLength. PUT/update
is untouched.

Test added: TestKeyHandler_RejectCustomKeyBelowMinTokenLength exercises
below/equal/above the limit, plus autogenerated create, under
MinTokenLength=32.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@probelabs

probelabs Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

This PR addresses two related defects in MinTokenLength enforcement. It corrects an off-by-one error in the runtime authentication check, allowing keys with a length equal to the configured minimum to be accepted. Additionally, it introduces a create-time validation to reject custom keys shorter than the minimum length, preventing a scenario where keys could be created successfully but would silently fail every authentication attempt.

Files Changed Analysis

  • gateway/api.go: A validation guard is added to the handleAddOrUpdate function. This change rejects POST requests for custom keys with an ID shorter than MinTokenLength, returning a 400 Bad Request with a descriptive error message.
  • gateway/middleware.go: The comparison operator in CheckSessionAndIdentityForValidKey is changed from <= to <. This corrects an off-by-one error, ensuring keys with a length exactly equal to MinTokenLength are now correctly authenticated.
  • gateway/api_test.go: A new test suite, TestKeyHandler_RejectCustomKeyBelowMinTokenLength, is added to verify the new behavior. It asserts that keys shorter than the limit are rejected, keys equal to the limit are accepted, and autogenerated keys are unaffected.

Architecture & Impact Assessment

  • What this PR accomplishes: It resolves a critical bug that caused silent authentication failures for custom API keys. By aligning the behavior of the key creation endpoint with the runtime authentication logic, it provides immediate, clear feedback for invalid key lengths and ensures the MinTokenLength setting behaves as documented.

  • Key technical changes introduced:

    1. Create-Time Validation: A new guard in gateway/api.go prevents the creation of custom keys that do not meet the MinTokenLength requirement.
    2. Runtime Logic Correction: The operator in the gateway/middleware.go length check is changed from <= to <, fixing an off-by-one error that incorrectly rejected valid keys.
  • Affected system components: The changes affect the Tyk Gateway's Admin API for key management (POST /tyk/keys/:keyName) and the core authentication middleware responsible for validating token length during request processing.

API Flow Comparison

Before Change (Silent Failure for key length == MinTokenLength):

sequenceDiagram
    participant Admin
    participant Tyk Gateway
    participant Redis
    participant Consumer

    Admin->>+Tyk Gateway: POST /tyk/keys/key-with-len-32 (MinTokenLength=32)
    Tyk Gateway->>+Redis: Store session for key
    Redis-->>-Tyk Gateway: OK
    Tyk Gateway-->>-Admin: 200 OK (Key created)

    Note over Consumer, Redis: Later...
    Consumer->>+Tyk Gateway: GET /api (Authorization: key-with-len-32)
    Note right of Tyk Gateway: Runtime check `len(key) <= 32` fails
    Tyk Gateway-->>-Consumer: 403 Forbidden
Loading

After Change (Correct Validation and Acceptance):

sequenceDiagram
    participant Admin
    participant Tyk Gateway
    participant Consumer

    Admin->>+Tyk Gateway: POST /tyk/keys/too-short-key (MinTokenLength=32)
    Note right of Tyk Gateway: Create-time check `len(key) < 32` fails
    Tyk Gateway-->>-Admin: 400 Bad Request

    Admin->>+Tyk Gateway: POST /tyk/keys/key-with-len-32 (MinTokenLength=32)
    Tyk Gateway-->>-Admin: 200 OK (Key created)

    Note over Consumer, Tyk Gateway: Later...
    Consumer->>+Tyk Gateway: GET /api (Authorization: key-with-len-32)
    Note right of Tyk Gateway: Runtime check `len(key) < 32` passes
    Tyk Gateway-->>-Consumer: 200 OK
Loading

Scope Discovery & Context Expansion

  • The changes are well-contained within the Tyk Gateway, specifically targeting the inconsistency between the key creation API and the authentication middleware.
  • The impact is primarily on users who have set a non-default MinTokenLength and are creating keys with custom IDs, a common scenario when migrating from other API management platforms.
  • The PR author correctly identifies a potential follow-up action: adding a similar validation to the Dashboard API (tyk-analytics) to provide a better user experience by failing faster, which demonstrates a good understanding of the broader system architecture.
Metadata
  • Review Effort: 2 / 5
  • Primary Label: bug

Powered by Visor from Probelabs

Last updated: 2026-06-08T12:17:05.540Z | Triggered by: pr_updated | Commit: 45ea2f3

💡 TIP: You can chat with Visor using /visor ask <your question>

@probelabs

probelabs Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Security Issues (1)

Severity Location Issue
🟡 Warning gateway/api.go:602-608
The create-time validation for minimum token length is incomplete. It does not handle the default case where `MinTokenLength` is not configured. The runtime check in `gateway/middleware.go` defaults to a minimum length of 3 in this scenario, but the new create-time check is skipped due to the `minLen > 0` condition. This allows an admin to create a custom key with a length less than 3, which will be successfully stored but will then be rejected at runtime, perpetuating the 'silent-accept' bug this PR aims to fix for the default configuration.
💡 SuggestionTo ensure consistent behavior, the logic in `handleAddOrUpdate` should fully mirror the runtime check by also applying the default minimum length of 3 when `MinTokenLength` is not set. This can be achieved by checking if `minLen <= 0` and setting it to 3 before validating the key length.

Architecture Issues (1)

Severity Location Issue
🟡 Warning gateway/api.go:602-609
The create-time validation for `MinTokenLength` does not handle the default configuration case, creating an inconsistency with the runtime validation logic. The runtime logic in `gateway/middleware.go` defaults `MinTokenLength` to 3 if it's unset (0), but the new create-time check is skipped if `minLen` is 0 due to the `minLen > 0` condition. This means that with a default gateway configuration, a user can still create a custom key with a length less than 3. This key will be accepted at creation but then silently fail during authentication, which is the same problem pattern this PR aims to fix for non-default configurations.
💡 SuggestionTo ensure consistent behavior and fully eliminate the 'silent-accept, runtime-reject' issue, the create-time validation should mirror the runtime logic by also applying the default minimum length of 3 when `MinTokenLength` is not explicitly set. This makes the system's behavior more predictable for operators regardless of their configuration.

✅ Performance Check Passed

No performance issues found – changes LGTM.

Security Issues (1)

Severity Location Issue
🟡 Warning gateway/api.go:602-608
The create-time validation for minimum token length is incomplete. It does not handle the default case where `MinTokenLength` is not configured. The runtime check in `gateway/middleware.go` defaults to a minimum length of 3 in this scenario, but the new create-time check is skipped due to the `minLen > 0` condition. This allows an admin to create a custom key with a length less than 3, which will be successfully stored but will then be rejected at runtime, perpetuating the 'silent-accept' bug this PR aims to fix for the default configuration.
💡 SuggestionTo ensure consistent behavior, the logic in `handleAddOrUpdate` should fully mirror the runtime check by also applying the default minimum length of 3 when `MinTokenLength` is not set. This can be achieved by checking if `minLen <= 0` and setting it to 3 before validating the key length.
\n\n ### Architecture Issues (1)
Severity Location Issue
🟡 Warning gateway/api.go:602-609
The create-time validation for `MinTokenLength` does not handle the default configuration case, creating an inconsistency with the runtime validation logic. The runtime logic in `gateway/middleware.go` defaults `MinTokenLength` to 3 if it's unset (0), but the new create-time check is skipped if `minLen` is 0 due to the `minLen > 0` condition. This means that with a default gateway configuration, a user can still create a custom key with a length less than 3. This key will be accepted at creation but then silently fail during authentication, which is the same problem pattern this PR aims to fix for non-default configurations.
💡 SuggestionTo ensure consistent behavior and fully eliminate the 'silent-accept, runtime-reject' issue, the create-time validation should mirror the runtime logic by also applying the default minimum length of 3 when `MinTokenLength` is not explicitly set. This makes the system's behavior more predictable for operators regardless of their configuration.
\n\n \n\n

Quality Issues (1)

Severity Location Issue
🟡 Warning gateway/middleware.go:622
The change to the token length validation in `CheckSessionAndIdentityForValidKey` (from `<=` to `<`) is not covered by a direct test. The new tests in `gateway/api_test.go` verify that a key with a length equal to `MinTokenLength` can be created, but they do not verify that this key can then be successfully used for authentication. This leaves a test coverage gap for a change in a critical authentication path.
💡 SuggestionEnhance the test case `equal_to_min_token_length_accepted` in `TestKeyHandler_RejectCustomKeyBelowMinTokenLength` to perform a second step: after successfully creating the key, make a request to the test API using that key and assert that the request is not rejected by the authentication middleware (i.e., does not result in a 401 or 403 error).

Powered by Visor from Probelabs

Last updated: 2026-06-08T12:17:03.916Z | Triggered by: pr_updated | Commit: 45ea2f3

💡 TIP: You can chat with Visor using /visor ask <your question>

@sedkis sedkis changed the title [TT-17065] Reject custom key create when len(customID) <= MinTokenLength [TT-17065] Fix MinTokenLength: reject silent-accept on create + correct off-by-one operator Apr 27, 2026
The auth-time gate at gateway/middleware.go:618 used `len(key) <= minLength`,
which rejects a key of length exactly equal to MinTokenLength. The config
field name reads as a "minimum accepted length" but was enforced as a
strict lower bound -- which is what bit Evri (32-char Apigee keys vs
MinTokenLength=32). Field name and docs both describe a minimum; the code
now matches.

Mirroring change in handleAddOrUpdate's create-time guard so the create
path keeps refusing exactly what the runtime gate refuses. Error message
updated: "less than or equal to" -> "less than", "longer than" -> "at
least".

The previous commit on this branch added the create-time guard but used
`<=` to match the runtime gate as it stood. Shipping only that half would
have left a worse bug behind: the operator now gets 400 for the very
case the field name promises (MinTokenLength=32 still rejecting 32-char
keys) but still can't make 32-char keys work without lowering the value.
The two defects are coupled; mirroring forces them to ship together.

Test TestKeyHandler_RejectCustomKeyBelowMinTokenLength updated:
- "below" case bumped to len=31 so it sits at the boundary
- "equal_to_min_token_length_rejected" -> "equal_to_min_token_length_accepted",
  wantCode flips from 400 to 200
- Docstring rewritten to describe the new operator

Pure-relaxation backwards-compat: no traffic that previously
authenticated stops authenticating; no key creation that previously
produced a usable key now fails.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@TykTechnologies TykTechnologies deleted a comment from github-actions Bot Apr 27, 2026
@mativm02
mativm02 requested a review from a team as a code owner April 28, 2026 11:58
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
100.0% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

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

PR #8154 — [TT-17065] Fix MinTokenLength: reject silent-accept on create + correct off-by-one operator
Review by Quinn · Tyk QA · 2026-06-04


PR Summary

Fixes two coupled defects in MinTokenLength enforcement. In middleware.go, the boundary operator <= is corrected to < so keys of exactly MinTokenLength characters are no longer rejected at auth time. In api.go, a new guard rejects custom-key creates where len(customID) < MinTokenLength with a descriptive 400 response, preventing the silent-accept/deferred-403 trap. Implementation matches the ticket description. Correctly scoped — only the POST create path is affected; updates, autogenerated keys, and hashed endpoints are not.


Jira Alignment

Field Value
Ticket TT-17065 — MinTokenLength: silent-accept of unusable custom keys + off-by-one operator at auth time
Type Bug
Status Ready for Testing
Acceptance Criteria Met? ⚠️ Partial

Criteria gaps:

# Acceptance Criterion Covered in PR? Note
1 Key of exactly min_token_length chars reaches Redis lookup (auth-time fix) ⚠️ Partial middleware.go fix is present; no test issues a proxy request with an exactly-minLength key and asserts 200
2 Key strictly shorter than min_token_length still short-circuits ✅ Yes < preserves this invariant
3 Default config (min_token_length=0 → fallback 3) preserved ✅ Yes minLen > 0 guard on create; fallback minLength = 3 in middleware unchanged
4 POST with short custom ID → 400 Bad Request with descriptive message ✅ Yes Covered by new test
5 POST with custom ID ≥ min_token_length → 200 OK, key stored ✅ Yes Covered by new test
6 min_token_length=0 → create guard is a no-op ✅ Yes minLen > 0 short-circuit present
7 Autogenerated-key creates unaffected ✅ Yes keyName != "" guard
8 PUT (update) path unaffected ✅ Yes Guard placed in else (create-only) branch
9 Error message stable and operator-matchable ✅ Yes Hardcoded format string; test verifies content

Unit & Integration Test Coverage

Package Coverage Tests Added? Gap Description Severity
gateway — api.go changes CI passed ✅ Yes TestKeyHandler_RejectCustomKeyBelowMinTokenLength covers all create-path scenarios ✅ None
gateway — middleware.go fix CI passed ❌ No dedicated test The <=< off-by-one fix has no test that exercises a proxy request with a key of exactly MinTokenLength chars and verifies it authenticates (200, not 403) 🟡 Medium

The middleware.go change is the more operationally impactful of the two fixes — it is what caused Evri's deployment to 403 every request. Yet there is no regression guard for it. A subtest should:

  1. Configure MinTokenLength = 32
  2. Create a key with a 32-character custom ID
  3. Issue a proxy request using that exact key
  4. Assert 200 OK

Without this, the off-by-one can be re-introduced without breaking the test suite.


UI Test Coverage (Playwright)

No frontend files changed — not applicable.


Security Findings

# Severity Location Finding Recommendation
1 🟢 Low gateway/api.go:602–608 Error response discloses min_token_length config value and the submitted key length Admin API — low practical risk. Consider omitting the submitted length if this endpoint is ever proxied through a less-trusted layer

No security issues require changes before merge.


Code Quality Issues

# Severity Location Issue Recommendation
1 🟢 Low gateway/api.go:597–604 Comment references the internal implementation of CheckSessionAndIdentityForValidKey (see middleware.go) — will become stale if middleware logic changes Keep only the business rationale; remove the cross-file implementation reference
2 🟢 Low gateway/api.go:603–607 Format string split across + concatenation — valid Go but a raw string literal or intermediate variable would be cleaner Non-blocking

Tyk Domain Issues

# Severity Location Issue Recommendation
1 🟢 Low gateway/api.go:597 The create-time guard is absent from the hashed-key path (isHashed == true). A short custom key on a hashed create endpoint bypasses validation Confirm intentional. If hashed custom IDs are user-supplied, apply the same guard; if the hash is always gateway-generated, add a comment explaining why validation is not needed

CI Failures — Must Be Resolved Before Merge

Check Status Action Required
s1-shift-left-cli (SentinelOne CNS Scan) 🔴 FAIL Inspect the scan report — confirm whether the new fmt.Sprintf format string or any added code triggered a rule. If false-positive, document suppression rationale
validate (Validate PR against Jira) 🔴 FAIL Confirm TT-17065 is in the correct Jira state for this workflow step; perform any required transition

Multiple upgrade-rpm jobs are CANCELLED — these appear to be infra-level race artefacts (the amazonlinux:2 variant re-ran and passed); no action needed unless the RPM maintainer says otherwise.


What Was Done Well

  • Surgical fix: the operator change in middleware.go is a single character — no collateral modification.
  • Correct enforcement point: rejecting short custom IDs at create time (rather than silently storing and failing later) is the right place for this invariant; consistent with fail-fast design.
  • Clear error message: the 400 body names both the submitted length and the configured minimum — operators can diagnose without reading source.
  • Good create-path test coverage: all relevant scenarios (short key → 400, exact-length → 200, autogenerated → 200, unset min_token_length → no-op) appear to be covered by the new test.

Gap Summary

Area Gaps Found Highest Severity
Unit / Integration Tests 1 🟡 Medium
UI Tests (Playwright) 0 — N/A
Security 1 🟢 Low
Code Quality 2 🟢 Low
Tyk Domain 1 🟢 Low
Jira Alignment 1 criterion partial ⚠️ Partial

Verdict

REQUEST CHANGES

Two blocking items before this can merge:

  1. Add an auth-flow regression test for the middleware.go fix. The <=< change is the fix that was breaking Evri's production traffic, but it has no test that verifies a key of exactly MinTokenLength characters can successfully authenticate through the gateway. Add a subtest to TestKeyHandler_RejectCustomKeyBelowMinTokenLength (or a dedicated test) that creates a 32-char key and issues a proxy request, asserting 200 OK. This is AC1 coverage and prevents silent regression.

  2. Resolve the two failing CI checks. Both s1-shift-left-cli and validate are failing. Explain and resolve each — or formally dismiss as infrastructure noise with documented rationale — before merge.

All other findings (comment fragility, hashed-key path gap, minor style) are non-blocking and can be addressed as a follow-up.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🚨 Jira Linter Failed

Commit: 45ea2f3
Failed at: 2026-06-08 12:15:49 UTC

The Jira linter failed to validate your PR. Please check the error details below:

🔍 Click to view error details
failed to get Jira issue: failed to fetch Jira issue TT-17065: Issue does not exist or you do not have permission to see it.: request failed. Please analyze the request body for more details. Status code: 404

Next Steps

  • Ensure your branch name contains a valid Jira ticket ID (e.g., ABC-123)
  • Verify your PR title matches the branch's Jira ticket ID
  • Check that the Jira ticket exists and is accessible

This comment will be automatically deleted once the linter passes.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🎯 Recommended Merge Targets

Based on JIRA ticket TT-17065: [Innersource] MinTokenLength: silent-accept of unusable custom keys + off-by-one operator at auth time

Fix Version: Tyk 5.8.15

Required:

  • release-5.8 - Minor version branch for 5.8.x patches - required for creating Tyk 5.8.15
  • master - Main development branch - ensures fix is in all future releases

Fix Version: Tyk 5.13.1

Required:

  • release-5.13 - Minor version branch for 5.13.x patches - required for creating Tyk 5.13.1
  • master - Main development branch - ensures fix is in all future releases

Fix Version: Tyk 5.14.0

⚠️ Warning: Expected release branches not found in repository

Required:

  • master - No matching release branches found. Fix will be included in future releases.

📋 Workflow

  1. Merge this PR to master first

  2. Cherry-pick to release branches by commenting on the merged PR:

    • /release to release-5.8
    • /release to release-5.13
  3. Automated backport - The bot will automatically create backport PRs to the specified release branches

@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
100.0% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

@imogenkraak
imogenkraak merged commit b118b4d into master Jun 8, 2026
53 of 55 checks passed
@imogenkraak
imogenkraak deleted the TT-17065/reject-short-custom-keys branch June 8, 2026 14:53
@imogenkraak

Copy link
Copy Markdown
Contributor

/release to release-5.8

@probelabs

probelabs Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

✅ Cherry-pick successful. A PR was created: #8287

@imogenkraak

Copy link
Copy Markdown
Contributor

/release to release-5.13

@probelabs

probelabs Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

✅ Cherry-pick successful. A PR was created: #8288

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.

5 participants