Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: "CodeQL config"

query-filters:
- exclude:
problem.severity:
- warning
- recommendation
- exclude:
id: go/log-injection
Comment on lines +3 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Top-level files:\n'
git ls-files | sed -n '1,120p'

printf '\nCodeQL config:\n'
cat -n .github/codeql/codeql-config.yml

printf '\nGo files in repository:\n'
git ls-files '*.go' | sed -n '1,200p'

printf '\nSearch for log-related sinks / suppressions:\n'
rg -n --hidden --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' 'go/log-injection|codeql|log-injection|logger|log\.' .

Repository: mattermost/mattermost-plugin-docs

Length of output: 2623


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Outline of Go files with logging-related names:\n'
ast-grep outline build/pluginctl/logs.go --view expanded || true
ast-grep outline server/main.go --view expanded || true
ast-grep outline server/plugin.go --view expanded || true
ast-grep outline server/api.go --view expanded || true
ast-grep outline server/job.go --view expanded || true

printf '\nLogging call sites:\n'
rg -n 'log\.|Printf|Println|Errorf|Infof|Warnf|logger|zap|slog' build/pluginctl server -g '*.go'

printf '\nRelevant snippets:\n'
sed -n '1,220p' build/pluginctl/logs.go
printf '\n--- server/main.go ---\n'
sed -n '1,220p' server/main.go
printf '\n--- server/plugin.go ---\n'
sed -n '1,260p' server/plugin.go
printf '\n--- server/api.go ---\n'
sed -n '1,240p' server/api.go
printf '\n--- server/job.go ---\n'
sed -n '1,240p' server/job.go

Repository: mattermost/mattermost-plugin-docs

Length of output: 13249


Remove the global go/log-injection exclusion in .github/codeql/codeql-config.yml:3-9. This disables CodeQL’s log-injection check across every Go file in the repo; keep it only with a documented repository-wide false-positive review, otherwise scope it to the specific finding.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/codeql/codeql-config.yml around lines 3 - 9, Remove the global
go/log-injection exclusion from the query-filters in the CodeQL configuration.
Keep the severity exclusions unchanged, and do not replace the removed rule
exclusion with another repository-wide suppression; scope any necessary
exception to the specific finding only.


paths-ignore:
- '**/*_test.go'
- '**/*.test.*'
203 changes: 199 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,204 @@ on:

permissions:
contents: read
id-token: write

jobs:
plugin-ci:
uses: mattermost/actions-workflows/.github/workflows/plugin-ci.yml@main
secrets: inherit
lint:
if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false

- name: ci/setup
uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be
with:
go-version-file: go.mod

- name: ci/lint
uses: mattermost/actions/plugin-ci/lint@0256d363493a1e6b9e361ea788c62a0a73bc00be

- name: ci/check-go-mod-tidy
run: |
go mod tidy
git diff --exit-code go.mod go.sum

- name: ci/check-manifest-drift
run: |
make apply
git diff --exit-code

- name: ci/check-i18n-drift
run: |
make i18n-extract
git diff --exit-code assets/i18n/en.json webapp/i18n/en.json

test:
if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }}
runs-on: ubuntu-latest
permissions:
contents: read
# The store and service tests require a real Postgres (PG14+ for the
# hierarchy CYCLE clause) and never skip; the default test DSN is
# postgres://mmuser:mostest@localhost:5432/mattermost_test.
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mostest
POSTGRES_DB: mattermost_test
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false

- name: ci/setup
uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be
with:
go-version-file: go.mod

- name: ci/test
uses: mattermost/actions/plugin-ci/test@0256d363493a1e6b9e361ea788c62a0a73bc00be

build:
if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false

- name: ci/setup
uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be
with:
go-version-file: go.mod

- name: ci/build
uses: mattermost/actions/plugin-ci/build@0256d363493a1e6b9e361ea788c62a0a73bc00be

coverage:
if: ${{ github.repository_owner == 'mattermost' || github.event_name != 'schedule' }}
runs-on: ubuntu-latest
permissions:
contents: read
services:
postgres:
image: postgres:14
env:
POSTGRES_USER: mmuser
POSTGRES_PASSWORD: mostest
POSTGRES_DB: mattermost_test
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false

- name: ci/setup
uses: mattermost/actions/plugin-ci/setup@0256d363493a1e6b9e361ea788c62a0a73bc00be
with:
go-version-file: go.mod

- name: ci/test-coverage
env:
TEST_DATABASE_POSTGRESQL_DSN: "postgres://mmuser:mostest@localhost/mattermost_test?sslmode=disable"
run: go test -coverprofile=server/coverage.txt ./server/...

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:
files: ./server/coverage.txt
disable_search: true

delivery:
if: ${{ github.repository_owner == 'mattermost' && github.event_name != 'schedule' && github.ref_name == 'master' }}
runs-on: ubuntu-latest
needs: [lint, test, build]
permissions:
contents: read
id-token: write
steps:
- name: ci/download-artifact
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: dist
path: dist

- name: ci/prepare-artifact
run: mv *.tar.gz ${GITHUB_REPOSITORY#*/}-ci.tar.gz
working-directory: dist

- name: ci/aws-configure
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
aws-region: us-east-1
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_RELEASE }}:role/mattermost-release-plugin-store-role

- name: ci/artifact-upload
shell: bash
run: |
aws s3 cp *.tar.gz s3://mattermost-plugins-delivery/ci/ --acl public-read --cache-control no-cache
working-directory: dist

release:
if: ${{ startsWith(github.ref, 'refs/tags/v') && github.repository_owner == 'mattermost' }}
runs-on: ubuntu-latest
needs: [lint, test, build]
permissions:
contents: read
id-token: write
steps:
- name: ci/download-artifact
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: dist
path: dist

- name: ci/prepare-artifact
env:
REF_NAME: ${{ github.ref_name }}
run: mv *.tar.gz ${GITHUB_REPOSITORY#*/}-${REF_NAME}.tar.gz
working-directory: dist

- name: ci/aws-configure
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
aws-region: us-east-1
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID_RELEASE }}:role/mattermost-release-plugin-store-role

- name: ci/artifact-upload
shell: bash
run: |
aws s3 cp *.tar.gz s3://mattermost-plugins-delivery/release/ --acl public-read --cache-control no-cache
working-directory: dist
41 changes: 41 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: "CodeQL"

on:
push:
branches: [master, 'release-*']
pull_request:
branches: [master, 'release-*']
schedule:
- cron: '30 4 * * 0'

permissions:
contents: read

jobs:
analyze:
permissions:
security-events: write
name: Analyze
Comment on lines +16 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== .github/workflows/codeql-analysis.yml (outline) ==\n'
ast-grep outline .github/workflows/codeql-analysis.yml --view expanded || true

printf '\n== .github/workflows/codeql-analysis.yml (numbered, first 240 lines) ==\n'
cat -n .github/workflows/codeql-analysis.yml | sed -n '1,240p'

printf '\n== Search for permissions blocks in workflow files ==\n'
rg -n --glob '.github/workflows/*.yml' --glob '.github/workflows/*.yaml' 'permissions:|contents: read|security-events: write|actions/checkout|github/codeql-action' .github/workflows

Repository: mattermost/mattermost-plugin-docs

Length of output: 3583


🌐 Web query:

GitHub Actions job-level permissions override workflow-level permissions unspecified set to none contents read actions/checkout

💡 Result:

In GitHub Actions, when you define the permissions key at the job level, it completely overrides any permissions defined at the workflow level [1][2]. The permissions do not merge; the job-level configuration becomes the definitive set of permissions for that specific job [2]. When you explicitly use the permissions key—at either the workflow or job level—any permissions that you do not specify are automatically set to none (no access), with the sole exception of the metadata scope, which always retains read access [1][3][4]. For the actions/checkout action, the recommended configuration to ensure it can successfully check out your repository is to explicitly grant read access to the contents scope [5][6][7]: permissions: contents: read If you have a workflow-level permissions block but need to override it for a specific job while maintaining the actions/checkout functionality, you must include contents: read in that job's permissions block, as it will otherwise be reset to none [1][2].

Citations:


Add contents: read to the job permissions.
jobs.analyze.permissions replaces the workflow-level block, so actions/checkout loses repo read access here and can fail before CodeQL starts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/codeql-analysis.yml around lines 16 - 18, Update the
analyze job’s permissions block to include contents: read alongside
security-events: write, ensuring actions/checkout retains repository read access
while preserving CodeQL’s security-events permission.

runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
language: ['go', 'javascript']

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Comment on lines +27 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Disable checkout credential persistence.

actions/checkout stores GITHUB_TOKEN in the local Git configuration by default. Later build or analysis tooling could expose that credential through an artefact.

       - name: Checkout repository
         uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 27-28: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/codeql-analysis.yml around lines 27 - 28, Update the
actions/checkout step in the CodeQL workflow to disable credential persistence
by setting its persist-credentials option to false, while preserving the pinned
action version and existing checkout behavior.

Source: Linters/SAST tools


- name: Initialize CodeQL
uses: github/codeql-action/init@v3.28.9
with:
languages: ${{ matrix.language }}
debug: false
config-file: ./.github/codeql/codeql-config.yml

- name: Autobuild
uses: github/codeql-action/autobuild@v3.28.9

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3.28.9
32 changes: 32 additions & 0 deletions .github/workflows/pr-test-analysis-override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: PR Test Analysis Override

on:
issue_comment:
types: [created]

concurrency:
group: test-analyzer-${{ github.event.issue.number }}
cancel-in-progress: false

jobs:
override:
permissions:
statuses: write
pull-requests: read
contents: read
issues: write
if: >-
github.repository == 'mattermost/mattermost-plugin-docs' &&
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/test-analysis-override') &&
contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)
uses: mattermost/mattermost-test-automation-toolkit/.github/workflows/pr-test-analysis-override.yml@main
with:
pr_number: ${{ github.event.issue.number }}
target_repo: mattermost/mattermost-plugin-docs
comment_body: ${{ github.event.comment.body }}
comment_id: ${{ github.event.comment.id }}
sender: ${{ github.event.comment.user.login }}
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL_TEST_PR_ANALYSIS_HUB }}
46 changes: 46 additions & 0 deletions .github/workflows/pr-test-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: PR Test Analysis

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches:
- master
- 'release-*'
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to analyze'
required: true
type: number
claude_model:
description: 'Claude model to use (default: claude-sonnet-4-6)'
required: false
type: string

concurrency:
group: test-analyzer-${{ github.event.pull_request.number || inputs.pr_number }}
cancel-in-progress: true

jobs:
analyze:
permissions:
contents: read
pull-requests: write
statuses: write
id-token: write
# pull_request: skip drafts and forks (drafts are not ready for analysis;
# fork runs do not receive this repo's Actions secrets).
# workflow_dispatch: always allowed — runs in this repo with secrets, so you can pass a fork PR number manually.
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name == 'mattermost/mattermost-plugin-docs')
uses: mattermost/mattermost-test-automation-toolkit/.github/workflows/pr-test-analysis.yml@main

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in .github/workflows/pr-test-analysis.yml .github/workflows/codeql-analysis.yml .github/workflows/pr-test-analysis-override.yml; do
  echo "===== $f ====="
  nl -ba "$f" | sed -n '1,120p'
  echo
done

Repository: mattermost/mattermost-plugin-docs

Length of output: 262


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in .github/workflows/pr-test-analysis.yml .github/workflows/codeql-analysis.yml .github/workflows/pr-test-analysis-override.yml; do
  echo "===== $f ====="
  sed -n '1,140p' "$f"
  echo
done

Repository: mattermost/mattermost-plugin-docs

Length of output: 3976


Pin reusable workflows and CodeQL actions to commit SHAs.

These references still use mutable tags/branches while running with repository permissions and secrets:

  • .github/workflows/pr-test-analysis.yml: mattermost/mattermost-test-automation-toolkit/.github/workflows/pr-test-analysis.yml@main
  • .github/workflows/codeql-analysis.yml: github/codeql-action/{init,autobuild,analyze}@v3.28.9``
  • .github/workflows/pr-test-analysis-override.yml: mattermost/mattermost-test-automation-toolkit/.github/workflows/pr-test-analysis-override.yml@main
📍 Affects 3 files
  • .github/workflows/pr-test-analysis.yml#L38-L38 (this comment)
  • .github/workflows/codeql-analysis.yml#L31-L41
  • .github/workflows/pr-test-analysis-override.yml#L23-L23
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/pr-test-analysis.yml at line 38, Pin all referenced
reusable workflows and CodeQL actions to immutable commit SHAs instead of the
mutable main and v3.28.9 references: update
.github/workflows/pr-test-analysis.yml lines 38-38,
.github/workflows/codeql-analysis.yml lines 31-41 for init, autobuild, and
analyze, and .github/workflows/pr-test-analysis-override.yml lines 23-23.
Preserve the existing workflow and action versions while replacing each tag or
branch with its corresponding verified commit SHA.

with:
pr_number: ${{ github.event.pull_request.number || inputs.pr_number }}
target_repo: mattermost/mattermost-plugin-docs
claude_model: ${{ inputs.claude_model || vars.CLAUDE_MODEL || 'claude-sonnet-4-6' }}
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL_TEST_PR_ANALYSIS_HUB }}