From 2e11ea87e30d0f6deaf17a67876c9f44d50283e5 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 27 Mar 2026 13:45:03 -0700 Subject: [PATCH 1/6] fix: address OpenSSF Scorecard findings - Add SECURITY.md (#85) - Scope workflow token permissions to least privilege (#86) - Pin all GitHub Action dependencies to commit SHAs (#87) - Update vulnerable dependencies via npm audit fix (#88) - Add schedule trigger to CodeQL for full SAST coverage (#89) - Ensure CI and SAST run on all pushes and PRs (#90) Closes #85, #86, #87, #88, #89, #90 Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/ci.yml | 10 +++--- .github/workflows/claude.yml | 2 ++ .github/workflows/codeql-analysis.yml | 12 ++++--- .github/workflows/coverage.yml | 8 +++-- .github/workflows/dependabot-automerge.yml | 11 +++--- .github/workflows/nodejs-tests.yml | 10 ++++-- .github/workflows/playwright-tests.yml | 10 +++--- .github/workflows/sonarcloud.yml | 12 ++++--- SECURITY.md | 33 +++++++++++++++++ package-lock.json | 42 +++++++++++----------- 10 files changed, 103 insertions(+), 47 deletions(-) create mode 100644 SECURITY.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0284426e..ed01f422 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,7 @@ name: CI Pipeline +permissions: read-all + on: push: branches: @@ -16,7 +18,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: # For same-repo PRs, check out the head branch explicitly so tests # run against the exact branch commit (not the synthetic merge commit). @@ -27,7 +29,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: node-version: '20' @@ -67,13 +69,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: ref: ${{ github.event.pull_request.head.ref }} token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: node-version: '20' diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 7297276c..22666104 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -1,5 +1,7 @@ name: Claude Code +permissions: read-all + on: pull_request: branches: [main] diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 83b46a69..8e57197b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,10 +1,14 @@ name: 'CodeQL' +permissions: read-all + on: push: branches: [main] pull_request: branches: [main] + schedule: + - cron: '25 14 * * 1' jobs: analyze: @@ -22,17 +26,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@v4 + uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4 - name: Run CodeQL analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4 with: category: 'security' diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 722a1d7f..c7f59c9a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,5 +1,7 @@ name: Coverage +permissions: read-all + on: pull_request: branches: @@ -11,12 +13,14 @@ on: jobs: coverage: runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: node-version: '20' diff --git a/.github/workflows/dependabot-automerge.yml b/.github/workflows/dependabot-automerge.yml index f750d57d..f1e76893 100644 --- a/.github/workflows/dependabot-automerge.yml +++ b/.github/workflows/dependabot-automerge.yml @@ -5,25 +5,26 @@ on: branches: - main -permissions: - contents: write - pull-requests: write +permissions: read-all jobs: dependabot: runs-on: ubuntu-latest if: github.event.pull_request.user.login == 'dependabot[bot]' + permissions: + contents: write + pull-requests: write steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2 + uses: dependabot/fetch-metadata@ffa630c65fa7e0ecfa0625b5ceda64399aea1b36 # v2 with: github-token: '${{ secrets.GITHUB_TOKEN }}' - name: Generate app token if: steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.dependency-type == 'indirect' id: app-token - uses: actions/create-github-app-token@v1 + uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1 with: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }} diff --git a/.github/workflows/nodejs-tests.yml b/.github/workflows/nodejs-tests.yml index bb3b52e6..1fd90c2e 100644 --- a/.github/workflows/nodejs-tests.yml +++ b/.github/workflows/nodejs-tests.yml @@ -1,5 +1,7 @@ name: Node.js Tests +permissions: read-all + on: push: branches: [main] @@ -10,16 +12,18 @@ jobs: node-tests: name: Node.js Tests runs-on: ubuntu-latest + permissions: + contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Use Node.js 20 - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: node-version: '20' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} diff --git a/.github/workflows/playwright-tests.yml b/.github/workflows/playwright-tests.yml index fca13428..048c563f 100644 --- a/.github/workflows/playwright-tests.yml +++ b/.github/workflows/playwright-tests.yml @@ -1,5 +1,7 @@ name: Playwright UI Tests +permissions: read-all + on: push: branches: [main] @@ -13,15 +15,15 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Use Node.js 20 - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6 with: node-version: '20' - name: Cache node modules - uses: actions/cache@v5 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} @@ -39,7 +41,7 @@ jobs: - name: Upload Playwright report on failure if: failure() - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 with: name: playwright-report path: playwright-report/ diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 368894ce..b16a340d 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -1,20 +1,24 @@ name: SonarCloud Analysis -permissions: - contents: read - pull-requests: read + +permissions: read-all + on: push: branches: [main] pull_request: branches: [main] + jobs: sonarcloud: name: SonarCloud runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - name: SonarCloud Scan diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..73f89ff7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,33 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| latest | :white_check_mark: | + +## Reporting a Vulnerability + +If you discover a security vulnerability in this project, please report it responsibly. + +**Do not open a public issue.** + +Instead, use one of the following methods: + +1. **GitHub Private Vulnerability Reporting**: Use the [Security tab](https://github.com/petry-projects/google-app-scripts/security/advisories/new) to report a vulnerability privately. +2. **Email**: Send details to **security@petry-projects.dev**. + +### What to include + +- A description of the vulnerability +- Steps to reproduce the issue +- Any relevant logs or screenshots +- The potential impact of the vulnerability + +### Response Timeline + +- **Acknowledgement**: Within 48 hours of receiving your report. +- **Initial Assessment**: Within 5 business days. +- **Resolution**: We aim to release a fix within 30 days of confirming the vulnerability, depending on complexity. + +We appreciate your help in keeping this project secure. diff --git a/package-lock.json b/package-lock.json index aaf9b4b7..893af62a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -944,9 +944,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1956,9 +1956,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2145,9 +2145,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2750,9 +2750,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", "dev": true, "license": "MIT", "dependencies": { @@ -3551,9 +3551,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6561,9 +6561,9 @@ } }, "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", "dev": true, "license": "MIT", "dependencies": { @@ -7110,9 +7110,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, "license": "ISC", "bin": { From fd412373ce6d07c0500be6576e89251c3d722b56 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 27 Mar 2026 19:27:42 -0700 Subject: [PATCH 2/6] fix: address PR review comments - Replace permissions: read-all with permissions: {} (deny-by-default) - Use concrete version target (main branch) in SECURITY.md Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/ci.yml | 2 +- .github/workflows/claude.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/dependabot-automerge.yml | 2 +- .github/workflows/nodejs-tests.yml | 2 +- .github/workflows/playwright-tests.yml | 2 +- .github/workflows/sonarcloud.yml | 2 +- SECURITY.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed01f422..fb8cb5df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ name: CI Pipeline -permissions: read-all +permissions: {} on: push: diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 22666104..1207d904 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -1,6 +1,6 @@ name: Claude Code -permissions: read-all +permissions: {} on: pull_request: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8e57197b..7da46fe6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,6 +1,6 @@ name: 'CodeQL' -permissions: read-all +permissions: {} on: push: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c7f59c9a..689447da 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,6 +1,6 @@ name: Coverage -permissions: read-all +permissions: {} on: pull_request: diff --git a/.github/workflows/dependabot-automerge.yml b/.github/workflows/dependabot-automerge.yml index f1e76893..2281580e 100644 --- a/.github/workflows/dependabot-automerge.yml +++ b/.github/workflows/dependabot-automerge.yml @@ -5,7 +5,7 @@ on: branches: - main -permissions: read-all +permissions: {} jobs: dependabot: diff --git a/.github/workflows/nodejs-tests.yml b/.github/workflows/nodejs-tests.yml index 1fd90c2e..7fd8bcd3 100644 --- a/.github/workflows/nodejs-tests.yml +++ b/.github/workflows/nodejs-tests.yml @@ -1,6 +1,6 @@ name: Node.js Tests -permissions: read-all +permissions: {} on: push: diff --git a/.github/workflows/playwright-tests.yml b/.github/workflows/playwright-tests.yml index 048c563f..3f5121b5 100644 --- a/.github/workflows/playwright-tests.yml +++ b/.github/workflows/playwright-tests.yml @@ -1,6 +1,6 @@ name: Playwright UI Tests -permissions: read-all +permissions: {} on: push: diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index b16a340d..fa1480ef 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -1,6 +1,6 @@ name: SonarCloud Analysis -permissions: read-all +permissions: {} on: push: diff --git a/SECURITY.md b/SECURITY.md index 73f89ff7..2a88989b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,7 @@ | Version | Supported | | ------- | ------------------ | -| latest | :white_check_mark: | +| main branch | :white_check_mark: | ## Reporting a Vulnerability From 4335ed9cad2baf63f5cfd67405997121569f9b03 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 27 Mar 2026 19:28:20 -0700 Subject: [PATCH 3/6] fix: add actions: write permission for cache and artifact jobs Jobs using actions/cache and actions/upload-artifact need actions: write permission at the job level to function correctly with deny-by-default workflow permissions. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/nodejs-tests.yml | 1 + .github/workflows/playwright-tests.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/nodejs-tests.yml b/.github/workflows/nodejs-tests.yml index 7fd8bcd3..cdf90ffe 100644 --- a/.github/workflows/nodejs-tests.yml +++ b/.github/workflows/nodejs-tests.yml @@ -14,6 +14,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + actions: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 diff --git a/.github/workflows/playwright-tests.yml b/.github/workflows/playwright-tests.yml index 3f5121b5..69fc83b2 100644 --- a/.github/workflows/playwright-tests.yml +++ b/.github/workflows/playwright-tests.yml @@ -14,6 +14,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + actions: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 From 86817caa98209893722c5738dbe8423a5ee23dab Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 28 Mar 2026 02:29:16 +0000 Subject: [PATCH 4/6] chore(ci): apply prettier/eslint auto-fixes --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 2a88989b..5e0255d0 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,8 +2,8 @@ ## Supported Versions -| Version | Supported | -| ------- | ------------------ | +| Version | Supported | +| ----------- | ------------------ | | main branch | :white_check_mark: | ## Reporting a Vulnerability From 62855250d6265469fb13ad35761ef0e0d541f874 Mon Sep 17 00:00:00 2001 From: DJ Date: Fri, 27 Mar 2026 20:19:40 -0700 Subject: [PATCH 5/6] chore: re-trigger CI checks From 586bcbd074553f556663b6ef86f0cc79f5f81fae Mon Sep 17 00:00:00 2001 From: DJ Date: Sat, 28 Mar 2026 06:17:41 -0700 Subject: [PATCH 6/6] fix: use claude_code_oauth_token instead of anthropic_api_key The action has separate inputs for API keys vs OAuth tokens. CLAUDE_CODE_OAUTH_TOKEN is an OAuth token, not an API key. --- .github/workflows/claude.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 1207d904..9d825cc6 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -33,4 +33,4 @@ jobs: - name: Run Claude Code uses: anthropics/claude-code-action@094bd24d575e7b30ac1576024817bf1a97c81262 # v1 with: - anthropic_api_key: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}