Skip to content

fix(cc-widgets): remediate P0 security scan findings - #728

Open
mkesavan13 wants to merge 2 commits into
webex:nextfrom
mkesavan13:SPARK-833336/remediate-secscan-p0-findings
Open

fix(cc-widgets): remediate P0 security scan findings#728
mkesavan13 wants to merge 2 commits into
webex:nextfrom
mkesavan13:SPARK-833336/remediate-secscan-p0-findings

Conversation

@mkesavan13

@mkesavan13 mkesavan13 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

COMPLETES SPARK-833336

This pull request addresses

Six P0 security findings reported in SPARK-833336: CI secrets exposed at workflow scope, command-injection risks in the publish tooling, access-token persistence in sample applications, and an internal MobX store exposed on window.

Root Cause:

  1. CI secret exposure: pull-request.yml declared Playwright secrets as workflow-level environment variables, making them available to jobs that did not need them.
  2. Command injection: publish.js built a shell command string from branch and workspace values without validation.
  3. Access-token persistence: Both sample applications wrote OAuth access tokens to localStorage and restored them on page load.
  4. Debug global exposure: The React sample application assigned its MobX store to window.

Fix:

  1. Scoped Playwright secrets to the two E2E jobs that use them.
  2. Replaced execSync with execFileSync and added validation for branch and workspace values.
  3. Removed access-token reads and writes from localStorage in both sample applications.
  4. Removed the React sample application's window['store'] assignment.

by making the following changes

  • .github/workflows/pull-request.yml — scope Playwright secrets to e2e_test_meetings and e2e_test_cc_widgets
  • tooling/src/publish.js — use an argument-vector process API and validate publish inputs
  • tooling/tests/publish.js — update process mocks and add injection-rejection tests
  • widgets-samples/cc/samples-cc-react-app/src/App.tsx — remove access-token persistence and the global store assignment
  • widgets-samples/cc/samples-cc-wc-app/app.js — remove access-token persistence

Change Type

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Tooling change
  • Internal code refactor

The following scenarios were tested

  • The testing is done with the amplify link
  • Targeted publish-tooling tests passed: 13/13.
  • Gate 1 passed: yarn build:dev.
  • Gate 2 passed: yarn test:cc-widgets.
  • Configuration inspection confirmed Playwright secrets are limited to the E2E jobs and the reported credential/global-storage patterns are absent.
  • Amplify testing was not run; this draft records the automated and inspection evidence available from the workflow.

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Please Specify: Claude Code (Anthropic)
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

Acceptance Criteria

ID Criterion Recorded evidence
AC-1 PR CI does not expose repository secrets to untrusted PR-head jobs PW_* values moved from workflow scope to the two label-gated E2E jobs
AC-2 The React sample app does not persist OAuth access tokens in localStorage Access-token reads, writes, and synchronization removed from App.tsx
AC-3 The Web Component sample app does not persist OAuth access tokens in localStorage Access-token reads and writes removed from app.js
AC-4 Publish commands do not use shell interpretation for package or tag input execFileSync argument vectors and input validation added; injection tests pass
AC-5 The React sample does not expose its MobX store on window window['store'] = store removed from App.tsx
AC-6 Affected tooling and CC verification gates pass Tooling tests 13/13, yarn build:dev passed, and yarn test:cc-widgets passed

Acceptance criteria and recorded evidence were generated by the Jira-to-PR workflow. Human review is required to confirm semantic and production correctness.

Checklist before merging

  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the testing document
  • I have tested the functionality with amplify link

Notes:

  • Repository CI completion remains a merge-time requirement.
  • Testing-document update: not applicable; this change does not modify testing procedures.
  • Amplify testing: not run.

Jira: SPARK-833336

- Scope CI secrets to only the e2e jobs that need them (pull-request.yml)
- Replace execSync with execFileSync in publish.js to prevent shell injection
- Validate branchName and workspace names before use as npm tags/args
- Remove access token persistence in localStorage (samples apps)
- Remove window['store'] debug exposure in samples-cc-react-app
@aws-amplify-us-east-2

Copy link
Copy Markdown

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-728.d1b38q61t1z947.amplifyapp.com

@akulakum
akulakum marked this pull request as ready for review July 29, 2026 06:11
@akulakum
akulakum requested a review from a team as a code owner July 29, 2026 06:11
@akulakum akulakum added the validated Indicates that the PR is ready for actions label Jul 29, 2026
@akulakum akulakum changed the title SPARK-833336: Remediate P0 security scan findings fix(cc-widgets): remediate P0 security scan findings Jul 29, 2026
@akulakum akulakum added validated Indicates that the PR is ready for actions and removed validated Indicates that the PR is ready for actions labels Jul 29, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

useEffect(() => {
if (window.location.hash) {

P1 Badge Clear tokens left by previous sample versions

When a browser has run an earlier build, the existing localStorage.accessToken remains indefinitely because this load path stops reading and writing the key but never removes it. Consequently, an XSS on the same sample origin can still retrieve the credential, so the remediation only protects fresh users; clear the legacy key during startup in both this app and the Web Component load handler.

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +118 to +119
env:
PW_SANDBOX_PASSWORD: ${{ secrets.PW_SANDBOX_PASSWORD }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update the standing docs with the security behavior

This commit changes credential persistence, CI secret scoping, and the publish command's trust boundary without updating any module spec or standing document. That leaves the repository's security design and verification guidance out of sync with the implementation despite the mandatory same-change spec-currency rule; update the relevant standing security documentation alongside these controls.

AGENTS.md reference: AGENTS.md:L68-L68

Useful? React with 👍 / 👎.

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

Approved for P0 sec-scan pilot. CI green; Amplify smoke-tested (manual token + Init Widgets, no token persist after refresh).

@github-actions github-actions Bot removed the validated Indicates that the PR is ready for actions label Jul 30, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 678011ae0f

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +118 to +119
env:
PW_SANDBOX_PASSWORD: ${{ secrets.PW_SANDBOX_PASSWORD }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Isolate secrets from checked-out PR code

When a fork PR receives both the validated and run_e2e labels, this pull_request_target job checks out the PR head while these job-level secrets are available to every subsequent step. PR-controlled install scripts, Webpack configuration, build scripts, and Playwright code can therefore read and exfiltrate all PW_* credentials; moving them from workflow scope to job scope narrows exposure but does not satisfy AC-1's requirement to keep repository secrets out of PR-head execution. Run secret-bearing E2E work from trusted base code/artifacts rather than executing the checked-out head with repository secrets.

Useful? React with 👍 / 👎.

@@ -29,10 +29,6 @@ import './App.scss';
import {observer} from 'mobx-react-lite';
import EngageWidget from './EngageWidget';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the campaign-preview test control path

When playwright/suites/campaign-preview-tests.spec.ts is run against this React sample, removing the global store makes every helper in playwright/Utils/campaignPreviewUtils.ts fail at its explicit Store not found on window object guard. That suite injects campaign tasks and stubs SDK actions through window['store'], so the security change needs a replacement test-only control path or corresponding Playwright rewrite rather than only deleting the assignment.

Useful? React with 👍 / 👎.

// Clear the hash from the URL to remove the token from browser history
window.history.replaceState({}, document.title, window.location.pathname + window.location.search);
}
} else {

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.

How are we verifying if this change doesn't break anything ?

group: e2e-cc-widgets
cancel-in-progress: false
env:
PW_SANDBOX_PASSWORD: ${{ secrets.PW_SANDBOX_PASSWORD }}

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.

Maybe we can have a common file from where these are exported and that can be used here in PR pipeline

Comment thread tooling/src/publish.js
const validPackageNamePattern = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;

const publishWorkspace = (workspace) => {
if (!validPackageNamePattern.test(workspace)) {

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.

Why are we validating this in 2 places ? Validating here should take care of it right

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