Skip to content

Commit 70d7f67

Browse files
authored
Merge pull request #14 from mnaimfaizy/security/dependency-supply-chain-hardening
chore: harden dependency supply chain
2 parents 79c9f1e + 925b616 commit 70d7f67

17 files changed

Lines changed: 1010 additions & 443 deletions

File tree

.github/CODEOWNERS

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Default owner
2+
3+
* @mnaimfaizy
4+
5+
# Security-sensitive files and directories
6+
7+
/.github/workflows/ @mnaimfaizy
8+
/.github/instructions/ @mnaimfaizy
9+
/package.json @mnaimfaizy
10+
/package-lock.json @mnaimfaizy
11+
/.npmrc @mnaimfaizy
12+
/SECURITY.md @mnaimfaizy
13+
/docs/SECURITY/ @mnaimfaizy

.github/copilot-instructions.md

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@
1515
- **Build**: `npm run build` (TypeScript + Vite)
1616
- **Test**: `npm test` (watch mode) or `npm run test:run` (CI mode)
1717

18+
## 🔐 Dependency and CI Security
19+
20+
See `docs/SECURITY/Dependency-Supply-Chain-Security-Plan.md` for the current repository policy and remediation plan.
21+
22+
- Treat all changes to `package.json`, `package-lock.json`, `.npmrc`, and `.github/workflows/**` as security-sensitive.
23+
- This repository is npm-only. Do not switch to Yarn or pnpm unless the repo is explicitly migrated and the security policy is updated.
24+
- Prefer existing platform APIs or already-approved packages before adding a new dependency.
25+
- Use exact versions for direct npm dependencies. Avoid `^` and `~`, and keep `.npmrc` configured with `save-exact=true`.
26+
- For existing lockfiles, use `npm ci`. For disposable review flows that only need metadata and audit signals, prefer `npm ci --ignore-scripts` first.
27+
- In CI, use only `npm ci` and verify that `package-lock.json` stays unchanged after install.
28+
- Review lockfile diffs for unexpected transitive packages and any new install-time script behavior before accepting dependency updates.
29+
- Keep `package-lock.json` committed and frozen in CI.
30+
- Do not recommend a blanket `ignore-scripts=true` change for normal local installs in this repo without a migration plan because the current toolchain depends on reviewed install-script packages such as `esbuild` and `@tailwindcss/oxide`.
31+
- Preserve the `package.json` overrides that block compromised Axios releases `1.14.1` and `0.30.4`.
32+
- For GitHub Actions, pin third-party actions to full commit SHAs, set explicit minimal `permissions`, and prefer OIDC over long-lived secrets whenever external systems are involved.
33+
1834
### **10 Learning Modules**
1935

2036
1. JavaScript Engine - V8 internals and execution flow
@@ -549,14 +565,14 @@ analyticsService.trackEvent('feature_used', { feature: 'visualization' });
549565
import { env } from './core/config/env';
550566

551567
// Available environment variables
552-
env.enableAnalytics // boolean
553-
env.googleAnalyticsId // string | undefined
554-
env.isDevelopment // boolean
555-
env.isProduction // boolean
568+
env.enableAnalytics; // boolean
569+
env.googleAnalyticsId; // string | undefined
570+
env.isDevelopment; // boolean
571+
env.isProduction; // boolean
556572

557573
// Access in components
558-
import.meta.env.DEV // Vite development mode
559-
import.meta.env.PROD // Vite production mode
574+
import.meta.env.DEV; // Vite development mode
575+
import.meta.env.PROD; // Vite production mode
560576
```
561577
562578
## 📚 Module-Specific Guidelines
@@ -638,6 +654,7 @@ The application includes these complete learning modules:
638654
### **ESLint Configuration**
639655
640656
The project uses:
657+
641658
- `@typescript-eslint` for TypeScript-specific rules
642659
- `eslint-plugin-react` and `eslint-plugin-react-hooks` for React best practices
643660
- `eslint-plugin-import` for import organization
@@ -789,13 +806,15 @@ describe('useMyHook', () => {
789806
```
790807

791808
**Test File Organization:**
809+
792810
- **Unit Tests**: Test utility functions and hooks
793811
- **Component Tests**: Verify rendering and interactions
794812
- **Integration Tests**: Test feature workflows
795813
- Place test files next to the code they test: `Component.test.tsx`
796814
- Use `src/test/` for shared test utilities and setup
797815

798816
**Existing Test Examples:**
817+
799818
- `src/shared/hooks/useDebounce.test.ts`
800819
- `src/shared/hooks/useThrottle.test.ts`
801820
- `src/shared/components/feedback/ErrorBoundary/ErrorBoundary.test.tsx`
@@ -808,12 +827,14 @@ describe('useMyHook', () => {
808827
Complete step-by-step guide:
809828

810829
1. **Create Feature Directory Structure**:
830+
811831
```bash
812832
mkdir -p src/features/[module]/components/{sections,visualizations/2d}
813833
touch src/features/[module]/index.tsx
814834
```
815835

816836
2. **Add Type Definitions** (if needed):
837+
817838
```typescript
818839
// src/types/[module].ts
819840
export interface ModuleState {
@@ -822,6 +843,7 @@ export interface ModuleState {
822843
```
823844

824845
3. **Add Theme Colors**:
846+
825847
```typescript
826848
// src/utils/theme.ts - Add to colors object
827849
[module]: {
@@ -835,6 +857,7 @@ export interface ModuleState {
835857
```
836858

837859
4. **Create Main Page Component**:
860+
838861
```typescript
839862
// src/features/[module]/index.tsx
840863
import React from 'react';
@@ -854,6 +877,7 @@ export default ModulePage;
854877
```
855878

856879
5. **Add Lazy Route in App.tsx**:
880+
857881
```typescript
858882
// Import
859883
const NewModulePage = lazy(() => import('./features/newmodule'));
@@ -875,6 +899,7 @@ const NewModulePage = lazy(() => import('./features/newmodule'));
875899
### **Creating Interactive Visualizations**
876900

877901
1. **Start with SVG Structure**:
902+
878903
```typescript
879904
const MyViz: React.FC = () => {
880905
return (
@@ -888,23 +913,26 @@ const MyViz: React.FC = () => {
888913
```
889914

890915
2. **Add State Management**:
916+
891917
```typescript
892918
const [step, setStep] = useState(0);
893919
const [isPlaying, setIsPlaying] = useState(false);
894920
```
895921

896922
3. **Implement Animation Logic**:
923+
897924
```typescript
898925
useEffect(() => {
899926
if (!isPlaying) return;
900927
const interval = setInterval(() => {
901-
setStep(prev => (prev + 1) % totalSteps);
928+
setStep((prev) => (prev + 1) % totalSteps);
902929
}, 1000);
903930
return () => clearInterval(interval);
904931
}, [isPlaying]);
905932
```
906933

907934
4. **Add Demo Controls**:
935+
908936
```typescript
909937
<div className="flex gap-2 mt-4">
910938
<button onClick={() => setIsPlaying(!isPlaying)}>
@@ -915,6 +943,7 @@ useEffect(() => {
915943
```
916944

917945
5. **Include Educational Tooltips**:
946+
918947
```typescript
919948
<title>Explanation of what this element represents</title>
920949
```

.github/dependabot.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: npm
4+
directory: /
5+
schedule:
6+
interval: daily
7+
time: '06:00'
8+
timezone: UTC
9+
open-pull-requests-limit: 5
10+
labels:
11+
- dependencies
12+
- security
13+
commit-message:
14+
prefix: deps
15+
allow:
16+
- dependency-type: direct
17+
- dependency-type: indirect
18+
groups:
19+
npm-production:
20+
dependency-type: production
21+
update-types:
22+
- minor
23+
- patch
24+
npm-development:
25+
dependency-type: development
26+
update-types:
27+
- minor
28+
- patch
29+
30+
- package-ecosystem: github-actions
31+
directory: /
32+
schedule:
33+
interval: weekly
34+
time: '06:30'
35+
timezone: UTC
36+
open-pull-requests-limit: 5
37+
labels:
38+
- dependencies
39+
- security
40+
- github-actions
41+
commit-message:
42+
prefix: ci
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
description: 'Use when changing npm dependencies, package-lock.json, .npmrc, or GitHub Actions workflows. Covers supply-chain security review, exact version pinning, install-script review, dependency incident response, and CI hardening for compromised packages such as Axios.'
3+
name: 'Dependency and Workflow Security'
4+
applyTo:
5+
- package.json
6+
- package-lock.json
7+
- .npmrc
8+
- .github/workflows/**
9+
- .github/dependabot.yml
10+
- docs/SECURITY/**
11+
---
12+
13+
# Dependency and Workflow Security
14+
15+
- Treat any dependency, lockfile, registry, or workflow change as security-sensitive.
16+
- This repository is npm-only. Do not introduce Yarn or pnpm for this repo unless the package manager migration is explicitly approved and the security policy is updated.
17+
- Prefer an existing dependency or a platform-native API before introducing a new package.
18+
- For this application repository, use exact versions for direct dependencies. Avoid `^` and `~` in `package.json`, and keep `.npmrc` configured with `save-exact=true`.
19+
- For existing lockfiles, use `npm ci`. For dependency review in disposable environments or dedicated CI security checks, prefer `npm ci --ignore-scripts` first.
20+
- Do not use `npm install`, `npm update`, or `npm audit fix` in CI. CI must use `npm ci` only and fail if `package-lock.json` changes.
21+
- If Yarn or pnpm are ever introduced elsewhere, require their immutable or frozen lockfile mode and disable lifecycle scripts unless an explicit allowlist process is in place.
22+
- Before adding or updating a package, check the current advisories, the latest patched version, maintainer health, recent publish activity, and whether the package adds install-time scripts, native binaries, or unusually large transitive churn.
23+
- Review `package-lock.json` diffs for unexpected new packages, registry changes, or install-time script packages.
24+
- Popularity is not a trust signal. Treat high-usage packages such as Axios as high-impact dependencies that still require full review.
25+
- Do not enable a blanket `ignore-scripts=true` policy for normal local installs in this repo without a migration plan because the current toolchain depends on reviewed install-script packages such as `esbuild` and `@tailwindcss/oxide`.
26+
- Keep `package-lock.json` committed. Prefer `npm ci` in CI and reproducible installs over ad hoc `npm install` in automation.
27+
- Keep Axios guardrails in `package.json` overrides so the compromised releases `1.14.1` and `0.30.4` cannot be selected if Axios is introduced directly or transitively.
28+
- When editing GitHub Actions workflows, pin third-party actions to full commit SHAs, set explicit minimal `permissions`, and prefer OIDC over long-lived secrets.
29+
- Require human review for workflow files, dependency manifests, and lockfiles.
30+
- If a package compromise is reported, immediately identify direct and transitive usage, block the affected versions, clear caches, rotate potentially exposed secrets, and record the outcome in `docs/SECURITY/Dependency-Supply-Chain-Security-Plan.md`.

0 commit comments

Comments
 (0)