Skip to content

Conversation

@traeok
Copy link
Member

@traeok traeok commented Oct 24, 2025

What It Does

  • Implements support for credential manager options in Imperative. Add a property for credentialManagerOptions at the root-level of the object in .zowe/settings/imperative.json to specify options to a credential manager.
  • Implements support for providing a persistence override for setting credentials on Windows. When provided as the persist property in the credentialManagerOptions object, credentials are stored using the given persistence value. Incorrect persistence values are ignored and "enterprise" (CRED_PERSIST_ENTERPRISE, or 0x3) is the default.

How to Test

  • Install dependencies and build all SDKs & CLI on this branch: npm install && npm run build
  • Update your .zowe/settings/imperative.json file to contain the new credential manager option:
{
  "overrides": {
    "CredentialManager": "@zowe/cli"
  },
  "credentialManagerOptions": {
    "persist": "session"
  }
}
  • Using the build of Zowe CLI, run ZOWE_IMPERATIVE_LOG_LEVEL=TRACE zowe --help
  • Check the log at .zowe/logs/imperative.log and see the following:
[TRACE] [DefaultCredentialManager.js:96] [DefaultCredentialManager] Persistence level received (win32): session
  • Run zowe config secure and enter in your secure values
  • Check the Credential Manager in Windows and see that the secure props are saved with the given persistence level, e.g.:
image

Where the persistence shows "Logon session" with the example above.

Review Checklist
I certify that I have:

  • updated the changelog
  • manually tested my changes
  • added/updated automated unit/integration tests
  • created/ran system tests (provide build number if applicable)
  • followed the contribution guidelines

@github-project-automation github-project-automation bot moved this to New Issues in Zowe CLI Squad Oct 24, 2025
@zowe-robot zowe-robot moved this from New Issues to In Progress in Zowe CLI Squad Oct 24, 2025
throw new ImperativeError({msg: `Namespace ${namespace} does not exist`});
}

(namespaceObj as Record<string, SettingValue>)[key] = value;

Check warning

Code scanning / CodeQL

Prototype-polluting assignment Medium

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
library input
.

Copilot Autofix

AI 4 days ago

To fix the problem, we should prevent storing any properties on namespaceObj whose keys could introduce prototype pollution—specifically "__proto__", "constructor", or "prototype". The simplest way to do this, and to minimize functional changes, is to add an explicit check that rejects such keys before performing the assignment. If such a key is detected, we should throw an error (e.g., using ImperativeError) and refuse the operation. This preserves all existing logic and validation, only adding a guard clause before the assignment in set.

Alternatively (and arguably even more robustly), we could replace the storage structure with a Map object. However, as this requires a potentially more extensive change (possibly impacting serialization and other logic), and the code is already interface-driven (ISettingsFile), the correct way with the smallest disruption is to simply prohibit dangerous keys.

All changes are to be made within the set method (lines 131-143) in packages/imperative/src/settings/src/AppSettings.ts.

No new imports are needed.


Suggested changeset 1
packages/imperative/src/settings/src/AppSettings.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/imperative/src/settings/src/AppSettings.ts b/packages/imperative/src/settings/src/AppSettings.ts
--- a/packages/imperative/src/settings/src/AppSettings.ts
+++ b/packages/imperative/src/settings/src/AppSettings.ts
@@ -138,6 +138,10 @@
             }
         }
 
+        if (key === "__proto__" || key === "constructor" || key === "prototype") {
+            throw new ImperativeError({msg: `Key '${key}' is not allowed.`});
+        }
+
         (namespaceObj as Record<string, SettingValue>)[key] = value;
         this.flush();
     }
EOF
@@ -138,6 +138,10 @@
}
}

if (key === "__proto__" || key === "constructor" || key === "prototype") {
throw new ImperativeError({msg: `Key '${key}' is not allowed.`});
}

(namespaceObj as Record<string, SettingValue>)[key] = value;
this.flush();
}
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Member Author

@traeok traeok Oct 27, 2025

Choose a reason for hiding this comment

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

I agree, but this change would be considered a bug fix and not an enhancement. Given that there are already 2 enhancements in this PR, I feel that it's sensible to resolve this in a follow-up PR to keep PR changes minimal and relevant to original issue/request scope.

@codecov
Copy link

codecov bot commented Oct 24, 2025

Codecov Report

❌ Patch coverage is 94.11765% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.84%. Comparing base (fdd6221) to head (3ef675c).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...tive/src/security/src/CredentialManagerOverride.ts 85.18% 4 Missing ⚠️
...ackages/imperative/src/settings/src/AppSettings.ts 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2630      +/-   ##
==========================================
+ Coverage   91.81%   91.84%   +0.02%     
==========================================
  Files         644      645       +1     
  Lines       19143    19208      +65     
  Branches     4124     4146      +22     
==========================================
+ Hits        17577    17641      +64     
- Misses       1564     1565       +1     
  Partials        2        2              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: Trae Yelovich <[email protected]>
@traeok traeok force-pushed the feat/cred-mgr-options branch from b7ed7ee to 58ca777 Compare October 24, 2025 17:56
@traeok traeok force-pushed the feat/cred-mgr-options branch from a05939b to 9b469b8 Compare October 27, 2025 12:55
@traeok traeok force-pushed the feat/cred-mgr-options branch from 6079197 to 26563bb Compare October 27, 2025 13:26
@traeok
Copy link
Member Author

traeok commented Oct 27, 2025

Regarding the remaining SonarCloud issue: Member 'displayName: string' is never reassigned; mark it as readonly

While I agree, I'm choosing to leave the member as-is as this code has existed in the codebase for some time. We can revisit in v4 if we feel that its important to address.

@traeok traeok force-pushed the feat/cred-mgr-options branch from 103f2bd to af7581a Compare October 27, 2025 13:46
@traeok

This comment was marked as outdated.

@traeok traeok marked this pull request as ready for review October 28, 2025 18:37
@github-actions
Copy link

📅 Suggested merge-by date: 11/11/2025

@zowe-robot zowe-robot moved this from In Progress to Review/QA in Zowe CLI Squad Oct 28, 2025
Copy link
Member

@gejohnston gejohnston left a comment

Choose a reason for hiding this comment

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

I identified something that might be a typo in a comment, which is harmless, but might be misleading.

The results in the log are as follows:

[2025/10/28 17:20:41.970] [TRACE] [DefaultCredentialManager.js:96] [DefaultCredentialManager] Persistence level received (win32): session

[2025/10/28 17:17:15.879] [TRACE] [AppSettings.js:58] {
  overrides: { CredentialManager: '@zowe/cli' },
  credentialManagerOptions: { persist: 'session' }
}

I think that the log records are consistent with the code changes. The test instructions in the PR might be slightly wrong.

}

await CredentialManagerFactory.initialize({
// Load credential manager options from team config if available
Copy link
Member

Choose a reason for hiding this comment

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

Minor detail: Unless I badly misunderstand, the comment about loading from "team config" is a typo.

Copy link
Member Author

@traeok traeok Oct 28, 2025

Choose a reason for hiding this comment

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

Thanks Gene - I initially jotted this down as a to-do for this PR, but after some discussions offline & in standup we felt it was best to save that for v4. I updated the comment in 3ca7d34 to reflect that 👍

I also updated the PR description to more accurately reflect the message seen in the log.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
4 Security Hotspots
72.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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

Labels

None yet

Projects

Status: Review/QA

Development

Successfully merging this pull request may close these issues.

Pass options to configured credential manager [Windows] Custom persistence flag for Secrets SDK

3 participants