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
20 changes: 20 additions & 0 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: TariffShield CodeQL configuration

queries:
- uses: security-and-quality

paths:
- apps/api/src
- apps/web
- packages/sdk/src
- scripts

paths-ignore:
- "**/node_modules/**"
- "**/dist/**"
- "**/build/**"
- "**/.next/**"
- "**/coverage/**"
- "**/generated/**"
- "**/*.generated.ts"
- "**/*.generated.tsx"
91 changes: 77 additions & 14 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,94 @@ on:
pull_request:
branches: [main, master]
schedule:
- cron: '0 8 * * 1'
- cron: "0 8 * * 1"
workflow_dispatch:

permissions:
actions: read
contents: read
security-events: write

jobs:
analyze:
name: analyze
name: Analyze JavaScript and TypeScript
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read

strategy:
fail-fast: false
matrix:
language: [javascript-typescript]
timeout-minutes: 20

steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

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

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

- name: Perform CodeQL analysis
id: analyze
uses: github/codeql-action/analyze@v3
with:
category: /language:${{ matrix.language }}
category: "/language:javascript-typescript"
output: codeql-results

- name: Fail on blocking CodeQL findings
shell: bash
run: |
node <<'NODE'
const fs = require('fs');
const path = require('path');

const sarifDir = process.env.SARIF_DIR || 'codeql-results';
if (!fs.existsSync(sarifDir)) {
console.log(`No SARIF output directory found at ${sarifDir}; skipping severity gate.`);
process.exit(0);
}

const sarifFiles = fs.readdirSync(sarifDir)
.filter((file) => file.endsWith('.sarif'))
.map((file) => path.join(sarifDir, file));

let blocking = 0;
let warnings = 0;

for (const sarifFile of sarifFiles) {
const sarif = JSON.parse(fs.readFileSync(sarifFile, 'utf8'));
for (const run of sarif.runs || []) {
const rules = run.tool?.driver?.rules || [];
for (const result of run.results || []) {
const rule = Number.isInteger(result.ruleIndex)
? rules[result.ruleIndex]
: rules.find((candidate) => candidate.id === result.ruleId);
const securitySeverity = Number(rule?.properties?.['security-severity'] || 0);
if (result.level === 'error' || securitySeverity >= 9) {
blocking += 1;
} else if (result.level === 'warning') {
warnings += 1;
}
}
}
}

console.log(`CodeQL warnings: ${warnings}`);
console.log(`CodeQL blocking findings: ${blocking}`);

if (blocking > 0) {
console.error('CodeQL found error-level or critical-severity results. Review the code scanning alerts before merging.');
process.exit(1);
}
NODE
env:
SARIF_DIR: ${{ steps.analyze.outputs.sarif-output }}
32 changes: 32 additions & 0 deletions docs/security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Security scanning

TariffShield uses GitHub CodeQL to scan the JavaScript and TypeScript codebase for security and code-quality issues.

## CodeQL coverage

The CodeQL workflow runs for pull requests targeting `main`, on a weekly schedule at `03:00 UTC` every Monday, and on manual dispatch. It analyzes JavaScript and TypeScript with the `security-and-quality` query suite.

The scan covers the API, web app, SDK, and TypeScript scripts:

- `apps/api/src`
- `apps/web`
- `packages/sdk/src`
- `scripts`

Generated and build outputs are excluded through `.github/codeql/codeql-config.yml`, including `node_modules`, `dist`, `build`, `.next`, coverage output, and generated TypeScript files.

## Triage policy

CodeQL findings with `error` level or critical security severity are release blockers. The workflow reads the generated SARIF report after analysis and fails the pull request check when those blocking findings are present. Maintainers should also require the CodeQL check before merging protected branches and should fix or explicitly dismiss those alerts in GitHub code scanning before a pull request is merged.

Warning-level findings should be reviewed from the pull request annotations and the repository Security tab. They do not block merge by default, but they should be marked as fixed, false positive, or accepted risk during triage.

## Reviewing alerts

1. Open the repository Security tab.
2. Select Code scanning alerts.
3. Filter by tool `CodeQL` and sort by severity.
4. Assign each alert to the relevant owner.
5. Close the alert only after the fix is merged or after the maintainer records why the finding is not exploitable.

If a CodeQL alert identifies a credential exposure, authentication bypass, injection path, or unsafe cryptographic use, treat it as a security incident and follow `docs/security/incident-response-playbook.md`.