Skip to content

Set inResponseTo validation to always#399

Open
cjbarth wants to merge 2 commits intonode-saml:masterfrom
cjbarth:inResponseTo-validation
Open

Set inResponseTo validation to always#399
cjbarth wants to merge 2 commits intonode-saml:masterfrom
cjbarth:inResponseTo-validation

Conversation

@cjbarth
Copy link
Collaborator

@cjbarth cjbarth commented Jul 27, 2025

Description

This tightens inResponseTo validation to always based on this comment.

Summary by CodeRabbit

  • Documentation

    • Updated the documentation to reflect the new default behavior for the validateInResponseTo setting.
  • Bug Fixes

    • Adjusted tests to explicitly disable InResponseTo validation where necessary, ensuring consistent test results.
  • Refactor

    • Changed the default behavior to always validate the InResponseTo attribute in SAML responses unless specified otherwise.

@coderabbitai
Copy link

coderabbitai bot commented Jul 27, 2025

Walkthrough

The default for the validateInResponseTo configuration in the SAML module was changed from "never" to "always," affecting both documentation and implementation. Related tests were updated to explicitly set the option to "never" where needed. No public APIs were changed, only default behaviors and test configurations.

Changes

Cohort / Files Change Summary
Documentation
README.md
Updated documentation to reflect new default and swapped descriptions for "always" and "never" options.
Core Implementation
src/saml.ts
Changed the default value for validateInResponseTo from never to always in the SAML class initialization.
Test Suites
test/tests.spec.ts, test/samlTests.spec.ts, test/test-signatures.spec.ts
Added validateInResponseTo: ValidateInResponseTo.never option explicitly in multiple test cases; updated imports accordingly.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Poem

A bunny hopped through docs and code,
Changing defaults on its road.
"Always" now the rule of thumb,
For SAML checks that never succumb.
Tests adjusted, docs made clear—
The code is safer, have no fear!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3529601 and 71fff2d.

📒 Files selected for processing (3)
  • test/samlTests.spec.ts (4 hunks)
  • test/test-signatures.spec.ts (33 hunks)
  • test/tests.spec.ts (21 hunks)
✅ Files skipped from review due to trivial changes (2)
  • test/test-signatures.spec.ts
  • test/tests.spec.ts
🔇 Additional comments (2)
test/samlTests.spec.ts (2)

8-8: LGTM! Import addition aligns with configuration changes.

The addition of ValidateInResponseTo import is necessary to support the explicit configuration of inResponseTo validation in the test cases below.


172-172: LGTM! Explicit configuration maintains test isolation.

These tests correctly set validateInResponseTo: ValidateInResponseTo.never to preserve their original behavior after the default was changed to "always". This approach ensures:

  1. Test isolation: These tests focus on certificate handling and caching behavior, not inResponseTo validation
  2. Backward compatibility: Tests continue to work as designed without being affected by the stricter default validation
  3. Clarity: The explicit configuration makes the test intentions clear

This pattern aligns well with the broader change to tighten inResponseTo validation by default while maintaining existing test functionality.

Also applies to: 185-185, 205-205

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cjbarth cjbarth added security Changes related to plugging exploit vectors breaking-change labels Jul 27, 2025
@cjbarth cjbarth added this to the v6 milestone Jul 27, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
test/tests.spec.ts (1)

3000-3007: Missing bulk updates – most tests still assume ValidateInResponseTo.never

Only this single test explicitly resets validateInResponseTo to never, but the build log shows dozens of failures where other test-suites still rely on the old default.
Either:

  1. Pass validateInResponseTo: ValidateInResponseTo.never in every test that doesn’t care about InResponseTo semantics, or
  2. Keep the stricter default (always) and update each assertion to expect the new InResponseTo-related errors.

Right now we have a half-way state: two tests patched, >25 still broken.
CI will stay red until this is addressed project-wide.

🧹 Nitpick comments (1)
test/tests.spec.ts (1)

3028-3032: Consider helper for repetitive SAML config overrides

Multiple tests will now need the same override:

{ ...baseConfig, validateInResponseTo: ValidateInResponseTo.never }

To avoid copy-paste and future drift, wrap it in a small factory/helper (e.g. createTestSaml(configOverrides)).
Keeps the suites concise and guarantees consistency when defaults change again.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d8d66f and 3529601.

📒 Files selected for processing (3)
  • README.md (1 hunks)
  • src/saml.ts (1 hunks)
  • test/tests.spec.ts (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: Build Status
src/saml.ts

[error] 91-91: SAML.validateInResponseTo method is causing multiple test failures with 'InResponseTo is not valid' errors.

test/tests.spec.ts

[error] 2453-2903: Assertion condition checks failed with 'InResponseTo is not valid' errors in various tests related to SAML assertion validation.


[error] 2517-2707: Assertion failures due to 'InResponseTo is not valid' replacing expected date parsing errors in assertion condition checks.


[error] 777-837: validatePostResponse tests failed with 'InResponseTo is not valid' errors instead of expected SAML error messages.


[error] 1104-1185: validatePostResponse xml signature checks failed with 'InResponseTo is not valid' errors replacing expected audience validation errors.


[error] 1245-1543: Multiple validatePostResponse xml signature tests failed with 'InResponseTo is not valid' or 'InResponseTo is missing from response' errors.


[error] 1168-1168: Audience mismatch test failed with 'InResponseTo is not valid' error instead of expected audience mismatch error.


[error] 1287-1418: Tests involving duplicate altered assertions and idpCert function validations failed due to 'InResponseTo is not valid' errors.


[error] 1507-1507: XML AttributeValue without signature test failed with 'InResponseTo is missing from response' error instead of 'Invalid signature'.


[error] 1318-1320: Tests for extra nested and altered assertions failed with 'InResponseTo is not valid' errors instead of expected invalid signature errors.


[error] 2658-2681: Assertion condition checks for expired and max assertion age failed with 'InResponseTo is not valid' errors.


[error] 2536-2536: Assertion check for NotOnOrAfter time failed with 'InResponseTo is not valid' error instead of expected expiration error.


[error] 2492-2492: Assertion check for NotBefore time failed with 'InResponseTo is not valid' error instead of expected 'not yet valid' error.


[error] 2801-2801: Assertion check for audience mismatch failed with 'InResponseTo is not valid' error instead of expected audience mismatch error.


[error] 777-815: validatePostResponse tests for error status codes and NoPassive status failed with 'InResponseTo is not valid' errors.


[error] 837-837: validatePostResponse test for attributeStatement without attributeValue failed with 'InResponseTo is not valid' error.


[error] 1364-1389: validatePostResponse xml signature checks for idpCert function validations failed with 'InResponseTo is not valid' errors.


[error] 1220-1271: validatePostResponse xml signature checks for valid and altered assertions failed with 'InResponseTo is not valid' errors.


[error] 52-52: Multiple tests failed due to assertion errors where 'InResponseTo is not valid' replaced expected signature validation messages.

🔇 Additional comments (1)
README.md (1)

118-119: Documentation accurately reflects the code changes.

The swap of descriptions and default annotation correctly documents that "always" is now the default behavior for validateInResponseTo, matching the code change in src/saml.ts.

"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
],
validateInResponseTo: ctorOptions.validateInResponseTo ?? ValidateInResponseTo.never,
validateInResponseTo: ctorOptions.validateInResponseTo ?? ValidateInResponseTo.always,
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Security improvement: Good change to enable InResponseTo validation by default.

This change tightens security by making InResponseTo validation the default behavior, which helps prevent replay attacks and ensures proper request-response correlation.

However, the pipeline failures indicate test issues with this change. Please verify that all tests have been properly updated to handle the new default behavior:


🏁 Script executed:

#!/bin/bash
# Description: Check for tests that might need explicit validateInResponseTo: never configuration

# Search for test files that might be affected by the validateInResponseTo default change
rg -A 10 -B 5 "validateInResponseTo.*never" test/
rg -A 10 -B 5 "InResponseTo.*not.*valid" test/
rg -A 10 -B 5 "new SAML\(" test/ | head -20

Length of output: 23912


Fix test failures by specifying validateInResponseTo explicitly in tests

The default for validateInResponseTo was tightened from never to always for security, which is correct. However, many existing tests assume the old default and now fail. Please update your test suites to explicitly opt-out of InResponseTo validation where needed:

• test/tests.spec.ts
– Around each validateInResponseTo: ValidateInResponseTo.never instantiation, ensure the SAML constructor includes
validateInResponseTo: ValidateInResponseTo.never.
• test/test-signatures.spec.ts
– In the new SAML({ … }) calls for signature tests that shouldn’t enforce InResponseTo, add
validateInResponseTo: ValidateInResponseTo.never.
• test/samlTests.spec.ts (and any other SAML-related spec)
– For cases “not problematic if not validated”, set
validateInResponseTo: ValidateInResponseTo.never.

Example update:

- const samlObj = new SAML({
-   callbackUrl: "http://localhost/saml/consume",
-   idpCert,
-   issuer: "onesaml_login",
-   audience: false,
-   // …other options
- });
+ const samlObj = new SAML({
+   callbackUrl: "http://localhost/saml/consume",
+   idpCert,
+   issuer: "onesaml_login",
+   audience: false,
+   validateInResponseTo: ValidateInResponseTo.never, // explicit override for this test
+   // …other options
+ });

After these adjustments, rerun the pipeline to confirm all tests pass.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/saml.ts at line 137, the default for validateInResponseTo was changed
from never to always, causing test failures. To fix this, update all relevant
test files—test/tests.spec.ts, test/test-signatures.spec.ts, and
test/samlTests.spec.ts—by explicitly setting validateInResponseTo:
ValidateInResponseTo.never in the SAML constructor options where InResponseTo
validation should be disabled. After making these changes, rerun the tests to
ensure they pass.

Copy link
Contributor

@markstos markstos left a comment

Choose a reason for hiding this comment

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

The new default ffollows the philosophy of "secure by default".

@ahacker1-securesaml
Copy link
Contributor

Attackers can just exclude inResponseTo (and there's no mechanism to reject SAML responses without InResponseTo). So this doesn't really make it more secure.

@cjbarth
Copy link
Collaborator Author

cjbarth commented Aug 18, 2025

With this default, the setting of always will require that inResponseTo be set. If we set this parameter to ifPresent, then the attacker could leave it off. So, unless there's something else I'm missing @ahacker1-securesaml , this does increase security.

@ahacker1-securesaml
Copy link
Contributor

I checked the code, and yes @cjbarth you are correct.

However, many applications use IdP initiated SSO, which has SAML responses without InResponseTo. I agree that this has some security benefit, namely preventing login CSRF.

When you click the Okta/Entra app tiles and the application logs in automatically you are basically using IdP initiated SSO. How many applications you use support this flow? Your change would basically break this flow.

I would instead change it to ifPresent, and then add some documentation saying the risks of IdP initiated SSO/login CSRF, and recommend changing it to always

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

Labels

breaking-change security Changes related to plugging exploit vectors

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants