From d03b6b36cdadcd89dc98a855eaaf8c163e24d9a2 Mon Sep 17 00:00:00 2001 From: Jeymz Simmons Date: Sun, 31 Aug 2025 21:14:12 -0400 Subject: [PATCH 1/2] feat: add Dockerfile, GitHub Actions lint workflow, and enhance server configuration for SSL support --- .dockerignore | 13 ++ .env.example | 3 + .../workflows/{markdownlint.yml => lint.yml} | 6 +- .gitignore | 3 +- Dockerfile | 24 +++ README.md | 168 +++++++++--------- images/example-chat_prompt_files.png | Bin 0 -> 39161 bytes images/example-run_prompt.png | Bin 0 -> 26732 bytes server.js | 86 ++++++--- src/core/config.js | 3 + src/express_app.js | 2 + src/mcp_server.js | 5 +- 12 files changed, 199 insertions(+), 114 deletions(-) create mode 100644 .dockerignore rename .github/workflows/{markdownlint.yml => lint.yml} (82%) create mode 100644 Dockerfile create mode 100644 images/example-chat_prompt_files.png create mode 100644 images/example-run_prompt.png diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cea5566 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.env +.git +.github +.gitignore +*.pfx +node_modules +tests +Dockerfile +renovate.json +eslint.config.mjs +copilot-instructions.node_modules.gitlab-ci.yml +.markdownlint.yml +.markdownlintignore \ No newline at end of file diff --git a/.env.example b/.env.example index 1c2d1a0..7b89ef8 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,8 @@ server.port=8080 server.hostname=localhost +server.ssl=false +server.ssl.pfx=localhost.pfx +server.ssl.pfxPassphrase='PFX_PASSPHRASE' logger.transports.console.enabled=true logger.transports.console.level=info logger.transports.amqp.enabled=false diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/lint.yml similarity index 82% rename from .github/workflows/markdownlint.yml rename to .github/workflows/lint.yml index f1803b0..e0f2876 100644 --- a/.github/workflows/markdownlint.yml +++ b/.github/workflows/lint.yml @@ -1,4 +1,4 @@ -name: Markdown Lint +name: Lint on: pull_request: @@ -21,8 +21,8 @@ jobs: - name: Clear npm cache run: npm cache clean --force - - name: Install markdownlint-cli + - name: Install dependencies run: npm install - - name: Run markdownlint + - name: Run lint run: npm run lint \ No newline at end of file diff --git a/.gitignore b/.gitignore index 13dfa36..7405ca3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env -node_modules/ \ No newline at end of file +node_modules/ +*.pfx \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dd92979 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM node:lts-bullseye-slim + +ENV NODE_ENV=production +ENV server.port=8080 +ENV server.hostname=localhost +ENV logger.transports.console.enabled=true +ENV logger.transports.console.level=info + +RUN apt-get update +RUN apt-get install -y --no-install-recommends dumb-init + +EXPOSE 8080 + +WORKDIR /usr/src/app + +COPY --chown=node:node . . + +RUN npm install --omit=dev + +USER node + +HEALTHCHECK CMD curl http://localhost:8080/health || exit 1 + +ENTRYPOINT ["dumb-init", "node", "server.js"] \ No newline at end of file diff --git a/README.md b/README.md index 8601f12..fd15d6e 100644 --- a/README.md +++ b/README.md @@ -2,53 +2,37 @@ [![Verified on MseeP](https://mseep.ai/badge.svg)](https://mseep.ai/app/1a935343-666d-457a-b210-2e0d27e9ef81) -A customizable `.github/copilot-instructions.md` file that guides **GitHub Copilot** toward **secure coding defaults** across **Java, Node.js, and C#**. +A comprehensive toolkit to guide **GitHub Copilot** toward **secure coding practices**. This project includes customizable instructions and security-focused prompts to help development teams identify and mitigate security risks effectively. -Designed for security-conscious development teams, this config helps Copilot suggest safer code patterns, avoid common vulnerabilities, and reinforce good practices โ€” without slowing down your workflow. +Designed for security-conscious teams, this configuration ensures Copilot suggests safer code patterns, avoids common vulnerabilities, and reinforces best practices โ€” all without disrupting your workflow. --- ## ๐Ÿ” What's Inside -This Copilot configuration includes: +This project offers: -- **Secure-by-default guidance** for all languages (input validation, secret handling, safe logging) +- **Secure-by-default guidance** for all languages (e.g., input validation, secret handling, safe logging). - **Language-specific secure patterns**: - โ˜• Java - ๐ŸŸฉ Node.js - ๐ŸŸฆ C# - ๐Ÿ Python -- **"Do Not Suggest" lists** to block risky Copilot completions (e.g. `eval`, inline SQL, insecure deserialization) -- **AI hallucination protections** (package spoofing, non-existent APIs, misinformation risks) -- **Mentorship-style dev tips** to help newer engineers build safe habits over time -- **An MCP server** to make using these prompts in other projects easier +- **"Do Not Suggest" lists** to block risky Copilot completions (e.g., `eval`, inline SQL, insecure deserialization). +- **AI hallucination protections** to prevent package spoofing, non-existent APIs, and misinformation risks. +- **Mentorship-style tips** to help newer engineers build secure coding habits. +- **An MCP server** for seamless integration of these prompts into other projects. --- -## ๐Ÿง  Using Prompts for Code Reviews (Copilot Chat) - -If your organization has [Copilot Prompt Customization](https://code.visualstudio.com/docs/copilot/copilot-customization#_prompt-files-experimental) enabled, you can guide Copilot Chat to run secure code audits using the included prompt files. - -1. Open any file in your IDE (e.g., `tests/secret-hardcode.js`) -2. Open the Copilot Chat sidebar -3. Type: - -```bash -@prompt .github/prompts/check-for-secrets.md -``` - -Copilot will scan the file using the selected prompt and return flagged issues, reasoning, and remediation tips. - -> โ„น๏ธ Note: If your org disables `chat.promptFiles`, you can manually paste the prompt contents into Copilot Chat or use them in PRs, checklists, and reviews. - ## ๐Ÿ—‚๏ธ Prompt Catalogue -Explore the available prompt files and their intended purpose: +Explore the available prompts and their intended use cases: | Prompt | Description | Intended Use | | --- | --- | --- | | [assess-logging.prompt.md](prompts/assess-logging.prompt.md) | Identify unsafe logging and exposure of sensitive data. | Audit log output for leaks and recommend safer patterns. | -| [business-logic-review.prompt.md](prompts/business-logic-review.prompt.md) | Analyze overall business logic flow and decision making. | Map application behaviour and critique critical logic paths. | +| [business-logic-review.prompt.md](prompts/business-logic-review.prompt.md) | Analyze overall business logic flow and decision making. | Map application behavior and critique critical logic paths. | | [check-access-controls.prompt.md](prompts/check-access-controls.prompt.md) | Audit authorization and access control weaknesses. | Ensure RBAC/ABAC enforcement and consistent permission checks. | | [check-for-secrets.prompt.md](prompts/check-for-secrets.prompt.md) | Detect hardcoded secrets and credentials. | Locate embedded keys or tokens and suggest secure storage. | | [check-for-unvalidated-genai-acceptances.prompt.md](prompts/check-for-unvalidated-genai-acceptances.prompt.md) | Find unvalidated AI-generated code or hallucinated assets. | Verify that AI suggestions are real, tested, and documented. | @@ -57,30 +41,11 @@ Explore the available prompt files and their intended purpose: | [secure-code-review.prompt.md](prompts/secure-code-review.prompt.md) | Perform a comprehensive security review of the codebase. | Conduct an end-to-end audit for security issues. | | [validate-input-handling.prompt.md](prompts/validate-input-handling.prompt.md) | Check for missing or unsafe input validation. | Evaluate request handling for validation and sanitization gaps. | -## ๐Ÿงช Testing the Prompts - -The `tests/` folder contains small, focused files designed to trigger specific security prompts: - -| File | Targets | -|--------------------------------|-----------------------------------| -| `secret-hardcode.js` | check-for-secrets.md | -| `unvalidated-input.java` | validate-input-handling.md | -| `insecure-api.cs` | scan-for-insecure-apis.md | -| `logs-sensitive-data.go` | assess-logging.md | -| `weak-auth-flow.ts` | review-auth-flows.md | -| `overtrusted-genai-snippet.js` | unvalidated-genai-acceptances.md | - -To run a test: - -1. Open a file in `tests/` -2. Run the related prompt in Copilot Chat -3. Review and refine based on Copilotโ€™s feedback - --- ## ๐Ÿ“ฆ How to Use in a Real Project -### Static Files +### Leveraging Static Files 1. Copy the `copilot-instructions.md` file into your repo under: `.github/copilot-instructions.md` @@ -88,52 +53,81 @@ To run a test: 2. Drop the prompts you want into: `.github/prompts/` -3. Use prompt-driven reviews in Copilot Chat during coding, PRs, or audits +3. Open the prompt you wish to run within your IDE -### Leveraging the included MCP Server +4. Click the `Run Prompt` button to the top-right of the file -The MCP server is designed to simplify the integration of secure coding prompts into your development workflow. Follow these steps to ensure a smooth experience: + ![Run Prompt Button](images/example-run_prompt.png) -#### 1. Setting Up the MCP Server + > โ„น๏ธ **Note**: If you don't see the run prompt button; check to make sure the `Chat: Prompt Files` functionality is enabled in your settings + > ![Chat Prompt Files Setting](images/example-chat_prompt_files.png) -```bash -npm install -cp .env.example .env -npm start -``` +### Leveraging the MCP Server -- **`npm install`**: Installs all required dependencies. -- **`cp .env.example .env`**: Creates a `.env` file for configuration. Update it with your specific settings. -- **`npm start`**: Launches the MCP server on `http://localhost:8080/mcp`. +The MCP server simplifies the integration of secure coding prompts into your workflow. Follow these steps: -#### Environment Variables +#### Run MCP from source -The MCP server reads configuration from a `.env` file. The following variables can be set: +1. Install dependencies -| Variable | Description | Default | Required | -| --- | --- | --- | --- | -| `server.port` | Port the MCP server listens on. | `8080` | Optional | -| `server.hostname` | Hostname the server binds to. | `localhost` | Optional | -| `logger.transports.console.enabled` | Enable console logging output. | `false` | Optional | -| `logger.transports.console.level` | Log level for console output. | `info` | Optional | -| `logger.transports.amqp.enabled` | Enable AMQP-based logging. | `false` | Optional | -| `logger.transports.amqp.level` | Log level for AMQP transport. | `http` | Optional | -| `logger.transports.amqp.hostname` | Hostname of the AMQP broker. | `localhost` | Optional | -| `logger.transports.amqp.port` | Port for the AMQP broker. | `5672` | Optional | -| `logger.transports.amqp.username` | Username for AMQP authentication. | `guest` | Optional | -| `logger.transports.amqp.password` | Password for AMQP authentication. | `guest` | Optional | -| `logger.transports.amqp.exchange` | Exchange name used for AMQP logging. | `logs` | Optional | -| `logger.transports.amqp.vhost` | Virtual host for AMQP logging. | `/logs` | Optional | -| `logger.transports.amqp.heartbeat` | Heartbeat interval in seconds. | `60` | Optional | -| `logger.transports.amqp.locale` | Locale for the AMQP connection. | `en_US` | Optional | -| `logger.transports.amqp.type` | AMQP exchange type. | `direct` | Optional | -| `logger.transports.amqp.durable` | Whether the AMQP exchange is durable. | `false` | Optional | + ```bash + npm install + ``` -All variables are optional; the server runs with these defaults. Set them in `.env` to customize behavior or enable logging transports. +2. Setup environment -#### 2. Configuring VSCode for MCP + ```bash + cp .env.example .env + ``` + + > The MCP server reads configuration from a `.env` file. Customize the following variables as needed: + > + > | Variable | Description | Default | + > | --- | --- | --- | + > | `server.port` | Port the MCP server listens on. | `8080` | + > | `server.ssl`| Whether to use ssl for express server | `false` | + > | `server.ssl.pfx` | Path to pfx file | `localhost.pfx` | + > | `server.ssl.pfx.passphrase` | Passphrase for pfx file | `PFX_PASSPHRASE` | + > | `server.hostname` | Hostname the server binds to. | `localhost` | + > | `logger.transports.console.enabled` | Enable console logging output. | `false` | + > | `logger.transports.console.level` | Log level for console output. | `info` | + > | `logger.transports.amqp.enabled` | Enable AMQP-based logging. | `false` | + > | `logger.transports.amqp.level` | Log level for AMQP transport. | `http` | + > | `logger.transports.amqp.hostname` | Hostname of the AMQP broker. | `localhost` | + > | `logger.transports.amqp.port` | Port for the AMQP broker. | `5672` | + > | `logger.transports.amqp.username` | Username for AMQP authentication. | `guest` | + > | `logger.transports.amqp.password` | Password for AMQP authentication. | `guest` | + > | `logger.transports.amqp.exchange` | Exchange name used for AMQP logging. | `logs` | + > | `logger.transports.amqp.vhost` | Virtual host for AMQP logging. | `/logs` | + > | `logger.transports.amqp.heartbeat` | Heartbeat interval in seconds. | `60` | + > | `logger.transports.amqp.locale` | Locale for the AMQP connection. | `en_US` | + > | `logger.transports.amqp.type` | AMQP exchange type. | `direct` | + > | `logger.transports.amqp.durable` | Whether the AMQP exchange is durable. | `false` | + +3. Start the server + + ```bash + npm start + ``` + +#### Run MCP in Docker + +1. Build docker container + + ```bash + docker build -t copilot-security-mcp . + ``` + +2. Run docker container + + ```bash + docker run -d -p 8080:8080 copilot-security-mcp + ``` + +#### Configuring VSCode for MCP 1. Open VSCode and run the `MCP: Open User Configuration` command. + 2. Add the following JSON configuration: ```json @@ -147,16 +141,18 @@ All variables are optional; the server runs with these defaults. Set them in `.e ``` 3. Save the configuration. + 4. Navigate to the Extensions menu in VSCode. + 5. Locate the `copilot-instructions-mcp` server, click the settings cog, and select `start server`. -#### 3. Using MCP with GitHub Copilot +#### Using MCP with GitHub Copilot + +1. Open GitHub Copilot Chat. -- Open GitHub Copilot Chat. -- Ask it to run any of the prompts against your repository or specific files. -- Example: `Please request and run the secure code review prompt using the MCP server.` +2. Ask it to run any of the prompts against your repository or specific files. -This setup ensures developers can easily leverage the MCP server to enhance their secure coding practices. + **Example:** `Please get and run the secure code review prompt.` --- @@ -180,7 +176,7 @@ Use these npm scripts to work on the project: | `npm run lint` | Runs ESLint and Markdownlint to verify code and docs. | | `npm run lint:fix` | Attempts to automatically fix linting issues. | -**Recommended workflow:** run `npm run lint` (and `npm run lint:fix` if needed) before committing or opening a PR. +**Recommended workflow:** Run `npm run lint` (and `npm run lint:fix` if needed) before committing or opening a PR. --- diff --git a/images/example-chat_prompt_files.png b/images/example-chat_prompt_files.png new file mode 100644 index 0000000000000000000000000000000000000000..ab0879ed9d2973dc48e3fd46ac15059bc3657afc GIT binary patch literal 39161 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 Ws&CTGe~x7!n>}6qT-G@yGywnyYAve( literal 0 HcmV?d00001 diff --git a/images/example-run_prompt.png b/images/example-run_prompt.png new file mode 100644 index 0000000000000000000000000000000000000000..819c9ccc0f722eaccfe35cef47836494e2858b1e GIT binary patch literal 26732 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 bV&UY>5&Ol%uou=dzYmB|(S{c(-GBLC1I}vU literal 0 HcmV?d00001 diff --git a/server.js b/server.js index f86f5ad..03b7c9e 100644 --- a/server.js +++ b/server.js @@ -1,26 +1,66 @@ +import fs from 'fs'; +import path from 'path'; +import https from 'https'; import { config, logger } from 'copilot-instructions-mcp/core'; import app from './src/express_app.js'; -app.listen(config.server.port, (error) => { - if (error) { - logger.error('Error starting server', { - source: 'server.listenHTTP', - details: { - port: config.server.port, - hostname: config.server.hostname, - }, - error: { - message: error.message || 'Unknown error', - stack: error.stack || 'No stack trace available', - }, - }); - } else { - logger.info(`Server listening on port ${config.server.port}`, { - source: 'server.listenHTTP', - details: { - port: config.server.port, - hostname: config.server.hostname, - }, - }); - } -}); +function listenHTTP() { + app.listen(config.server.port, (error) => { + if (error) { + logger.error('Error starting server', { + source: 'server.listenHTTP', + details: { + port: config.server.port, + hostname: config.server.hostname, + }, + error: { + message: error.message || 'Unknown error', + stack: error.stack || 'No stack trace available', + }, + }); + } else { + logger.info(`Server listening on port ${config.server.port}`, { + source: 'server.listenHTTP', + details: { + port: config.server.port, + hostname: config.server.hostname, + }, + }); + } + }); +} + +function listenHTTPS() { + https.createServer({ + pfx: fs.readFileSync(path.resolve(config.server['ssl.pfx'])), + passphrase: config.server['ssl.pfx.passphrase'], + }, app).listen(config.server.port, (error) => { + if (error) { + logger.error('Error starting server', { + source: 'server.listenHTTPS', + details: { + port: config.server.port, + hostname: config.server.hostname, + }, + error: { + message: error.message || 'Unknown error', + stack: error.stack || 'No stack trace available', + }, + }); + } else { + logger.info(`Server listening on port ${config.server.port}`, { + source: 'server.listenHTTPS', + details: { + port: config.server.port, + hostname: config.server.hostname, + }, + }); + } + }); +} + +if (config.server.ssl) { + listenHTTPS(); +} else { + listenHTTP(); +} diff --git a/src/core/config.js b/src/core/config.js index e590ad0..b3897c8 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -5,6 +5,9 @@ dotenv.config({ quiet: true }); const server = { port: process.env['server.port'] ? parseInt(process.env['server.port'], 10) : 8080, hostname: process.env['server.hostname'] || 'localhost', + ssl: process.env['server.ssl'] === 'true' || false, + 'ssl.pfx': process.env['server.ssl.pfx'] || 'localhost.pfx', + 'ssl.pfxPassphrase': process.env['server.ssl.pfxPassphrase'] || 'PFX_PASSPHRASE', }; const logger = { diff --git a/src/express_app.js b/src/express_app.js index 47dfa51..e46cf20 100644 --- a/src/express_app.js +++ b/src/express_app.js @@ -17,6 +17,8 @@ app.get('/', (req, res) => { return res.status(200).send(homeHTML); }); +app.get('/health', (req, res) => res.status(200).send('OK')); + app.get('/mcp', (req, res) => { // TODO: Log request details /** TODO: Implement MCP Server GET Specification diff --git a/src/mcp_server.js b/src/mcp_server.js index 8bd0b47..619f215 100644 --- a/src/mcp_server.js +++ b/src/mcp_server.js @@ -7,10 +7,13 @@ import mcpTools from 'copilot-instructions-mcp/mcp_tools'; function makeMCPServer() { const server = new McpServer({ - name: 'copilot-instructions-mcp', + name: 'copilot-security-mcp', version: '1.0.0', + title: 'Copilot Security Instructions MCP', + }); + // Register Tools mcpTools.list_resources(server); mcpTools.list_prompts(server); mcpTools.get_prompt(server); From cf42c44c04e1778354ab25652435665112331a91 Mon Sep 17 00:00:00 2001 From: Jeymz Simmons Date: Sun, 31 Aug 2025 21:18:32 -0400 Subject: [PATCH 2/2] fix: correct ssl.pfxPassphrase key to ssl.pfx.passphrase in server configuration --- src/core/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config.js b/src/core/config.js index b3897c8..8f84c7b 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -7,7 +7,7 @@ const server = { hostname: process.env['server.hostname'] || 'localhost', ssl: process.env['server.ssl'] === 'true' || false, 'ssl.pfx': process.env['server.ssl.pfx'] || 'localhost.pfx', - 'ssl.pfxPassphrase': process.env['server.ssl.pfxPassphrase'] || 'PFX_PASSPHRASE', + 'ssl.pfx.passphrase': process.env['server.ssl.pfx.passphrase'] || 'PFX_PASSPHRASE', }; const logger = {