Skip to content
Open
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
41 changes: 41 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# CodeQL: static analysis for the whole tree (backend/ + frontend/).
#
# Both halves are interpreted TypeScript, so CodeQL's `build-mode: none`
# extracts them straight from source — no npm ci, no build step, and no
# autobuild guessing at the two-package layout. One analyze job covers
# backend and frontend together. The weekly cron re-runs analysis on an
# otherwise-quiet tree so newly shipped CodeQL queries still get applied.
# Findings land in the Security tab (code scanning), not as CI noise.
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Mondays 04:30 UTC.
- cron: "30 4 * * 1"

permissions:
contents: read

jobs:
analyze:
name: Analyze (javascript-typescript)
runs-on: ubuntu-latest
permissions:
contents: read
# Required to upload results to code scanning.
security-events: write
steps:
- uses: actions/checkout@v4

- uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
build-mode: none

- uses: github/codeql-action/analyze@v3
with:
category: "/language:javascript-typescript"
45 changes: 45 additions & 0 deletions .github/workflows/gitleaks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Secret scan: gitleaks over the full git history.
#
# Deliberately NOT gitleaks/gitleaks-action — that action requires a paid
# GITLEAKS_LICENSE for organization-owned repos. The scanner itself is a
# single MIT-licensed Go binary, so this downloads a pinned release and
# verifies its sha256 (from the upstream release checksums file) before
# running it. fetch-depth: 0 so every commit is scanned, not just the PR
# head — a secret that was committed and later deleted is still leaked.
# Known fake secrets (test fixtures, docs placeholders) are allowlisted
# in .gitleaks.toml at the repo root; anything new fails the run.
name: Secret scan

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
gitleaks:
name: gitleaks (full history)
runs-on: ubuntu-latest
env:
GITLEAKS_VERSION: 8.30.1
# sha256 of gitleaks_8.30.1_linux_x64.tar.gz, from
# gitleaks_8.30.1_checksums.txt on the upstream release.
GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb
steps:
- uses: actions/checkout@v4
with:
# Full history — gitleaks scans commits, not the working tree.
fetch-depth: 0

- name: Download and verify gitleaks
run: |
curl -sSfL -o gitleaks.tar.gz \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
echo "${GITLEAKS_SHA256} gitleaks.tar.gz" | sha256sum -c -
tar -xzf gitleaks.tar.gz gitleaks

- name: Scan full history
run: ./gitleaks detect --no-banner --redact
43 changes: 43 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# OpenSSF Scorecard: automated checks of this repo's own security posture
# (branch protection, token permissions, pinned dependencies, ...).
#
# Runs on pushes to main plus a weekly cron — Scorecard rates the repo, not
# a PR's diff, so there is no pull_request trigger. publish_results: true
# sends the score to the OpenSSF public API (which enables the README badge
# and is what other tools query); that upload is signed via OIDC, hence
# id-token: write. Results also land in the Security tab as SARIF.
name: Scorecard

on:
push:
branches: [main]
schedule:
# Mondays 05:30 UTC.
- cron: "30 5 * * 1"

permissions: read-all

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to sign the published results (OIDC).
id-token: write
# Needed to upload SARIF to code scanning.
security-events: write
contents: read
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- uses: ossf/scorecard-action@v2.4.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true

- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
34 changes: 34 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# gitleaks config for the Secret scan workflow (.github/workflows/gitleaks.yml).
#
# Default rules apply everywhere; the allowlist below covers paths whose
# "secrets" are deliberate fakes, verified by hand before listing:
# test fixtures (sk-proj-abc123..., minted throwaway JWTs, the public
# supabase-demo anon key) and docs examples (mike_sk_... placeholders).
# Several of the paths only exist in old commits from before the repo was
# restructured (apps/, sdks/, word-addin/) — the scan covers full history,
# so history-only paths still need allowlisting. Keep entries narrow:
# allowlist a specific file or test directory, never a whole source tree.

[extend]
useDefault = true

[[allowlists]]
description = "Unit-test fixtures: fake API keys and locally minted JWTs"
paths = [
'''(^|/)src/lib/__tests__/safeError\.test\.ts$''',
'''(^|/)src/lib/__tests__/secretGuard\.test\.ts$''',
'''(^|/)src/lib/__tests__/webhookSignature\.test\.ts$''',
]

[[allowlists]]
description = "E2E fixtures: mocked login tokens (history includes pre-restructure apps/word-addin/ path)"
paths = [
'''(^|/)word-addin/e2e/auth\.spec\.ts$''',
]

[[allowlists]]
description = "History-only paths: Python SDK tests and developer-platform docs with mike_sk_... placeholders"
paths = [
'''^sdks/python/tests/''',
'''^docs/developer-platform\.md$''',
]
32 changes: 32 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Security Policy

## Supported versions

There are no tagged releases yet; the only supported version is the tip of
`main`. If you are self-hosting, please update to the latest `main` before
reporting — the issue may already be fixed.

## Reporting a vulnerability

Please report vulnerabilities privately through GitHub:

**Security tab → Report a vulnerability** on this repository
(GitHub's private vulnerability reporting).

Please do not open a public issue for anything security-sensitive.

This project has a solo maintainer. You can expect an acknowledgment within
7 days; fixes are prioritized by severity after that.

## Scope

- Mike is **self-hosted** — there is no hosted service operated by this
repository to test against. Reports about the code, default configuration,
and deployment guidance in this repo are all in scope. Findings that only
apply to a specific third-party deployment should go to whoever operates it.
- Mike is an **LLM legal product**, so LLM-specific reports are explicitly
welcome: prompt injection (including via uploaded documents), getting the
model to ignore its guardrails, leaking another user's data or system
prompts through model output, and similar.
- Secrets accidentally committed to this repository's history are also worth
a private report, even though CI runs a secret scanner.
Loading